Home | History | Annotate | Line # | Download | only in sbus
cs4231_sbus.c revision 1.10
      1  1.10      eeh /*	$NetBSD: cs4231_sbus.c,v 1.10 1999/03/19 02:32:48 eeh Exp $	*/
      2   1.2       pk 
      3   1.2       pk /*-
      4   1.9  mycroft  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
      5   1.2       pk  * All rights reserved.
      6   1.2       pk  *
      7   1.2       pk  * This code is derived from software contributed to The NetBSD Foundation
      8   1.2       pk  * by Paul Kranenburg.
      9   1.2       pk  *
     10   1.2       pk  * Redistribution and use in source and binary forms, with or without
     11   1.2       pk  * modification, are permitted provided that the following conditions
     12   1.2       pk  * are met:
     13   1.2       pk  * 1. Redistributions of source code must retain the above copyright
     14   1.2       pk  *    notice, this list of conditions and the following disclaimer.
     15   1.2       pk  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.2       pk  *    notice, this list of conditions and the following disclaimer in the
     17   1.2       pk  *    documentation and/or other materials provided with the distribution.
     18   1.2       pk  * 3. All advertising materials mentioning features or use of this software
     19   1.2       pk  *    must display the following acknowledgement:
     20   1.2       pk  *        This product includes software developed by the NetBSD
     21   1.2       pk  *        Foundation, Inc. and its contributors.
     22   1.2       pk  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23   1.2       pk  *    contributors may be used to endorse or promote products derived
     24   1.2       pk  *    from this software without specific prior written permission.
     25   1.2       pk  *
     26   1.2       pk  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27   1.2       pk  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28   1.2       pk  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29   1.2       pk  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30   1.2       pk  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31   1.2       pk  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32   1.2       pk  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33   1.2       pk  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34   1.2       pk  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35   1.2       pk  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36   1.2       pk  * POSSIBILITY OF SUCH DAMAGE.
     37   1.2       pk  */
     38   1.1       pk 
     39   1.1       pk #include "audio.h"
     40   1.1       pk #if NAUDIO > 0
     41   1.1       pk 
     42   1.1       pk #include <sys/param.h>
     43   1.1       pk #include <sys/systm.h>
     44   1.1       pk #include <sys/errno.h>
     45   1.1       pk #include <sys/device.h>
     46   1.1       pk #include <sys/malloc.h>
     47   1.1       pk 
     48   1.1       pk #include <machine/autoconf.h>
     49   1.1       pk #include <machine/cpu.h>
     50   1.1       pk 
     51   1.1       pk #include <sys/audioio.h>
     52   1.1       pk #include <dev/audio_if.h>
     53   1.1       pk 
     54   1.1       pk #include <dev/ic/ad1848reg.h>
     55   1.1       pk #include <dev/ic/cs4231reg.h>
     56   1.1       pk #include <dev/ic/ad1848var.h>
     57   1.1       pk 
     58   1.1       pk #if 0
     59   1.1       pk /* XXX- put these elsewhere */
     60   1.1       pk #define SUNAUDIO_MIC_PORT       0
     61   1.1       pk #define SUNAUDIO_SPEAKER	1
     62   1.1       pk #define SUNAUDIO_HEADPHONES     2
     63   1.1       pk #define SUNAUDIO_MONITOR	3
     64   1.1       pk #define SUNAUDIO_SOURCE         4
     65   1.1       pk #define SUNAUDIO_OUTPUT         5
     66   1.1       pk #define SUNAUDIO_INPUT_CLASS    6
     67   1.1       pk #define SUNAUDIO_OUTPUT_CLASS   7
     68   1.1       pk #define SUNAUDIO_RECORD_CLASS   8
     69   1.1       pk #define SUNAUDIO_MONITOR_CLASS  9
     70   1.1       pk #endif
     71   1.1       pk 
     72   1.1       pk /*---*/
     73   1.2       pk #define CSAUDIO_DAC_LVL		0
     74   1.1       pk #define CSAUDIO_LINE_IN_LVL	1
     75   1.1       pk #define CSAUDIO_MONO_LVL	2
     76   1.1       pk #define CSAUDIO_CD_LVL		3
     77   1.1       pk #define CSAUDIO_MONITOR_LVL	4
     78   1.2       pk #define CSAUDIO_OUT_LVL		5
     79   1.1       pk #define CSAUDIO_LINE_IN_MUTE	6
     80   1.1       pk #define CSAUDIO_DAC_MUTE	7
     81   1.2       pk #define CSAUDIO_CD_MUTE		8
     82   1.1       pk #define CSAUDIO_MONO_MUTE	9
     83   1.1       pk #define CSAUDIO_MONITOR_MUTE	10
     84   1.2       pk #define CSAUDIO_REC_LVL		11
     85   1.1       pk #define CSAUDIO_RECORD_SOURCE	12
     86   1.1       pk 
     87   1.2       pk #define CSAUDIO_INPUT_CLASS	13
     88   1.2       pk #define CSAUDIO_OUTPUT_CLASS	14
     89   1.2       pk #define CSAUDIO_RECORD_CLASS	15
     90   1.2       pk #define CSAUDIO_MONITOR_CLASS	16
     91   1.1       pk 
     92   1.2       pk #define AUDIO_ROM_NAME		"SUNW,CS4231"
     93   1.1       pk 
     94   1.1       pk #ifdef AUDIO_DEBUG
     95   1.1       pk int     cs4231debug = 0;
     96   1.2       pk #define DPRINTF(x)      if (cs4231debug) printf x
     97   1.1       pk #else
     98   1.1       pk #define DPRINTF(x)
     99   1.1       pk #endif
    100   1.1       pk 
    101   1.1       pk /*
    102   1.1       pk  * Layout of 4231 registers.
    103   1.1       pk  *
    104   1.1       pk struct cs4231_reg {
    105   1.1       pk 	volatile u_int8_t	iar;		// Index Address Register
    106   1.1       pk 	volatile u_int8_t	pad0[3];
    107   1.1       pk 	volatile u_int8_t	idr;		// Data Register
    108   1.1       pk 	volatile u_int8_t	pad1[3];
    109   1.1       pk 	volatile u_int8_t	status;		// Status Register
    110   1.1       pk 	volatile u_int8_t	pad2[3];
    111   1.1       pk 	volatile u_int8_t	piodr;		// PIO Data Register I/O
    112   1.1       pk 	volatile u_int8_t	pad3[3];
    113   1.1       pk };
    114   1.1       pk */
    115   1.1       pk #define CS4231_REG_SIZE		16
    116   1.1       pk 
    117   1.1       pk 
    118   1.1       pk /*
    119   1.1       pk  * APC DMA hardware; from SunOS header
    120   1.1       pk  * Thanks to Derrick J. Brashear for additional info on the
    121   1.1       pk  * meaning of some of these bits.
    122   1.1       pk  */
    123   1.1       pk struct apc_dma {
    124   1.2       pk 	volatile u_int32_t dmacsr;	/* APC CSR */
    125   1.2       pk 	volatile u_int32_t lpad[3];	/* */
    126   1.2       pk 	volatile u_int32_t dmacva;	/* Capture Virtual Address */
    127   1.2       pk 	volatile u_int32_t dmacc;	/* Capture Count */
    128   1.2       pk 	volatile u_int32_t dmacnva;	/* Capture Next Virtual Address */
    129   1.2       pk 	volatile u_int32_t dmacnc;	/* Capture next count */
    130   1.2       pk 	volatile u_int32_t dmapva;	/* Playback Virtual Address */
    131   1.2       pk 	volatile u_int32_t dmapc;	/* Playback Count */
    132   1.2       pk 	volatile u_int32_t dmapnva;	/* Playback Next VAddress */
    133   1.2       pk 	volatile u_int32_t dmapnc;	/* Playback Next Count */
    134   1.1       pk };
    135   1.1       pk 
    136   1.1       pk /*
    137   1.1       pk  * APC CSR Register bit definitions
    138   1.1       pk  */
    139   1.1       pk #define	APC_IP		0x00800000	/* Interrupt Pending */
    140   1.1       pk #define	APC_PI		0x00400000	/* Playback interrupt */
    141   1.1       pk #define	APC_CI		0x00200000	/* Capture interrupt */
    142   1.1       pk #define	APC_EI		0x00100000	/* General interrupt */
    143   1.1       pk #define	APC_IE		0x00080000	/* General ext int. enable */
    144   1.1       pk #define	APC_PIE		0x00040000	/* Playback ext intr */
    145   1.1       pk #define	APC_CIE		0x00020000	/* Capture ext intr */
    146   1.1       pk #define	APC_EIE		0x00010000	/* Error ext intr */
    147   1.1       pk #define	APC_PMI		0x00008000	/* Pipe empty interrupt */
    148   1.1       pk #define	APC_PM		0x00004000	/* Play pipe empty */
    149   1.1       pk #define	APC_PD		0x00002000	/* Playback NVA dirty */
    150   1.1       pk #define	APC_PMIE	0x00001000	/* play pipe empty Int enable */
    151   1.1       pk #define	APC_CM		0x00000800	/* Cap data dropped on floor */
    152   1.1       pk #define	APC_CD		0x00000400	/* Capture NVA dirty */
    153   1.1       pk #define	APC_CMI		0x00000200	/* Capture pipe empty interrupt */
    154   1.1       pk #define	APC_CMIE	0x00000100	/* Cap. pipe empty int enable */
    155   1.1       pk #define	APC_PPAUSE	0x00000080	/* Pause the play DMA */
    156   1.1       pk #define	APC_CPAUSE	0x00000040	/* Pause the capture DMA */
    157   1.1       pk #define	APC_CODEC_PDN   0x00000020	/* CODEC RESET */
    158   1.1       pk #define	PDMA_GO		0x00000008
    159   1.1       pk #define	CDMA_GO		0x00000004	/* bit 2 of the csr */
    160   1.1       pk #define	APC_RESET	0x00000001	/* Reset the chip */
    161   1.1       pk 
    162   1.1       pk #define APC_BITS					\
    163   1.1       pk 	"\20\30IP\27PI\26CI\25EI\24IE"			\
    164   1.1       pk 	"\23PIE\22CIE\21EIE\20PMI\17PM\16PD\15PMIE"	\
    165   1.1       pk 	"\14CM\13CD\12CMI\11CMIE\10PPAUSE\7CPAUSE\6PDN\4PGO\3CGO"
    166   1.1       pk 
    167   1.1       pk /*
    168   1.1       pk  * To start DMA, you write to dma[cp]nva and dma[cp]nc and set [CP]DMA_GO
    169   1.1       pk  * in dmacsr. dma[cp]va and dma[cp]c, when read, appear to be the live
    170   1.1       pk  * counter as the DMA operation progresses.
    171   1.1       pk  * Supposedly, you get an interrupt with the "dirty" bits (APC_PD,APC_CD)
    172   1.1       pk  * set, when the next DMA buffer can be programmed, while the current one
    173   1.1       pk  * is still in progress. We don't currently use this feature, since I
    174   1.1       pk  * haven't been able to make it work.. instead the next buffer goes in
    175   1.1       pk  * as soon as we see a "pipe empty" (APC_PM) interrupt.
    176   1.1       pk  */
    177   1.1       pk 
    178   1.1       pk /* It's not clear if there's a maximum DMA size.. */
    179   1.1       pk #define APC_MAX		(sc->sc_blksz)/*(16*1024)*/
    180   1.1       pk 
    181   1.1       pk /*
    182   1.1       pk  * List of device memory allocations (see cs4231_malloc/cs4231_free).
    183   1.1       pk  */
    184   1.1       pk struct cs_dma {
    185   1.1       pk 	struct	cs_dma *next;
    186   1.1       pk 	caddr_t	addr;
    187   1.1       pk 	bus_dma_segment_t segs[1];
    188   1.1       pk 	int	nsegs;
    189   1.1       pk 	size_t	size;
    190   1.1       pk };
    191   1.1       pk 
    192   1.1       pk 
    193   1.1       pk /*
    194   1.1       pk  * Software state, per CS4231 audio chip.
    195   1.1       pk  */
    196   1.1       pk struct cs4231_softc {
    197   1.1       pk 	struct ad1848_softc sc_ad1848;	/* base device */
    198   1.1       pk 	struct sbusdev	sc_sd;		/* sbus device */
    199   1.1       pk 	bus_space_tag_t	sc_bustag;
    200   1.1       pk 	bus_dma_tag_t	sc_dmatag;
    201   1.1       pk 	struct evcnt	sc_intrcnt;	/* statistics */
    202   1.1       pk 
    203   1.1       pk 	struct cs_dma	*sc_dmas;
    204   1.1       pk 	struct cs_dma	*sc_nowplaying;	/*XXX*/
    205   1.1       pk 	u_long		sc_playsegsz;	/*XXX*/
    206   1.1       pk 	u_long		sc_playcnt;
    207   1.1       pk 	u_long		sc_blksz;
    208   1.1       pk 
    209   1.1       pk 	int	sc_open;		/* single use device */
    210   1.1       pk 	int	sc_locked;		/* true when transfering data */
    211   1.1       pk 	struct	apc_dma	*sc_dmareg;	/* DMA registers */
    212   1.1       pk 
    213   1.1       pk 	/* interfacing with the interrupt handlers */
    214   1.1       pk 	void	(*sc_rintr)(void*);	/* input completion intr handler */
    215   1.1       pk 	void	*sc_rarg;		/* arg for sc_rintr() */
    216   1.1       pk 	void	(*sc_pintr)(void*);	/* output completion intr handler */
    217   1.1       pk 	void	*sc_parg;		/* arg for sc_pintr() */
    218   1.1       pk };
    219   1.1       pk 
    220   1.1       pk /* autoconfiguration driver */
    221   1.1       pk void	cs4231attach __P((struct device *, struct device *, void *));
    222   1.1       pk int	cs4231match __P((struct device *, struct cfdata *, void *));
    223   1.1       pk 
    224   1.1       pk struct cfattach audiocs_ca = {
    225   1.1       pk 	sizeof(struct cs4231_softc), cs4231match, cs4231attach
    226   1.1       pk };
    227   1.1       pk 
    228   1.1       pk struct audio_device cs4231_device = {
    229   1.1       pk 	"cs4231",
    230   1.1       pk 	"x",
    231   1.1       pk 	"audio"
    232   1.1       pk };
    233   1.1       pk 
    234   1.1       pk 
    235   1.1       pk /*
    236   1.1       pk  * Define our interface to the higher level audio driver.
    237   1.1       pk  */
    238   1.1       pk int	cs4231_open __P((void *, int));
    239   1.1       pk void	cs4231_close __P((void *));
    240   1.8  mycroft size_t	cs4231_round_buffersize __P((void *, int, size_t));
    241   1.1       pk int	cs4231_round_blocksize __P((void *, int));
    242   1.1       pk int	cs4231_halt_output __P((void *));
    243   1.1       pk int	cs4231_halt_input __P((void *));
    244   1.1       pk int	cs4231_getdev __P((void *, struct audio_device *));
    245   1.1       pk int	cs4231_set_port __P((void *, mixer_ctrl_t *));
    246   1.1       pk int	cs4231_get_port __P((void *, mixer_ctrl_t *));
    247   1.1       pk int	cs4231_query_devinfo __P((void *, mixer_devinfo_t *));
    248   1.1       pk int	cs4231_get_props __P((void *));
    249   1.1       pk 
    250   1.8  mycroft void   *cs4231_malloc __P((void *, int, size_t, int, int));
    251   1.1       pk void	cs4231_free __P((void *, void *, int));
    252   1.1       pk int	cs4231_trigger_output __P((void *, void *, void *, int,
    253   1.1       pk 				   void (*)(void *), void *,
    254   1.1       pk 				   struct audio_params *));
    255   1.1       pk int	cs4231_trigger_input __P((void *, void *, void *, int,
    256   1.1       pk 				  void (*)(void *), void *,
    257   1.1       pk 				  struct audio_params *));
    258   1.1       pk 
    259   1.1       pk int	cs4231_intr __P((void *));
    260   1.1       pk void	cs4231_init __P((struct cs4231_softc *));
    261   1.1       pk 
    262   1.3       pk #ifdef AUDIO_DEBUG
    263   1.3       pk static void	cs4231_regdump __P((char *, struct cs4231_softc *));
    264   1.3       pk #endif
    265   1.1       pk 
    266   1.1       pk static int	cs_read __P((struct ad1848_softc *, int));
    267   1.1       pk static void	cs_write __P((struct ad1848_softc *, int, int));
    268   1.1       pk 
    269   1.1       pk static int
    270   1.1       pk cs_read(sc, index)
    271   1.1       pk 	struct ad1848_softc	*sc;
    272   1.1       pk 	int			index;
    273   1.1       pk {
    274  1.10      eeh 	return bus_space_read_1(sc->sc_iot, sc->sc_ioh, (index << 2));
    275   1.1       pk }
    276   1.1       pk 
    277   1.1       pk static void
    278   1.1       pk cs_write(sc, index, value)
    279   1.1       pk 	struct ad1848_softc	*sc;
    280   1.1       pk 	int			index, value;
    281   1.1       pk {
    282  1.10      eeh 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, (index << 2), value);
    283   1.1       pk }
    284   1.1       pk 
    285   1.1       pk static struct audio_hw_if hw_if = {
    286   1.1       pk 	cs4231_open,
    287   1.1       pk 	cs4231_close,
    288   1.1       pk 	0,
    289   1.1       pk 	ad1848_query_encoding,
    290   1.1       pk 	ad1848_set_params,
    291   1.1       pk 	cs4231_round_blocksize,
    292   1.1       pk 	ad1848_commit_settings,
    293   1.1       pk 	0,
    294   1.1       pk 	0,
    295   1.1       pk 	NULL,
    296   1.1       pk 	NULL,
    297   1.1       pk 	cs4231_halt_output,
    298   1.1       pk 	cs4231_halt_input,
    299   1.1       pk 	0,
    300   1.1       pk 	cs4231_getdev,
    301   1.1       pk 	0,
    302   1.1       pk 	cs4231_set_port,
    303   1.1       pk 	cs4231_get_port,
    304   1.1       pk 	cs4231_query_devinfo,
    305   1.1       pk 	cs4231_malloc,
    306   1.1       pk 	cs4231_free,
    307   1.1       pk 	cs4231_round_buffersize,
    308   1.1       pk         0,
    309   1.1       pk 	cs4231_get_props,
    310   1.1       pk 	cs4231_trigger_output,
    311   1.1       pk 	cs4231_trigger_input
    312   1.1       pk };
    313   1.1       pk 
    314   1.1       pk /* autoconfig routines */
    315   1.1       pk 
    316   1.1       pk int
    317   1.1       pk cs4231match(parent, cf, aux)
    318   1.1       pk 	struct device *parent;
    319   1.1       pk 	struct cfdata *cf;
    320   1.1       pk 	void *aux;
    321   1.1       pk {
    322   1.1       pk 	struct sbus_attach_args *sa = aux;
    323   1.1       pk 
    324   1.1       pk 	return (strcmp(AUDIO_ROM_NAME, sa->sa_name) == 0);
    325   1.1       pk }
    326   1.1       pk 
    327   1.1       pk /*
    328   1.1       pk  * Audio chip found.
    329   1.1       pk  */
    330   1.1       pk void
    331   1.1       pk cs4231attach(parent, self, aux)
    332   1.1       pk 	struct device *parent, *self;
    333   1.1       pk 	void *aux;
    334   1.1       pk {
    335   1.1       pk 	struct cs4231_softc *sc = (struct cs4231_softc *)self;
    336   1.1       pk 	struct sbus_attach_args *sa = aux;
    337   1.1       pk 	bus_space_handle_t bh;
    338   1.1       pk 
    339   1.1       pk 	sc->sc_bustag = sa->sa_bustag;
    340   1.1       pk 	sc->sc_dmatag = sa->sa_dmatag;
    341   1.1       pk 
    342   1.1       pk 	sc->sc_ad1848.parent = sc;
    343  1.10      eeh 	sc->sc_ad1848.sc_iot = sc->sc_bustag;
    344   1.1       pk 	sc->sc_ad1848.sc_readreg = cs_read;
    345   1.1       pk 	sc->sc_ad1848.sc_writereg = cs_write;
    346   1.1       pk 
    347   1.1       pk 	/*
    348   1.1       pk 	 * Map my registers in, if they aren't already in virtual
    349   1.1       pk 	 * address space.
    350   1.1       pk 	 */
    351   1.1       pk 	if (sa->sa_npromvaddrs) {
    352   1.1       pk 		bh = (bus_space_handle_t)sa->sa_promvaddrs[0];
    353   1.1       pk 	} else {
    354   1.1       pk 		if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
    355   1.1       pk 				 sa->sa_offset,
    356   1.1       pk 				 sa->sa_size,
    357   1.1       pk 				 BUS_SPACE_MAP_LINEAR,
    358   1.1       pk 				 0, &bh) != 0) {
    359   1.1       pk 			printf("%s @ sbus: cannot map registers\n",
    360   1.1       pk 				self->dv_xname);
    361   1.1       pk 			return;
    362   1.1       pk 		}
    363   1.1       pk 	}
    364   1.1       pk 
    365   1.1       pk 	sc->sc_ad1848.sc_ioh = bh;
    366  1.10      eeh 	sc->sc_dmareg = (struct apc_dma *)(bh + CS4231_REG_SIZE);
    367   1.1       pk 
    368   1.1       pk 	cs4231_init(sc);
    369   1.1       pk 
    370   1.1       pk 	/* Put ad1848 driver in `MODE 2' mode */
    371   1.1       pk 	sc->sc_ad1848.mode = 2;
    372   1.1       pk 	ad1848_attach(&sc->sc_ad1848);
    373   1.1       pk 
    374   1.1       pk 	printf("\n");
    375   1.1       pk 
    376   1.1       pk 	sbus_establish(&sc->sc_sd, &sc->sc_ad1848.sc_dev);
    377   1.1       pk 
    378   1.1       pk 	/* Establish interrupt channel */
    379   1.1       pk 	bus_intr_establish(sa->sa_bustag,
    380   1.1       pk 			   sa->sa_pri, 0,
    381   1.1       pk 			   cs4231_intr, sc);
    382   1.1       pk 
    383   1.1       pk 	evcnt_attach(&sc->sc_ad1848.sc_dev, "intr", &sc->sc_intrcnt);
    384   1.1       pk 	audio_attach_mi(&hw_if, sc, &sc->sc_ad1848.sc_dev);
    385   1.1       pk }
    386   1.1       pk 
    387   1.1       pk 
    388   1.3       pk #ifdef AUDIO_DEBUG
    389   1.1       pk static void
    390   1.1       pk cs4231_regdump(label, sc)
    391   1.1       pk 	char *label;
    392   1.1       pk 	struct cs4231_softc *sc;
    393   1.1       pk {
    394   1.1       pk 	char bits[128];
    395   1.1       pk 	volatile struct apc_dma *dma = sc->sc_dmareg;
    396   1.1       pk 
    397   1.1       pk 	printf("cs4231regdump(%s): regs:", label);
    398  1.10      eeh 	printf("dmapva: 0x%x; ", dma->dmapva);
    399  1.10      eeh 	printf("dmapc: 0x%x; ", dma->dmapc);
    400  1.10      eeh 	printf("dmapnva: 0x%x; ", dma->dmapnva);
    401  1.10      eeh 	printf("dmapnc: 0x%x\n", dma->dmapnc);
    402  1.10      eeh 	printf("dmacva: 0x%x; ", dma->dmacva);
    403  1.10      eeh 	printf("dmacc: 0x%x; ", dma->dmacc);
    404  1.10      eeh 	printf("dmacnva: 0x%x; ", dma->dmacnva);
    405  1.10      eeh 	printf("dmacnc: 0x%x\n", dma->dmacnc);
    406   1.1       pk 
    407   1.1       pk 	printf("apc_dmacsr=%s\n",
    408   1.1       pk 		bitmask_snprintf(dma->dmacsr, APC_BITS, bits, sizeof(bits)) );
    409   1.1       pk 
    410   1.1       pk 	ad1848_dump_regs(&sc->sc_ad1848);
    411   1.1       pk }
    412   1.3       pk #endif
    413   1.1       pk 
    414   1.1       pk void
    415   1.1       pk cs4231_init(sc)
    416   1.1       pk 	register struct cs4231_softc *sc;
    417   1.1       pk {
    418   1.1       pk 	char *buf;
    419   1.1       pk #if 0
    420   1.1       pk 	volatile struct apc_dma *dma = sc->sc_dmareg;
    421   1.1       pk #endif
    422   1.1       pk 	int reg;
    423   1.1       pk 
    424   1.1       pk #if 0
    425   1.1       pk 	dma->dmacsr = APC_CODEC_PDN;
    426   1.1       pk 	delay(20);
    427   1.1       pk 	dma->dmacsr &= ~APC_CODEC_PDN;
    428   1.1       pk #endif
    429   1.1       pk 	/* First, put chip in native mode */
    430   1.1       pk 	reg = ad_read(&sc->sc_ad1848, SP_MISC_INFO);
    431   1.1       pk 	ad_write(&sc->sc_ad1848, SP_MISC_INFO, reg | MODE2);
    432   1.1       pk 
    433   1.1       pk 	/* Read version numbers from I25 */
    434   1.1       pk 	reg = ad_read(&sc->sc_ad1848, CS_VERSION_ID);
    435   1.1       pk 	switch (reg & (CS_VERSION_NUMBER | CS_VERSION_CHIPID)) {
    436   1.1       pk 	case 0xa0:
    437   1.1       pk 		sc->sc_ad1848.chip_name = "CS4231A";
    438   1.1       pk 		break;
    439   1.1       pk 	case 0x80:
    440   1.1       pk 		sc->sc_ad1848.chip_name = "CS4231";
    441   1.1       pk 		break;
    442   1.1       pk 	case 0x82:
    443   1.1       pk 		sc->sc_ad1848.chip_name = "CS4232";
    444   1.1       pk 		break;
    445   1.1       pk 	default:
    446   1.1       pk 		if ((buf = malloc(32, M_TEMP, M_NOWAIT)) != NULL) {
    447   1.1       pk 			sprintf(buf, "unknown rev: %x/%x", reg&0xe, reg&7);
    448   1.1       pk 			sc->sc_ad1848.chip_name = buf;
    449   1.1       pk 		}
    450   1.1       pk 	}
    451   1.1       pk }
    452   1.1       pk 
    453   1.1       pk void *
    454   1.8  mycroft cs4231_malloc(addr, direction, size, pool, flags)
    455   1.1       pk 	void *addr;
    456   1.8  mycroft 	int direction;
    457   1.8  mycroft 	size_t size;
    458   1.8  mycroft 	int pool, flags;
    459   1.1       pk {
    460   1.1       pk 	struct cs4231_softc *sc = addr;
    461   1.1       pk 	struct cs_dma *p;
    462   1.1       pk 	int error;
    463   1.1       pk 
    464   1.1       pk 	p = malloc(sizeof(*p), pool, flags);
    465   1.1       pk 	if (p == NULL)
    466   1.1       pk 		return (NULL);
    467   1.1       pk 
    468   1.1       pk 	p->size = size;
    469   1.1       pk 	error = bus_dmamem_alloc(sc->sc_dmatag, size, 64*1024, 0,
    470   1.1       pk 				 p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
    471   1.1       pk 				 &p->nsegs, BUS_DMA_NOWAIT);
    472   1.1       pk 	if (error) {
    473   1.1       pk 		free(p, pool);
    474   1.1       pk 		return (NULL);
    475   1.1       pk 	}
    476   1.1       pk 
    477   1.1       pk 	error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
    478   1.1       pk 			       &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
    479   1.1       pk 	if (error) {
    480   1.1       pk 		bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
    481   1.1       pk 		free(p, pool);
    482   1.1       pk 		return (NULL);
    483   1.1       pk 	}
    484   1.1       pk 
    485   1.1       pk 	p->next = sc->sc_dmas;
    486   1.1       pk 	sc->sc_dmas = p;
    487   1.1       pk 	return (p->addr);
    488   1.1       pk }
    489   1.1       pk 
    490   1.1       pk void
    491   1.1       pk cs4231_free(addr, ptr, pool)
    492   1.1       pk 	void *addr;
    493   1.1       pk 	void *ptr;
    494   1.1       pk 	int pool;
    495   1.1       pk {
    496   1.1       pk 	struct cs4231_softc *sc = addr;
    497   1.1       pk 	struct cs_dma *p, **pp;
    498   1.1       pk 
    499   1.1       pk 	for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &(*pp)->next) {
    500   1.1       pk 		if (p->addr != ptr)
    501   1.1       pk 			continue;
    502   1.1       pk 		bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
    503   1.1       pk 		bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
    504   1.1       pk 		*pp = p->next;
    505   1.1       pk 		free(p, pool);
    506   1.1       pk 		return;
    507   1.1       pk 	}
    508   1.1       pk 	printf("cs4231_free: rogue pointer\n");
    509   1.1       pk }
    510   1.1       pk 
    511   1.1       pk int
    512   1.1       pk cs4231_open(addr, flags)
    513   1.1       pk 	void *addr;
    514   1.1       pk 	int flags;
    515   1.1       pk {
    516   1.1       pk 	struct cs4231_softc *sc = addr;
    517   1.1       pk #if 0
    518   1.1       pk 	struct apc_dma *dma = sc->sc_dmareg;
    519   1.1       pk #endif
    520   1.1       pk 
    521   1.1       pk 	DPRINTF(("sa_open: unit %p\n", sc));
    522   1.1       pk 
    523   1.1       pk 	if (sc->sc_open)
    524   1.1       pk 		return (EBUSY);
    525   1.1       pk 	sc->sc_open = 1;
    526   1.1       pk 	sc->sc_locked = 0;
    527   1.1       pk 	sc->sc_rintr = 0;
    528   1.1       pk 	sc->sc_rarg = 0;
    529   1.1       pk 	sc->sc_pintr = 0;
    530   1.1       pk 	sc->sc_parg = 0;
    531   1.1       pk #if 1
    532   1.1       pk 	/*No interrupts from ad1848 */
    533   1.1       pk 	ad_write(&sc->sc_ad1848, SP_PIN_CONTROL, 0);
    534   1.1       pk #endif
    535   1.1       pk #if 0
    536   1.1       pk 	dma->dmacsr = APC_RESET;
    537   1.1       pk 	delay(10);
    538   1.1       pk 	dma->dmacsr = 0;
    539   1.1       pk 	delay(10);
    540   1.1       pk 	ad1848_reset(&sc->sc_ad1848);
    541   1.1       pk #endif
    542   1.1       pk 
    543   1.1       pk 	DPRINTF(("saopen: ok -> sc=%p\n", sc));
    544   1.1       pk 	return (0);
    545   1.1       pk }
    546   1.1       pk 
    547   1.1       pk void
    548   1.1       pk cs4231_close(addr)
    549   1.1       pk 	void *addr;
    550   1.1       pk {
    551   1.1       pk 	register struct cs4231_softc *sc = addr;
    552   1.1       pk 
    553   1.1       pk 	DPRINTF(("sa_close: sc=%p\n", sc));
    554   1.1       pk 	/*
    555   1.1       pk 	 * halt i/o, clear open flag, and done.
    556   1.1       pk 	 */
    557   1.1       pk 	cs4231_halt_input(sc);
    558   1.1       pk 	cs4231_halt_output(sc);
    559   1.1       pk 	sc->sc_open = 0;
    560   1.1       pk 
    561   1.1       pk 	DPRINTF(("sa_close: closed.\n"));
    562   1.1       pk }
    563   1.1       pk 
    564   1.8  mycroft size_t
    565   1.8  mycroft cs4231_round_buffersize(addr, direction, size)
    566   1.1       pk 	void *addr;
    567   1.8  mycroft 	int direction;
    568   1.8  mycroft 	size_t size;
    569   1.1       pk {
    570   1.1       pk #if 0
    571   1.1       pk 	if (size > APC_MAX)
    572   1.1       pk 		size = APC_MAX;
    573   1.1       pk #endif
    574   1.1       pk 	return (size);
    575   1.1       pk }
    576   1.1       pk 
    577   1.1       pk int
    578   1.1       pk cs4231_round_blocksize(addr, blk)
    579   1.1       pk 	void *addr;
    580   1.1       pk 	int blk;
    581   1.1       pk {
    582   1.1       pk 	return (blk & -4);
    583   1.1       pk }
    584   1.1       pk 
    585   1.1       pk int
    586   1.1       pk cs4231_getdev(addr, retp)
    587   1.1       pk         void *addr;
    588   1.1       pk         struct audio_device *retp;
    589   1.1       pk {
    590   1.1       pk         *retp = cs4231_device;
    591   1.1       pk         return (0);
    592   1.1       pk }
    593   1.1       pk 
    594   1.1       pk static ad1848_devmap_t csmapping[] = {
    595   1.1       pk 	{ CSAUDIO_DAC_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
    596   1.1       pk 	{ CSAUDIO_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL },
    597   1.1       pk 	{ CSAUDIO_MONO_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
    598   1.1       pk 	{ CSAUDIO_CD_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
    599   1.1       pk 	{ CSAUDIO_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL },
    600   1.1       pk 	{ CSAUDIO_OUT_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
    601   1.1       pk 	{ CSAUDIO_DAC_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
    602   1.1       pk 	{ CSAUDIO_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL },
    603   1.1       pk 	{ CSAUDIO_MONO_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL },
    604   1.1       pk 	{ CSAUDIO_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
    605   1.1       pk 	{ CSAUDIO_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL },
    606   1.1       pk 	{ CSAUDIO_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
    607   1.1       pk 	{ CSAUDIO_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1 }
    608   1.1       pk };
    609   1.1       pk 
    610   1.1       pk static int nummap = sizeof(csmapping) / sizeof(csmapping[0]);
    611   1.1       pk 
    612   1.1       pk 
    613   1.1       pk int
    614   1.1       pk cs4231_set_port(addr, cp)
    615   1.1       pk 	void *addr;
    616   1.1       pk 	mixer_ctrl_t *cp;
    617   1.1       pk {
    618   1.1       pk 	struct ad1848_softc *ac = addr;
    619   1.1       pk 
    620   1.1       pk 	DPRINTF(("cs4231_set_port: port=%d", cp->dev));
    621   1.6       pk 	return (ad1848_mixer_set_port(ac, csmapping, nummap, cp));
    622   1.1       pk }
    623   1.1       pk 
    624   1.1       pk int
    625   1.1       pk cs4231_get_port(addr, cp)
    626   1.1       pk 	void *addr;
    627   1.1       pk 	mixer_ctrl_t *cp;
    628   1.1       pk {
    629   1.1       pk 	struct ad1848_softc *ac = addr;
    630   1.1       pk 
    631   1.1       pk 	DPRINTF(("cs4231_get_port: port=%d", cp->dev));
    632   1.1       pk 	return (ad1848_mixer_get_port(ac, csmapping, nummap, cp));
    633   1.1       pk }
    634   1.1       pk 
    635   1.1       pk int
    636   1.1       pk cs4231_get_props(addr)
    637   1.1       pk 	void *addr;
    638   1.1       pk {
    639   1.1       pk 	return (AUDIO_PROP_FULLDUPLEX);
    640   1.1       pk }
    641   1.1       pk 
    642   1.1       pk int
    643   1.1       pk cs4231_query_devinfo(addr, dip)
    644   1.1       pk 	void *addr;
    645   1.1       pk 	register mixer_devinfo_t *dip;
    646   1.1       pk {
    647   1.1       pk 
    648   1.1       pk 	switch(dip->index) {
    649   1.1       pk #if 0
    650   1.1       pk 	case CSAUDIO_MIC_IN_LVL:	/* Microphone */
    651   1.1       pk 		dip->type = AUDIO_MIXER_VALUE;
    652   1.1       pk 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
    653   1.1       pk 		dip->prev = AUDIO_MIXER_LAST;
    654   1.1       pk 		dip->next = CSAUDIO_MIC_IN_MUTE;
    655   1.1       pk 		strcpy(dip->label.name, AudioNmicrophone);
    656   1.1       pk 		dip->un.v.num_channels = 2;
    657   1.1       pk 		strcpy(dip->un.v.units.name, AudioNvolume);
    658   1.1       pk 		break;
    659   1.1       pk #endif
    660   1.1       pk 
    661   1.1       pk 	case CSAUDIO_MONO_LVL:	/* mono/microphone mixer */
    662   1.1       pk 		dip->type = AUDIO_MIXER_VALUE;
    663   1.1       pk 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
    664   1.1       pk 		dip->prev = AUDIO_MIXER_LAST;
    665   1.1       pk 		dip->next = CSAUDIO_MONO_MUTE;
    666   1.1       pk 		strcpy(dip->label.name, AudioNmicrophone);
    667   1.1       pk 		dip->un.v.num_channels = 1;
    668   1.1       pk 		strcpy(dip->un.v.units.name, AudioNvolume);
    669   1.1       pk 		break;
    670   1.1       pk 
    671   1.1       pk 	case CSAUDIO_DAC_LVL:		/*  dacout */
    672   1.1       pk 		dip->type = AUDIO_MIXER_VALUE;
    673   1.1       pk 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
    674   1.1       pk 		dip->prev = AUDIO_MIXER_LAST;
    675   1.1       pk 		dip->next = CSAUDIO_DAC_MUTE;
    676   1.1       pk 		strcpy(dip->label.name, AudioNdac);
    677   1.1       pk 		dip->un.v.num_channels = 2;
    678   1.1       pk 		strcpy(dip->un.v.units.name, AudioNvolume);
    679   1.1       pk 		break;
    680   1.1       pk 
    681   1.1       pk 	case CSAUDIO_LINE_IN_LVL:	/* line */
    682   1.1       pk 		dip->type = AUDIO_MIXER_VALUE;
    683   1.1       pk 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
    684   1.1       pk 		dip->prev = AUDIO_MIXER_LAST;
    685   1.1       pk 		dip->next = CSAUDIO_LINE_IN_MUTE;
    686   1.1       pk 		strcpy(dip->label.name, AudioNline);
    687   1.1       pk 		dip->un.v.num_channels = 2;
    688   1.1       pk 		strcpy(dip->un.v.units.name, AudioNvolume);
    689   1.1       pk 		break;
    690   1.1       pk 
    691   1.1       pk 	case CSAUDIO_CD_LVL:		/* cd */
    692   1.1       pk 		dip->type = AUDIO_MIXER_VALUE;
    693   1.1       pk 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
    694   1.1       pk 		dip->prev = AUDIO_MIXER_LAST;
    695   1.1       pk 		dip->next = CSAUDIO_CD_MUTE;
    696   1.1       pk 		strcpy(dip->label.name, AudioNcd);
    697   1.1       pk 		dip->un.v.num_channels = 2;
    698   1.1       pk 		strcpy(dip->un.v.units.name, AudioNvolume);
    699   1.1       pk 		break;
    700   1.1       pk 
    701   1.1       pk 
    702   1.1       pk 	case CSAUDIO_MONITOR_LVL:	/* monitor level */
    703   1.1       pk 		dip->type = AUDIO_MIXER_VALUE;
    704   1.1       pk 		dip->mixer_class = CSAUDIO_MONITOR_CLASS;
    705   1.1       pk 		dip->next = CSAUDIO_MONITOR_MUTE;
    706   1.1       pk 		dip->prev = AUDIO_MIXER_LAST;
    707   1.1       pk 		strcpy(dip->label.name, AudioNmonitor);
    708   1.1       pk 		dip->un.v.num_channels = 1;
    709   1.1       pk 		strcpy(dip->un.v.units.name, AudioNvolume);
    710   1.1       pk 		break;
    711   1.1       pk 
    712   1.1       pk 	case CSAUDIO_OUT_LVL:		/* cs4231 output volume: not useful? */
    713   1.1       pk 		dip->type = AUDIO_MIXER_VALUE;
    714   1.1       pk 		dip->mixer_class = CSAUDIO_MONITOR_CLASS;
    715   1.1       pk 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    716   1.1       pk 		strcpy(dip->label.name, AudioNoutput);
    717   1.1       pk 		dip->un.v.num_channels = 2;
    718   1.1       pk 		strcpy(dip->un.v.units.name, AudioNvolume);
    719   1.1       pk 		break;
    720   1.1       pk 
    721   1.1       pk 	case CSAUDIO_LINE_IN_MUTE:
    722   1.1       pk 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
    723   1.1       pk 		dip->type = AUDIO_MIXER_ENUM;
    724   1.1       pk 		dip->prev = CSAUDIO_LINE_IN_LVL;
    725   1.1       pk 		dip->next = AUDIO_MIXER_LAST;
    726   1.1       pk 		goto mute;
    727   1.1       pk 
    728   1.1       pk 	case CSAUDIO_DAC_MUTE:
    729   1.1       pk 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
    730   1.1       pk 		dip->type = AUDIO_MIXER_ENUM;
    731   1.1       pk 		dip->prev = CSAUDIO_DAC_LVL;
    732   1.1       pk 		dip->next = AUDIO_MIXER_LAST;
    733   1.1       pk 		goto mute;
    734   1.1       pk 
    735   1.1       pk 	case CSAUDIO_CD_MUTE:
    736   1.1       pk 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
    737   1.1       pk 		dip->type = AUDIO_MIXER_ENUM;
    738   1.1       pk 		dip->prev = CSAUDIO_CD_LVL;
    739   1.1       pk 		dip->next = AUDIO_MIXER_LAST;
    740   1.1       pk 		goto mute;
    741   1.1       pk 
    742   1.1       pk 	case CSAUDIO_MONO_MUTE:
    743   1.1       pk 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
    744   1.1       pk 		dip->type = AUDIO_MIXER_ENUM;
    745   1.1       pk 		dip->prev = CSAUDIO_MONO_LVL;
    746   1.1       pk 		dip->next = AUDIO_MIXER_LAST;
    747   1.1       pk 		goto mute;
    748   1.1       pk 
    749   1.1       pk 	case CSAUDIO_MONITOR_MUTE:
    750   1.1       pk 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
    751   1.1       pk 		dip->type = AUDIO_MIXER_ENUM;
    752   1.1       pk 		dip->prev = CSAUDIO_MONITOR_LVL;
    753   1.1       pk 		dip->next = AUDIO_MIXER_LAST;
    754   1.1       pk 	mute:
    755   1.1       pk 		strcpy(dip->label.name, AudioNmute);
    756   1.1       pk 		dip->un.e.num_mem = 2;
    757   1.1       pk 		strcpy(dip->un.e.member[0].label.name, AudioNoff);
    758   1.1       pk 		dip->un.e.member[0].ord = 0;
    759   1.1       pk 		strcpy(dip->un.e.member[1].label.name, AudioNon);
    760   1.1       pk 		dip->un.e.member[1].ord = 1;
    761   1.1       pk 		break;
    762   1.1       pk 
    763   1.1       pk 	case CSAUDIO_REC_LVL:	/* record level */
    764   1.1       pk 		dip->type = AUDIO_MIXER_VALUE;
    765   1.1       pk 		dip->mixer_class = CSAUDIO_RECORD_CLASS;
    766   1.1       pk 		dip->prev = AUDIO_MIXER_LAST;
    767   1.1       pk 		dip->next = CSAUDIO_RECORD_SOURCE;
    768   1.1       pk 		strcpy(dip->label.name, AudioNrecord);
    769   1.1       pk 		dip->un.v.num_channels = 2;
    770   1.1       pk 		strcpy(dip->un.v.units.name, AudioNvolume);
    771   1.1       pk 		break;
    772   1.1       pk 
    773   1.1       pk 	case CSAUDIO_RECORD_SOURCE:
    774   1.1       pk 		dip->mixer_class = CSAUDIO_RECORD_CLASS;
    775   1.1       pk 		dip->type = AUDIO_MIXER_ENUM;
    776   1.1       pk 		dip->prev = CSAUDIO_REC_LVL;
    777   1.1       pk 		dip->next = AUDIO_MIXER_LAST;
    778   1.1       pk 		strcpy(dip->label.name, AudioNsource);
    779   1.1       pk 		dip->un.e.num_mem = 4;
    780   1.1       pk 		strcpy(dip->un.e.member[0].label.name, AudioNoutput);
    781   1.1       pk 		dip->un.e.member[0].ord = DAC_IN_PORT;
    782   1.1       pk 		strcpy(dip->un.e.member[1].label.name, AudioNmicrophone);
    783   1.1       pk 		dip->un.e.member[1].ord = MIC_IN_PORT;
    784   1.1       pk 		strcpy(dip->un.e.member[2].label.name, AudioNdac);
    785   1.1       pk 		dip->un.e.member[2].ord = AUX1_IN_PORT;
    786   1.1       pk 		strcpy(dip->un.e.member[3].label.name, AudioNline);
    787   1.1       pk 		dip->un.e.member[3].ord = LINE_IN_PORT;
    788   1.1       pk 		break;
    789   1.1       pk 
    790   1.1       pk 	case CSAUDIO_INPUT_CLASS:		/* input class descriptor */
    791   1.1       pk 		dip->type = AUDIO_MIXER_CLASS;
    792   1.1       pk 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
    793   1.1       pk 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    794   1.1       pk 		strcpy(dip->label.name, AudioCinputs);
    795   1.1       pk 		break;
    796   1.1       pk 
    797   1.1       pk 	case CSAUDIO_OUTPUT_CLASS:		/* output class descriptor */
    798   1.1       pk 		dip->type = AUDIO_MIXER_CLASS;
    799   1.1       pk 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
    800   1.1       pk 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    801   1.1       pk 		strcpy(dip->label.name, AudioCoutputs);
    802   1.1       pk 		break;
    803   1.1       pk 
    804   1.1       pk 	case CSAUDIO_MONITOR_CLASS:		/* monitor class descriptor */
    805   1.1       pk 		dip->type = AUDIO_MIXER_CLASS;
    806   1.1       pk 		dip->mixer_class = CSAUDIO_MONITOR_CLASS;
    807   1.1       pk 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    808   1.1       pk 		strcpy(dip->label.name, AudioCmonitor);
    809   1.1       pk 		break;
    810   1.1       pk 
    811   1.1       pk 	case CSAUDIO_RECORD_CLASS:		/* record source class */
    812   1.1       pk 		dip->type = AUDIO_MIXER_CLASS;
    813   1.1       pk 		dip->mixer_class = CSAUDIO_RECORD_CLASS;
    814   1.1       pk 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    815   1.1       pk 		strcpy(dip->label.name, AudioCrecord);
    816   1.1       pk 		break;
    817   1.1       pk 
    818   1.1       pk 	default:
    819   1.1       pk 		return ENXIO;
    820   1.1       pk 		/*NOTREACHED*/
    821   1.1       pk 	}
    822   1.1       pk 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    823   1.1       pk 
    824   1.1       pk 	return (0);
    825   1.1       pk }
    826   1.1       pk 
    827   1.1       pk 
    828   1.1       pk int
    829   1.1       pk cs4231_trigger_output(addr, start, end, blksize, intr, arg, param)
    830   1.1       pk 	void *addr;
    831   1.1       pk 	void *start, *end;
    832   1.1       pk 	int blksize;
    833   1.1       pk 	void (*intr) __P((void *));
    834   1.1       pk 	void *arg;
    835   1.1       pk 	struct audio_params *param;
    836   1.1       pk {
    837   1.1       pk 	struct cs4231_softc *sc = addr;
    838   1.1       pk 	struct cs_dma *p;
    839   1.1       pk 	volatile struct apc_dma *dma = sc->sc_dmareg;
    840   1.1       pk 	int csr;
    841  1.10      eeh 	vsize_t n;
    842   1.1       pk 
    843   1.1       pk 	if (sc->sc_locked != 0) {
    844   1.1       pk 		printf("cs4231_trigger_output: already running\n");
    845   1.1       pk 		return (EINVAL);
    846   1.1       pk 	}
    847   1.1       pk 
    848   1.1       pk 	sc->sc_locked = 1;
    849   1.1       pk 	sc->sc_pintr = intr;
    850   1.1       pk 	sc->sc_parg = arg;
    851   1.1       pk 
    852   1.1       pk 	for (p = sc->sc_dmas; p != NULL && p->addr != start; p = p->next)
    853   1.1       pk 		/*void*/;
    854   1.1       pk 	if (p == NULL) {
    855   1.1       pk 		printf("cs4231_trigger_output: bad addr %p\n", start);
    856   1.1       pk 		return (EINVAL);
    857   1.1       pk 	}
    858   1.1       pk 
    859   1.7   kleink 	n = (char *)end - (char *)start;
    860   1.1       pk 
    861   1.1       pk 	/* XXX
    862   1.1       pk 	 * Do only `blksize' at a time, so audio_pint() is kept
    863   1.1       pk 	 * synchronous with us...
    864   1.1       pk 	 */
    865   1.1       pk 	/*XXX*/sc->sc_blksz = blksize;
    866   1.1       pk 	/*XXX*/sc->sc_nowplaying = p;
    867   1.1       pk 	/*XXX*/sc->sc_playsegsz = n;
    868   1.1       pk 
    869   1.1       pk 	if (n > APC_MAX)
    870   1.1       pk 		n = APC_MAX;
    871   1.1       pk 
    872   1.1       pk 	sc->sc_playcnt = n;
    873   1.1       pk 
    874   1.1       pk 	DPRINTF(("trigger_out: start %p, end %p, size %lu; "
    875   1.1       pk 		 "dmaaddr 0x%lx, dmacnt %lu, segsize %lu\n",
    876  1.10      eeh 		 start, end, (u_long)sc->sc_playsegsz,
    877  1.10      eeh 		 (u_long)p->segs[0].ds_addr,
    878  1.10      eeh 		 (u_long)n, (u_long)p->size));
    879   1.1       pk 
    880   1.1       pk 	csr = dma->dmacsr;
    881   1.1       pk 	dma->dmapnva = (u_long)p->segs[0].ds_addr;
    882  1.10      eeh 	dma->dmapnc = (u_long)n;
    883   1.1       pk 	if ((csr & PDMA_GO) == 0 || (csr & APC_PPAUSE) != 0) {
    884   1.1       pk 		int reg;
    885   1.1       pk 
    886   1.1       pk 		dma->dmacsr &= ~(APC_PIE|APC_PPAUSE);
    887   1.1       pk 		dma->dmacsr |= APC_EI|APC_IE|APC_PIE|APC_EIE|APC_PMIE|PDMA_GO;
    888   1.1       pk 
    889   1.1       pk 		/* Start chip */
    890   1.1       pk 
    891   1.1       pk 		/* Probably should just ignore this.. */
    892   1.1       pk 		ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff);
    893   1.1       pk 		ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff);
    894   1.1       pk 
    895   1.1       pk 		reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
    896   1.1       pk 		ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,
    897   1.1       pk 			 (PLAYBACK_ENABLE|reg));
    898   1.1       pk 	}
    899   1.1       pk 
    900   1.1       pk 	return (0);
    901   1.1       pk }
    902   1.1       pk 
    903   1.1       pk int
    904   1.1       pk cs4231_trigger_input(addr, start, end, blksize, intr, arg, param)
    905   1.1       pk 	void *addr;
    906   1.1       pk 	void *start, *end;
    907   1.1       pk 	int blksize;
    908   1.1       pk 	void (*intr) __P((void *));
    909   1.1       pk 	void *arg;
    910   1.1       pk 	struct audio_params *param;
    911   1.1       pk {
    912   1.1       pk 	return (ENXIO);
    913   1.1       pk }
    914   1.1       pk 
    915   1.1       pk int
    916   1.1       pk cs4231_halt_output(addr)
    917   1.1       pk 	void *addr;
    918   1.1       pk {
    919   1.1       pk 	struct cs4231_softc *sc = addr;
    920   1.1       pk 	volatile struct apc_dma *dma = sc->sc_dmareg;
    921   1.1       pk 	int reg;
    922   1.1       pk 
    923   1.1       pk 	dma->dmacsr &= ~(APC_EI | APC_IE | APC_PIE | APC_EIE | PDMA_GO | APC_PMIE);
    924   1.1       pk 	reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
    925   1.1       pk 	ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (reg & ~PLAYBACK_ENABLE));
    926   1.1       pk 	sc->sc_locked = 0;
    927   1.1       pk 
    928   1.1       pk 	return (0);
    929   1.1       pk }
    930   1.1       pk 
    931   1.1       pk int
    932   1.1       pk cs4231_halt_input(addr)
    933   1.1       pk 	void *addr;
    934   1.1       pk {
    935   1.1       pk 	struct cs4231_softc *sc = addr;
    936   1.1       pk 	int reg;
    937   1.1       pk 
    938   1.1       pk 	reg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG);
    939   1.1       pk 	ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (reg & ~CAPTURE_ENABLE));
    940   1.1       pk 	sc->sc_locked = 0;
    941   1.1       pk 
    942   1.1       pk 	return (0);
    943   1.1       pk }
    944   1.1       pk 
    945   1.1       pk 
    946   1.1       pk int
    947   1.1       pk cs4231_intr(arg)
    948   1.1       pk 	void *arg;
    949   1.1       pk {
    950   1.1       pk 	struct cs4231_softc *sc = arg;
    951   1.1       pk 	volatile struct apc_dma *dma = sc->sc_dmareg;
    952   1.1       pk 	struct cs_dma *p;
    953   1.1       pk 	int ret = 0;
    954   1.1       pk 	int csr;
    955   1.1       pk 	int reg, status;
    956   1.5       pk #if defined(DEBUG) || defined(AUDIO_DEBUG)
    957   1.1       pk 	char bits[128];
    958   1.3       pk #endif
    959   1.1       pk 
    960   1.1       pk #ifdef AUDIO_DEBUG
    961   1.1       pk 	if (cs4231debug > 1)
    962   1.1       pk 		cs4231_regdump("audiointr", sc);
    963   1.1       pk #endif
    964   1.1       pk 
    965   1.1       pk 	/* Read DMA status */
    966   1.1       pk 	csr = dma->dmacsr;
    967   1.1       pk 	DPRINTF((
    968   1.1       pk 	    "intr: csr=%s; dmapva=0x%lx,dmapc=%lu;dmapnva=0x%lx,dmapnc=%lu\n",
    969   1.1       pk 		bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits)),
    970   1.2       pk 		(u_long)dma->dmapva, (u_long)dma->dmapc,
    971   1.2       pk 		(u_long)dma->dmapnva, (u_long)dma->dmapnc));
    972   1.1       pk 
    973   1.1       pk 	status = ADREAD(&sc->sc_ad1848, AD1848_STATUS);
    974   1.1       pk 	DPRINTF(("%s: status: %s\n", sc->sc_ad1848.sc_dev.dv_xname,
    975   1.1       pk 		bitmask_snprintf(status, AD_R2_BITS, bits, sizeof(bits))));
    976   1.1       pk 	if (status & (INTERRUPT_STATUS | SAMPLE_ERROR)) {
    977   1.1       pk 		reg = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS);
    978   1.1       pk 		DPRINTF(("%s: i24: %s\n", sc->sc_ad1848.sc_dev.dv_xname,
    979   1.1       pk 		       bitmask_snprintf(reg, CS_I24_BITS, bits, sizeof(bits))));
    980   1.1       pk 
    981   1.1       pk 		if (reg & CS_IRQ_PI) {
    982   1.1       pk 			ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff);
    983   1.1       pk 			ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff);
    984   1.1       pk 		}
    985   1.1       pk 		/* Clear interrupt bit */
    986   1.1       pk 		ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0);
    987   1.1       pk 	}
    988   1.1       pk 
    989   1.1       pk 	/* Write back DMA status (clears interrupt) */
    990   1.1       pk 	dma->dmacsr = csr;
    991   1.1       pk 
    992   1.1       pk 	/*
    993   1.1       pk 	 * Simplistic.. if "play emtpy" is set advance to next chunk.
    994   1.1       pk 	 */
    995   1.1       pk #if 1
    996   1.1       pk 	/* Ack all play interrupts*/
    997   1.1       pk 	if ((csr & (APC_PI|APC_PD|APC_PIE|APC_PMI)) != 0)
    998   1.1       pk 		ret = 1;
    999   1.1       pk #endif
   1000   1.1       pk 	if (csr & APC_PM) {
   1001   1.1       pk 		u_long nextaddr, togo;
   1002   1.1       pk 
   1003   1.1       pk 		p = sc->sc_nowplaying;
   1004   1.1       pk 
   1005   1.1       pk 		togo = sc->sc_playsegsz - sc->sc_playcnt;
   1006   1.1       pk 		if (togo == 0) {
   1007   1.1       pk 			/* Roll over */
   1008   1.1       pk 			nextaddr = (u_long)p->segs[0].ds_addr;
   1009   1.1       pk 			sc->sc_playcnt = togo = APC_MAX;
   1010   1.1       pk 		} else {
   1011   1.1       pk 			nextaddr = dma->dmapnva + APC_MAX;
   1012   1.1       pk 			if (togo > APC_MAX)
   1013   1.1       pk 				togo = APC_MAX;
   1014   1.1       pk 			sc->sc_playcnt += togo;
   1015   1.1       pk 		}
   1016   1.1       pk 
   1017   1.1       pk 		dma->dmapnva = nextaddr;
   1018   1.1       pk 		dma->dmapnc = togo;
   1019   1.1       pk 
   1020   1.1       pk 		if (sc->sc_pintr != NULL)
   1021   1.1       pk 			(*sc->sc_pintr)(sc->sc_parg);
   1022   1.1       pk 
   1023   1.1       pk 		ret = 1;
   1024   1.1       pk 	}
   1025   1.1       pk 
   1026   1.1       pk 	if (csr & APC_CI) {
   1027   1.1       pk 		if (sc->sc_rintr != NULL) {
   1028   1.1       pk 			ret = 1;
   1029   1.1       pk 			(*sc->sc_rintr)(sc->sc_rarg);
   1030   1.1       pk 		}
   1031   1.1       pk 	}
   1032   1.1       pk 
   1033   1.1       pk #ifdef DEBUG
   1034   1.1       pk if (ret == 0) {
   1035   1.1       pk 	printf(
   1036   1.1       pk 	    "oops: csr=%s; dmapva=0x%lx,dmapc=%lu;dmapnva=0x%lx,dmapnc=%lu\n",
   1037   1.1       pk 		bitmask_snprintf(csr, APC_BITS, bits, sizeof(bits)),
   1038   1.2       pk 		(u_long)dma->dmapva, (u_long)dma->dmapc,
   1039   1.2       pk 		(u_long)dma->dmapnva, (u_long)dma->dmapnc);
   1040   1.1       pk 	ret = 1;
   1041   1.1       pk }
   1042   1.1       pk #endif
   1043   1.1       pk 
   1044   1.1       pk 	return (ret);
   1045   1.1       pk }
   1046   1.1       pk #endif /* NAUDIO > 0 */
   1047