171901Sscottl/*- 271901Sscottl * Copyright (c) 2001 Scott Long <scottl@freebsd.org> 371901Sscottl * Copyright (c) 2001 Darrell Anderson <anderson@cs.duke.edu> 471901Sscottl * All rights reserved. 571901Sscottl * 671901Sscottl * Redistribution and use in source and binary forms, with or without 771901Sscottl * modification, are permitted provided that the following conditions 871901Sscottl * are met: 971901Sscottl * 1. Redistributions of source code must retain the above copyright 1071901Sscottl * notice, this list of conditions and the following disclaimer. 1171901Sscottl * 2. Redistributions in binary form must reproduce the above copyright 1271901Sscottl * notice, this list of conditions and the following disclaimer in the 1371901Sscottl * documentation and/or other materials provided with the distribution. 1471901Sscottl * 1571901Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1671901Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1771901Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1871901Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1971901Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2071901Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2171901Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2271901Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2371901Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2471901Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2571901Sscottl * SUCH DAMAGE. 2671901Sscottl */ 2771901Sscottl 2871901Sscottl/* 2971901Sscottl * Maestro-3/Allegro FreeBSD pcm sound driver 3071901Sscottl * 3171901Sscottl * executive status summary: 3271901Sscottl * (+) /dev/dsp multiple concurrent play channels. 3371901Sscottl * (+) /dev/dsp config (speed, mono/stereo, 8/16 bit). 3471901Sscottl * (+) /dev/mixer sets left/right volumes. 3571901Sscottl * (+) /dev/dsp recording works. Tested successfully with the cdrom channel 3671901Sscottl * (+) apm suspend/resume works, and works properly!. 3771901Sscottl * (-) hardware volme controls don't work =-( 3871901Sscottl * (-) setblocksize() does nothing. 3971901Sscottl * 4071901Sscottl * The real credit goes to: 4171901Sscottl * 4271901Sscottl * Zach Brown for his Linux driver core and helpful technical comments. 4371901Sscottl * <zab@zabbo.net>, http://www.zabbo.net/maestro3 4471901Sscottl * 4571901Sscottl * Cameron Grant created the pcm framework used here nearly verbatim. 4671901Sscottl * <cg@freebsd.org>, http://people.freebsd.org/~cg/template.c 4771901Sscottl * 4871901Sscottl * Taku YAMAMOTO for his Maestro-1/2 FreeBSD driver and sanity reference. 4971901Sscottl * <taku@cent.saitama-u.ac.jp> 5074797Scg * 5171901Sscottl * ESS docs explained a few magic registers and numbers. 5274797Scg * http://virgo.caltech.edu/~dmoore/maestro3.pdf.gz 5371901Sscottl */ 5471901Sscottl 55193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS 56193640Sariff#include "opt_snd.h" 57193640Sariff#endif 58193640Sariff 5971901Sscottl#include <dev/sound/pcm/sound.h> 6071901Sscottl#include <dev/sound/pcm/ac97.h> 6171901Sscottl 62119287Simp#include <dev/pci/pcireg.h> 63119287Simp#include <dev/pci/pcivar.h> 6471901Sscottl 65230985Spfg#define M3_MODEL 1 6671901Sscottl 67230985Spfg#include <dev/sound/pci/allegro_reg.h> 68230985Spfg#include <dev/sound/pci/allegro_code.h> 69230985Spfg 7082180ScgSND_DECLARE_FILE("$FreeBSD$"); 7182180Scg 7271901Sscottl/* -------------------------------------------------------------------- */ 7371901Sscottl 7471901Sscottlenum {CHANGE=0, CALL=1, INTR=2, BORING=3, NONE=-1}; 7571901Sscottl#ifndef M3_DEBUG_LEVEL 7671901Sscottl#define M3_DEBUG_LEVEL NONE 7771901Sscottl#endif 7871901Sscottl#define M3_DEBUG(level, _msg) {if ((level) <= M3_DEBUG_LEVEL) {printf _msg;}} 7971901Sscottl 8071901Sscottl/* -------------------------------------------------------------------- */ 8171901Sscottlenum { 8271901Sscottl ESS_ALLEGRO_1, 8371901Sscottl ESS_MAESTRO3 8471901Sscottl}; 8571901Sscottl 8671901Sscottlstatic struct m3_card_type { 8771901Sscottl u_int32_t pci_id; int which; int delay1; int delay2; char *name; 8871901Sscottl} m3_card_types[] = { 8971901Sscottl { 0x1988125d, ESS_ALLEGRO_1, 50, 800, "ESS Technology Allegro-1" }, 9071901Sscottl { 0x1998125d, ESS_MAESTRO3, 20, 500, "ESS Technology Maestro3" }, 9171901Sscottl { 0x199a125d, ESS_MAESTRO3, 20, 500, "ESS Technology Maestro3" }, 9271901Sscottl { 0, 0, 0, 0, NULL } 9371901Sscottl}; 9471901Sscottl 95167355Sariff#define M3_BUFSIZE_MIN 4096 96146514Syongari#define M3_BUFSIZE_MAX 65536 9784731Sscottl#define M3_BUFSIZE_DEFAULT 4096 9884926Sscottl#define M3_PCHANS 4 /* create /dev/dsp0.[0-N] to use more than one */ 9971901Sscottl#define M3_RCHANS 1 10080003Sscottl#define M3_MAXADDR ((1 << 27) - 1) 101230985Spfg#define M3_DEFAULT_VOL 0x6800 10271901Sscottl 10371901Sscottlstruct sc_info; 10471901Sscottl 10571901Sscottlstruct sc_pchinfo { 10671901Sscottl u_int32_t spd; 10771901Sscottl u_int32_t fmt; 10874763Scg struct snd_dbuf *buffer; 10974763Scg struct pcm_channel *channel; 11071901Sscottl struct sc_info *parent; 11171901Sscottl u_int32_t bufsize; 11271901Sscottl u_int32_t dac_data; 11371901Sscottl u_int32_t dac_idx; 11471901Sscottl u_int32_t active; 115167355Sariff u_int32_t ptr; 116167355Sariff u_int32_t prevptr; 11771901Sscottl}; 11871901Sscottl 11971901Sscottlstruct sc_rchinfo { 12071901Sscottl u_int32_t spd; 12171901Sscottl u_int32_t fmt; 12274763Scg struct snd_dbuf *buffer; 12374763Scg struct pcm_channel *channel; 12471901Sscottl struct sc_info *parent; 12571901Sscottl u_int32_t bufsize; 12671901Sscottl u_int32_t adc_data; 12771901Sscottl u_int32_t adc_idx; 12871901Sscottl u_int32_t active; 129167355Sariff u_int32_t ptr; 130167355Sariff u_int32_t prevptr; 13171901Sscottl}; 13271901Sscottl 13371901Sscottlstruct sc_info { 13471901Sscottl device_t dev; 13571901Sscottl u_int32_t type; 13671901Sscottl int which; 13771901Sscottl int delay1; 13871901Sscottl int delay2; 13971901Sscottl 14071901Sscottl bus_space_tag_t st; 14171901Sscottl bus_space_handle_t sh; 14271901Sscottl bus_dma_tag_t parent_dmat; 14371901Sscottl 14471901Sscottl struct resource *reg; 14571901Sscottl struct resource *irq; 14671901Sscottl int regtype; 14771901Sscottl int regid; 14871901Sscottl int irqid; 14971901Sscottl void *ih; 15071901Sscottl 15171901Sscottl struct sc_pchinfo pch[M3_PCHANS]; 15271901Sscottl struct sc_rchinfo rch[M3_RCHANS]; 15371901Sscottl int pch_cnt; 15471901Sscottl int rch_cnt; 15571901Sscottl int pch_active_cnt; 15684731Sscottl unsigned int bufsz; 15771901Sscottl u_int16_t *savemem; 158146514Syongari 159146514Syongari struct mtx *sc_lock; 16071901Sscottl}; 16171901Sscottl 162146514Syongari#define M3_LOCK(_sc) snd_mtxlock((_sc)->sc_lock) 163146514Syongari#define M3_UNLOCK(_sc) snd_mtxunlock((_sc)->sc_lock) 164146514Syongari#define M3_LOCK_ASSERT(_sc) snd_mtxassert((_sc)->sc_lock) 165146514Syongari 16671901Sscottl/* -------------------------------------------------------------------- */ 16771901Sscottl 16871901Sscottl/* play channel interface */ 16974763Scgstatic void *m3_pchan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int); 17071901Sscottlstatic int m3_pchan_free(kobj_t, void *); 17171901Sscottlstatic int m3_pchan_setformat(kobj_t, void *, u_int32_t); 172193640Sariffstatic u_int32_t m3_pchan_setspeed(kobj_t, void *, u_int32_t); 173193640Sariffstatic u_int32_t m3_pchan_setblocksize(kobj_t, void *, u_int32_t); 17471901Sscottlstatic int m3_pchan_trigger(kobj_t, void *, int); 175146514Syongaristatic int m3_pchan_trigger_locked(kobj_t, void *, int); 176167355Sariffstatic u_int32_t m3_pchan_getptr_internal(struct sc_pchinfo *); 177167355Sariffstatic u_int32_t m3_pchan_getptr(kobj_t, void *); 17874763Scgstatic struct pcmchan_caps *m3_pchan_getcaps(kobj_t, void *); 17971901Sscottl 18071901Sscottl/* record channel interface */ 18174763Scgstatic void *m3_rchan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int); 18271901Sscottlstatic int m3_rchan_free(kobj_t, void *); 18371901Sscottlstatic int m3_rchan_setformat(kobj_t, void *, u_int32_t); 184193640Sariffstatic u_int32_t m3_rchan_setspeed(kobj_t, void *, u_int32_t); 185193640Sariffstatic u_int32_t m3_rchan_setblocksize(kobj_t, void *, u_int32_t); 18671901Sscottlstatic int m3_rchan_trigger(kobj_t, void *, int); 187146514Syongaristatic int m3_rchan_trigger_locked(kobj_t, void *, int); 188167355Sariffstatic u_int32_t m3_rchan_getptr_internal(struct sc_rchinfo *); 189167355Sariffstatic u_int32_t m3_rchan_getptr(kobj_t, void *); 19074763Scgstatic struct pcmchan_caps *m3_rchan_getcaps(kobj_t, void *); 19171901Sscottl 192167355Sariffstatic int m3_chan_active(struct sc_info *); 193167355Sariff 19471901Sscottl/* talk to the codec - called from ac97.c */ 195193640Sariffstatic u_int32_t m3_initcd(kobj_t, void *); 19671901Sscottlstatic int m3_rdcd(kobj_t, void *, int); 19771901Sscottlstatic int m3_wrcd(kobj_t, void *, int, u_int32_t); 19871901Sscottl 19971901Sscottl/* stuff */ 20071901Sscottlstatic void m3_intr(void *); 20171901Sscottlstatic int m3_power(struct sc_info *, int); 20271901Sscottlstatic int m3_init(struct sc_info *); 20371901Sscottlstatic int m3_uninit(struct sc_info *); 20471901Sscottlstatic u_int8_t m3_assp_halt(struct sc_info *); 20571901Sscottlstatic void m3_config(struct sc_info *); 20671901Sscottlstatic void m3_amp_enable(struct sc_info *); 20771901Sscottlstatic void m3_enable_ints(struct sc_info *); 20871901Sscottlstatic void m3_codec_reset(struct sc_info *); 20971901Sscottl 21071901Sscottl/* -------------------------------------------------------------------- */ 21171901Sscottl/* Codec descriptor */ 21271901Sscottlstatic kobj_method_t m3_codec_methods[] = { 21371901Sscottl KOBJMETHOD(ac97_init, m3_initcd), 21471901Sscottl KOBJMETHOD(ac97_read, m3_rdcd), 21571901Sscottl KOBJMETHOD(ac97_write, m3_wrcd), 216193640Sariff KOBJMETHOD_END 21771901Sscottl}; 21871901SscottlAC97_DECLARE(m3_codec); 21971901Sscottl 22071901Sscottl/* -------------------------------------------------------------------- */ 22171901Sscottl/* channel descriptors */ 22271901Sscottl 22371901Sscottlstatic u_int32_t m3_playfmt[] = { 224193640Sariff SND_FORMAT(AFMT_U8, 1, 0), 225193640Sariff SND_FORMAT(AFMT_U8, 2, 0), 226193640Sariff SND_FORMAT(AFMT_S16_LE, 1, 0), 227193640Sariff SND_FORMAT(AFMT_S16_LE, 2, 0), 22871901Sscottl 0 22971901Sscottl}; 23074763Scgstatic struct pcmchan_caps m3_playcaps = {8000, 48000, m3_playfmt, 0}; 23171901Sscottl 23271901Sscottlstatic kobj_method_t m3_pch_methods[] = { 23371901Sscottl KOBJMETHOD(channel_init, m3_pchan_init), 23471901Sscottl KOBJMETHOD(channel_setformat, m3_pchan_setformat), 23571901Sscottl KOBJMETHOD(channel_setspeed, m3_pchan_setspeed), 23671901Sscottl KOBJMETHOD(channel_setblocksize, m3_pchan_setblocksize), 23771901Sscottl KOBJMETHOD(channel_trigger, m3_pchan_trigger), 23871901Sscottl KOBJMETHOD(channel_getptr, m3_pchan_getptr), 23971901Sscottl KOBJMETHOD(channel_getcaps, m3_pchan_getcaps), 24071901Sscottl KOBJMETHOD(channel_free, m3_pchan_free), 241193640Sariff KOBJMETHOD_END 24271901Sscottl}; 24371901SscottlCHANNEL_DECLARE(m3_pch); 24471901Sscottl 24571901Sscottlstatic u_int32_t m3_recfmt[] = { 246193640Sariff SND_FORMAT(AFMT_U8, 1, 0), 247193640Sariff SND_FORMAT(AFMT_U8, 2, 0), 248193640Sariff SND_FORMAT(AFMT_S16_LE, 1, 0), 249193640Sariff SND_FORMAT(AFMT_S16_LE, 2, 0), 25071901Sscottl 0 25171901Sscottl}; 25274763Scgstatic struct pcmchan_caps m3_reccaps = {8000, 48000, m3_recfmt, 0}; 25371901Sscottl 25471901Sscottlstatic kobj_method_t m3_rch_methods[] = { 25571901Sscottl KOBJMETHOD(channel_init, m3_rchan_init), 25671901Sscottl KOBJMETHOD(channel_setformat, m3_rchan_setformat), 25771901Sscottl KOBJMETHOD(channel_setspeed, m3_rchan_setspeed), 25871901Sscottl KOBJMETHOD(channel_setblocksize, m3_rchan_setblocksize), 25971901Sscottl KOBJMETHOD(channel_trigger, m3_rchan_trigger), 26071901Sscottl KOBJMETHOD(channel_getptr, m3_rchan_getptr), 26171901Sscottl KOBJMETHOD(channel_getcaps, m3_rchan_getcaps), 26271901Sscottl KOBJMETHOD(channel_free, m3_rchan_free), 263193640Sariff KOBJMETHOD_END 26471901Sscottl}; 26571901SscottlCHANNEL_DECLARE(m3_rch); 26671901Sscottl 26771901Sscottl/* -------------------------------------------------------------------- */ 26871901Sscottl/* some i/o convenience functions */ 26971901Sscottl 27071901Sscottl#define m3_rd_1(sc, regno) bus_space_read_1(sc->st, sc->sh, regno) 27171901Sscottl#define m3_rd_2(sc, regno) bus_space_read_2(sc->st, sc->sh, regno) 27271901Sscottl#define m3_rd_4(sc, regno) bus_space_read_4(sc->st, sc->sh, regno) 27371901Sscottl#define m3_wr_1(sc, regno, data) bus_space_write_1(sc->st, sc->sh, regno, data) 27471901Sscottl#define m3_wr_2(sc, regno, data) bus_space_write_2(sc->st, sc->sh, regno, data) 27571901Sscottl#define m3_wr_4(sc, regno, data) bus_space_write_4(sc->st, sc->sh, regno, data) 27671901Sscottl#define m3_rd_assp_code(sc, index) \ 27771901Sscottl m3_rd_assp(sc, MEMTYPE_INTERNAL_CODE, index) 27871901Sscottl#define m3_wr_assp_code(sc, index, data) \ 27971901Sscottl m3_wr_assp(sc, MEMTYPE_INTERNAL_CODE, index, data) 28071901Sscottl#define m3_rd_assp_data(sc, index) \ 28171901Sscottl m3_rd_assp(sc, MEMTYPE_INTERNAL_DATA, index) 28271901Sscottl#define m3_wr_assp_data(sc, index, data) \ 28371901Sscottl m3_wr_assp(sc, MEMTYPE_INTERNAL_DATA, index, data) 28471901Sscottl 28571901Sscottlstatic __inline u_int16_t 28671901Sscottlm3_rd_assp(struct sc_info *sc, u_int16_t region, u_int16_t index) 28771901Sscottl{ 28871901Sscottl m3_wr_2(sc, DSP_PORT_MEMORY_TYPE, region & MEMTYPE_MASK); 28971901Sscottl m3_wr_2(sc, DSP_PORT_MEMORY_INDEX, index); 29071901Sscottl return m3_rd_2(sc, DSP_PORT_MEMORY_DATA); 29171901Sscottl} 29271901Sscottl 29371901Sscottlstatic __inline void 29474797Scgm3_wr_assp(struct sc_info *sc, u_int16_t region, u_int16_t index, 29571901Sscottl u_int16_t data) 29671901Sscottl{ 29771901Sscottl m3_wr_2(sc, DSP_PORT_MEMORY_TYPE, region & MEMTYPE_MASK); 29871901Sscottl m3_wr_2(sc, DSP_PORT_MEMORY_INDEX, index); 29971901Sscottl m3_wr_2(sc, DSP_PORT_MEMORY_DATA, data); 30071901Sscottl} 30171901Sscottl 30271901Sscottlstatic __inline int 30371901Sscottlm3_wait(struct sc_info *sc) 30471901Sscottl{ 30571901Sscottl int i; 30671901Sscottl 30771901Sscottl for (i=0 ; i<20 ; i++) { 30871901Sscottl if ((m3_rd_1(sc, CODEC_STATUS) & 1) == 0) { 30971901Sscottl return 0; 31071901Sscottl } 31171901Sscottl DELAY(2); 31271901Sscottl } 31371901Sscottl return -1; 31471901Sscottl} 31571901Sscottl 31671901Sscottl/* -------------------------------------------------------------------- */ 31771901Sscottl/* ac97 codec */ 31871901Sscottl 319193640Sariffstatic u_int32_t 32071901Sscottlm3_initcd(kobj_t kobj, void *devinfo) 32171901Sscottl{ 32271901Sscottl struct sc_info *sc = (struct sc_info *)devinfo; 32371901Sscottl u_int32_t data; 32471901Sscottl 32571901Sscottl M3_DEBUG(CALL, ("m3_initcd\n")); 32671901Sscottl 32771901Sscottl /* init ac-link */ 32871901Sscottl 32971901Sscottl data = m3_rd_1(sc, CODEC_COMMAND); 33071901Sscottl return ((data & 0x1) ? 0 : 1); 33171901Sscottl} 33271901Sscottl 33371901Sscottlstatic int 33471901Sscottlm3_rdcd(kobj_t kobj, void *devinfo, int regno) 33571901Sscottl{ 33671901Sscottl struct sc_info *sc = (struct sc_info *)devinfo; 33771901Sscottl u_int32_t data; 33871901Sscottl 33971901Sscottl if (m3_wait(sc)) { 34071901Sscottl device_printf(sc->dev, "m3_rdcd timed out.\n"); 34171901Sscottl return -1; 34271901Sscottl } 34371901Sscottl m3_wr_1(sc, CODEC_COMMAND, (regno & 0x7f) | 0x80); 34474763Scg DELAY(50); /* ac97 cycle = 20.8 usec */ 34571901Sscottl if (m3_wait(sc)) { 34671901Sscottl device_printf(sc->dev, "m3_rdcd timed out.\n"); 34771901Sscottl return -1; 34871901Sscottl } 34971901Sscottl data = m3_rd_2(sc, CODEC_DATA); 35071901Sscottl return data; 35171901Sscottl} 35271901Sscottl 35371901Sscottlstatic int 35471901Sscottlm3_wrcd(kobj_t kobj, void *devinfo, int regno, u_int32_t data) 35571901Sscottl{ 35671901Sscottl struct sc_info *sc = (struct sc_info *)devinfo; 35771901Sscottl if (m3_wait(sc)) { 35871901Sscottl device_printf(sc->dev, "m3_wrcd timed out.\n"); 359201758Smbr return -1; 36071901Sscottl } 36171901Sscottl m3_wr_2(sc, CODEC_DATA, data); 36271901Sscottl m3_wr_1(sc, CODEC_COMMAND, regno & 0x7f); 36374763Scg DELAY(50); /* ac97 cycle = 20.8 usec */ 36471901Sscottl return 0; 36571901Sscottl} 36671901Sscottl 36771901Sscottl/* -------------------------------------------------------------------- */ 36871901Sscottl/* play channel interface */ 36971901Sscottl 37071901Sscottl#define LO(x) (((x) & 0x0000ffff) ) 37171901Sscottl#define HI(x) (((x) & 0xffff0000) >> 16) 37271901Sscottl 37371901Sscottlstatic void * 37474763Scgm3_pchan_init(kobj_t kobj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 37571901Sscottl{ 37671901Sscottl struct sc_info *sc = devinfo; 37771901Sscottl struct sc_pchinfo *ch; 37871901Sscottl u_int32_t bus_addr, i; 379146514Syongari int idx, data_bytes, dac_data; 380146514Syongari int dsp_in_size, dsp_out_size, dsp_in_buf, dsp_out_buf; 38171901Sscottl 382230985Spfg struct data_word { 383230985Spfg u_int16_t addr, val; 384230985Spfg } pv[] = { 385230985Spfg {CDATA_LEFT_VOLUME, M3_DEFAULT_VOL}, 386230985Spfg {CDATA_RIGHT_VOLUME, M3_DEFAULT_VOL}, 387230985Spfg {SRC3_DIRECTION_OFFSET, 0} , 388230985Spfg {SRC3_DIRECTION_OFFSET + 3, 0x0000}, 389230985Spfg {SRC3_DIRECTION_OFFSET + 4, 0}, 390230985Spfg {SRC3_DIRECTION_OFFSET + 5, 0}, 391230985Spfg {SRC3_DIRECTION_OFFSET + 6, 0}, 392230985Spfg {SRC3_DIRECTION_OFFSET + 7, 0}, 393230985Spfg {SRC3_DIRECTION_OFFSET + 8, 0}, 394230985Spfg {SRC3_DIRECTION_OFFSET + 9, 0}, 395230985Spfg {SRC3_DIRECTION_OFFSET + 10, 0x8000}, 396230985Spfg {SRC3_DIRECTION_OFFSET + 11, 0xFF00}, 397230985Spfg {SRC3_DIRECTION_OFFSET + 13, 0}, 398230985Spfg {SRC3_DIRECTION_OFFSET + 14, 0}, 399230985Spfg {SRC3_DIRECTION_OFFSET + 15, 0}, 400230985Spfg {SRC3_DIRECTION_OFFSET + 16, 8}, 401230985Spfg {SRC3_DIRECTION_OFFSET + 17, 50*2}, 402230985Spfg {SRC3_DIRECTION_OFFSET + 18, MINISRC_BIQUAD_STAGE - 1}, 403230985Spfg {SRC3_DIRECTION_OFFSET + 20, 0}, 404230985Spfg {SRC3_DIRECTION_OFFSET + 21, 0} 405230985Spfg }; 406230985Spfg 407146514Syongari M3_LOCK(sc); 408146514Syongari idx = sc->pch_cnt; /* dac instance number, no active reuse! */ 40971901Sscottl M3_DEBUG(CHANGE, ("m3_pchan_init(dac=%d)\n", idx)); 41071901Sscottl 41171901Sscottl if (dir != PCMDIR_PLAY) { 412146514Syongari M3_UNLOCK(sc); 41371901Sscottl device_printf(sc->dev, "m3_pchan_init not PCMDIR_PLAY\n"); 414146514Syongari return (NULL); 41571901Sscottl } 416146514Syongari 417146514Syongari data_bytes = (((MINISRC_TMP_BUFFER_SIZE & ~1) + 418146514Syongari (MINISRC_IN_BUFFER_SIZE & ~1) + 419146514Syongari (MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255) &~ 255; 420146514Syongari dac_data = 0x1100 + (data_bytes * idx); 421146514Syongari 422146514Syongari dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x20 * 2); 423146514Syongari dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x20 * 2); 424146514Syongari dsp_in_buf = dac_data + (MINISRC_TMP_BUFFER_SIZE/2); 425146514Syongari dsp_out_buf = dsp_in_buf + (dsp_in_size/2) + 1; 426146514Syongari 42771901Sscottl ch = &sc->pch[idx]; 42871901Sscottl ch->dac_idx = idx; 42971901Sscottl ch->dac_data = dac_data; 43071901Sscottl if (ch->dac_data + data_bytes/2 >= 0x1c00) { 431146514Syongari M3_UNLOCK(sc); 43271901Sscottl device_printf(sc->dev, "m3_pchan_init: revb mem exhausted\n"); 433146514Syongari return (NULL); 43471901Sscottl } 43571901Sscottl 43671901Sscottl ch->buffer = b; 43771901Sscottl ch->parent = sc; 43871901Sscottl ch->channel = c; 439193640Sariff ch->fmt = SND_FORMAT(AFMT_U8, 1, 0); 44071901Sscottl ch->spd = DSP_DEFAULT_SPEED; 441146514Syongari M3_UNLOCK(sc); /* XXX */ 442168847Sariff if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0) { 44371901Sscottl device_printf(sc->dev, "m3_pchan_init chn_allocbuf failed\n"); 444146514Syongari return (NULL); 44571901Sscottl } 446146514Syongari M3_LOCK(sc); 44771901Sscottl ch->bufsize = sndbuf_getsize(ch->buffer); 44871901Sscottl 44971901Sscottl /* host dma buffer pointers */ 450111183Scognet bus_addr = sndbuf_getbufaddr(ch->buffer); 45171901Sscottl if (bus_addr & 3) { 45271901Sscottl device_printf(sc->dev, "m3_pchan_init unaligned bus_addr\n"); 45371901Sscottl bus_addr = (bus_addr + 4) & ~3; 45471901Sscottl } 45571901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_ADDRL, LO(bus_addr)); 45671901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_ADDRH, HI(bus_addr)); 45774797Scg m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_END_PLUS_1L, 45871901Sscottl LO(bus_addr + ch->bufsize)); 45974797Scg m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_END_PLUS_1H, 46071901Sscottl HI(bus_addr + ch->bufsize)); 46174797Scg m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTL, 46271901Sscottl LO(bus_addr)); 46374797Scg m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTH, 46471901Sscottl HI(bus_addr)); 46571901Sscottl 46671901Sscottl /* dsp buffers */ 46771901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_BEGIN, dsp_in_buf); 46871901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_END_PLUS_1, 46971901Sscottl dsp_in_buf + dsp_in_size/2); 47071901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_HEAD, dsp_in_buf); 47171901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_TAIL, dsp_in_buf); 47271901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_BEGIN, dsp_out_buf); 47371901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_END_PLUS_1, 47471901Sscottl dsp_out_buf + dsp_out_size/2); 47571901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_HEAD, dsp_out_buf); 47671901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_TAIL, dsp_out_buf); 47771901Sscottl 47871901Sscottl /* some per client initializers */ 47974797Scg m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 12, 48071901Sscottl ch->dac_data + 40 + 8); 48171901Sscottl m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 19, 48271901Sscottl 0x400 + MINISRC_COEF_LOC); 48371901Sscottl /* enable or disable low pass filter? (0xff if rate> 45000) */ 48471901Sscottl m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 22, 0); 48571901Sscottl /* tell it which way dma is going? */ 48671901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_DMA_CONTROL, 48774797Scg DMACONTROL_AUTOREPEAT + DMAC_PAGE3_SELECTOR + 48871901Sscottl DMAC_BLOCKF_SELECTOR); 48971901Sscottl 49071901Sscottl /* set an armload of static initializers */ 49171901Sscottl for(i = 0 ; i < (sizeof(pv) / sizeof(pv[0])) ; i++) { 49271901Sscottl m3_wr_assp_data(sc, ch->dac_data + pv[i].addr, pv[i].val); 49371901Sscottl } 49471901Sscottl 49571901Sscottl /* put us in the packed task lists */ 49674797Scg m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC + 49774797Scg (sc->pch_cnt + sc->rch_cnt), 49871901Sscottl ch->dac_data >> DP_SHIFT_COUNT); 49974797Scg m3_wr_assp_data(sc, KDATA_DMA_XFER0 + (sc->pch_cnt + sc->rch_cnt), 50071901Sscottl ch->dac_data >> DP_SHIFT_COUNT); 50174797Scg m3_wr_assp_data(sc, KDATA_MIXER_XFER0 + sc->pch_cnt, 50271901Sscottl ch->dac_data >> DP_SHIFT_COUNT); 50371901Sscottl 504146514Syongari /* gotta start before stop */ 505146514Syongari m3_pchan_trigger_locked(NULL, ch, PCMTRIG_START); 506146514Syongari /* silence noise on load */ 507146514Syongari m3_pchan_trigger_locked(NULL, ch, PCMTRIG_STOP); 50871901Sscottl 50971901Sscottl sc->pch_cnt++; 510146514Syongari M3_UNLOCK(sc); 511146514Syongari 512146514Syongari return (ch); 51371901Sscottl} 51471901Sscottl 51571901Sscottlstatic int 51671901Sscottlm3_pchan_free(kobj_t kobj, void *chdata) 51771901Sscottl{ 51871901Sscottl struct sc_pchinfo *ch = chdata; 51971901Sscottl struct sc_info *sc = ch->parent; 52071901Sscottl 521146514Syongari M3_LOCK(sc); 52271901Sscottl M3_DEBUG(CHANGE, ("m3_pchan_free(dac=%d)\n", ch->dac_idx)); 52371901Sscottl 52471901Sscottl /* 52571901Sscottl * should remove this exact instance from the packed lists, but all 52671901Sscottl * are released at once (and in a stopped state) so this is ok. 52771901Sscottl */ 52874797Scg m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC + 52971901Sscottl (sc->pch_cnt - 1) + sc->rch_cnt, 0); 53074797Scg m3_wr_assp_data(sc, KDATA_DMA_XFER0 + 53171901Sscottl (sc->pch_cnt - 1) + sc->rch_cnt, 0); 53271901Sscottl m3_wr_assp_data(sc, KDATA_MIXER_XFER0 + (sc->pch_cnt-1), 0); 533146514Syongari sc->pch_cnt--; 534146514Syongari M3_UNLOCK(sc); 53571901Sscottl 536146514Syongari return (0); 53771901Sscottl} 53871901Sscottl 53971901Sscottlstatic int 54071901Sscottlm3_pchan_setformat(kobj_t kobj, void *chdata, u_int32_t format) 54171901Sscottl{ 54271901Sscottl struct sc_pchinfo *ch = chdata; 54371901Sscottl struct sc_info *sc = ch->parent; 54471901Sscottl u_int32_t data; 54574797Scg 546146514Syongari M3_LOCK(sc); 54774797Scg M3_DEBUG(CHANGE, 54874797Scg ("m3_pchan_setformat(dac=%d, format=0x%x{%s-%s})\n", 54971901Sscottl ch->dac_idx, format, 55071901Sscottl format & (AFMT_U8|AFMT_S8) ? "8bit":"16bit", 551193640Sariff (AFMT_CHANNEL(format) > 1) ? "STEREO":"MONO")); 55274797Scg 55371901Sscottl /* mono word */ 554193640Sariff data = (AFMT_CHANNEL(format) > 1)? 0 : 1; 55571901Sscottl m3_wr_assp_data(sc, ch->dac_data + SRC3_MODE_OFFSET, data); 55674797Scg 55771901Sscottl /* 8bit word */ 55871901Sscottl data = ((format & AFMT_U8) || (format & AFMT_S8)) ? 1 : 0; 55971901Sscottl m3_wr_assp_data(sc, ch->dac_data + SRC3_WORD_LENGTH_OFFSET, data); 56074797Scg 56171901Sscottl ch->fmt = format; 562146514Syongari M3_UNLOCK(sc); 563146514Syongari 564146514Syongari return (0); 56571901Sscottl} 56671901Sscottl 567193640Sariffstatic u_int32_t 56871901Sscottlm3_pchan_setspeed(kobj_t kobj, void *chdata, u_int32_t speed) 56971901Sscottl{ 57071901Sscottl struct sc_pchinfo *ch = chdata; 57171901Sscottl struct sc_info *sc = ch->parent; 57271901Sscottl u_int32_t freq; 57371901Sscottl 574146514Syongari M3_LOCK(sc); 57574797Scg M3_DEBUG(CHANGE, ("m3_pchan_setspeed(dac=%d, speed=%d)\n", 57671901Sscottl ch->dac_idx, speed)); 57771901Sscottl 57871901Sscottl if ((freq = ((speed << 15) + 24000) / 48000) != 0) { 57971901Sscottl freq--; 58071901Sscottl } 58171901Sscottl 58271901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_FREQUENCY, freq); 583146514Syongari ch->spd = speed; 584146514Syongari M3_UNLOCK(sc); 58571901Sscottl 586146514Syongari /* return closest possible speed */ 587146514Syongari return (speed); 58871901Sscottl} 58971901Sscottl 590193640Sariffstatic u_int32_t 59171901Sscottlm3_pchan_setblocksize(kobj_t kobj, void *chdata, u_int32_t blocksize) 59271901Sscottl{ 59371901Sscottl struct sc_pchinfo *ch = chdata; 59471901Sscottl 59574797Scg M3_DEBUG(CHANGE, ("m3_pchan_setblocksize(dac=%d, blocksize=%d)\n", 59671901Sscottl ch->dac_idx, blocksize)); 59771901Sscottl 598167355Sariff return (sndbuf_getblksz(ch->buffer)); 59971901Sscottl} 60071901Sscottl 60171901Sscottlstatic int 60271901Sscottlm3_pchan_trigger(kobj_t kobj, void *chdata, int go) 60371901Sscottl{ 60471901Sscottl struct sc_pchinfo *ch = chdata; 60571901Sscottl struct sc_info *sc = ch->parent; 606146514Syongari int ret; 607146514Syongari 608170521Sariff if (!PCMTRIG_COMMON(go)) 609170521Sariff return (0); 610170521Sariff 611146514Syongari M3_LOCK(sc); 612146514Syongari ret = m3_pchan_trigger_locked(kobj, chdata, go); 613146514Syongari M3_UNLOCK(sc); 614146514Syongari 615146514Syongari return (ret); 616146514Syongari} 617146514Syongari 618146514Syongaristatic int 619167355Sariffm3_chan_active(struct sc_info *sc) 620167355Sariff{ 621167355Sariff int i, ret; 622167355Sariff 623167355Sariff ret = 0; 624167355Sariff 625167355Sariff for (i = 0; i < sc->pch_cnt; i++) 626167355Sariff ret += sc->pch[i].active; 627167355Sariff 628167355Sariff for (i = 0; i < sc->rch_cnt; i++) 629167355Sariff ret += sc->rch[i].active; 630167355Sariff 631167355Sariff return (ret); 632167355Sariff} 633167355Sariff 634167355Sariffstatic int 635146514Syongarim3_pchan_trigger_locked(kobj_t kobj, void *chdata, int go) 636146514Syongari{ 637146514Syongari struct sc_pchinfo *ch = chdata; 638146514Syongari struct sc_info *sc = ch->parent; 63971901Sscottl u_int32_t data; 64074797Scg 641146514Syongari M3_LOCK_ASSERT(sc); 64271901Sscottl M3_DEBUG(go == PCMTRIG_START ? CHANGE : 64371901Sscottl go == PCMTRIG_STOP ? CHANGE : 64471901Sscottl go == PCMTRIG_ABORT ? CHANGE : 64571901Sscottl CALL, 64671901Sscottl ("m3_pchan_trigger(dac=%d, go=0x%x{%s})\n", ch->dac_idx, go, 64771901Sscottl go == PCMTRIG_START ? "PCMTRIG_START" : 64871901Sscottl go == PCMTRIG_STOP ? "PCMTRIG_STOP" : 64971901Sscottl go == PCMTRIG_ABORT ? "PCMTRIG_ABORT" : "ignore")); 65071901Sscottl 65171901Sscottl switch(go) { 65271901Sscottl case PCMTRIG_START: 65371901Sscottl if (ch->active) { 65471901Sscottl return 0; 65571901Sscottl } 65671901Sscottl ch->active = 1; 657167355Sariff ch->ptr = 0; 658167355Sariff ch->prevptr = 0; 65971901Sscottl sc->pch_active_cnt++; 66074797Scg 66171901Sscottl /*[[inc_timer_users]]*/ 662167355Sariff if (m3_chan_active(sc) == 1) { 663167355Sariff m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 240); 664167355Sariff m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 240); 665167355Sariff data = m3_rd_2(sc, HOST_INT_CTRL); 666167355Sariff m3_wr_2(sc, HOST_INT_CTRL, data | CLKRUN_GEN_ENABLE); 667167355Sariff } 66874797Scg 66971901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_INSTANCE_READY, 1); 67074797Scg m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER, 67171901Sscottl sc->pch_active_cnt); 67271901Sscottl break; 67371901Sscottl 67471901Sscottl case PCMTRIG_STOP: 67571901Sscottl case PCMTRIG_ABORT: 67671901Sscottl if (ch->active == 0) { 67771901Sscottl return 0; 67871901Sscottl } 67971901Sscottl ch->active = 0; 68071901Sscottl sc->pch_active_cnt--; 68171901Sscottl 68271901Sscottl /* XXX should the channel be drained? */ 68371901Sscottl /*[[dec_timer_users]]*/ 684167355Sariff if (m3_chan_active(sc) == 0) { 685167355Sariff m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 0); 686167355Sariff m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 0); 687167355Sariff data = m3_rd_2(sc, HOST_INT_CTRL); 688167355Sariff m3_wr_2(sc, HOST_INT_CTRL, data & ~CLKRUN_GEN_ENABLE); 689167355Sariff } 69074797Scg 69171901Sscottl m3_wr_assp_data(sc, ch->dac_data + CDATA_INSTANCE_READY, 0); 69274797Scg m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER, 69371901Sscottl sc->pch_active_cnt); 69471901Sscottl break; 69571901Sscottl 69671901Sscottl case PCMTRIG_EMLDMAWR: 69771901Sscottl /* got play irq, transfer next buffer - ignore if using dma */ 69871901Sscottl case PCMTRIG_EMLDMARD: 69971901Sscottl /* got rec irq, transfer next buffer - ignore if using dma */ 70071901Sscottl default: 70171901Sscottl break; 70271901Sscottl } 70371901Sscottl return 0; 70471901Sscottl} 70571901Sscottl 706167355Sariffstatic u_int32_t 707167355Sariffm3_pchan_getptr_internal(struct sc_pchinfo *ch) 70871901Sscottl{ 70971901Sscottl struct sc_info *sc = ch->parent; 710146514Syongari u_int32_t hi, lo, bus_base, bus_crnt; 71171901Sscottl 712146514Syongari bus_base = sndbuf_getbufaddr(ch->buffer); 71371901Sscottl hi = m3_rd_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTH); 71471901Sscottl lo = m3_rd_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTL); 71571901Sscottl bus_crnt = lo | (hi << 16); 71671901Sscottl 71774797Scg M3_DEBUG(CALL, ("m3_pchan_getptr(dac=%d) result=%d\n", 71871901Sscottl ch->dac_idx, bus_crnt - bus_base)); 71971901Sscottl 72071901Sscottl return (bus_crnt - bus_base); /* current byte offset of channel */ 72171901Sscottl} 72271901Sscottl 723167355Sariffstatic u_int32_t 724167355Sariffm3_pchan_getptr(kobj_t kobj, void *chdata) 725167355Sariff{ 726167355Sariff struct sc_pchinfo *ch = chdata; 727167355Sariff struct sc_info *sc = ch->parent; 728167355Sariff u_int32_t ptr; 729167355Sariff 730167355Sariff M3_LOCK(sc); 731167355Sariff ptr = ch->ptr; 732167355Sariff M3_UNLOCK(sc); 733167355Sariff 734167355Sariff return (ptr); 735167355Sariff} 736167355Sariff 73774763Scgstatic struct pcmchan_caps * 73871901Sscottlm3_pchan_getcaps(kobj_t kobj, void *chdata) 73971901Sscottl{ 74071901Sscottl struct sc_pchinfo *ch = chdata; 74171901Sscottl 74271901Sscottl M3_DEBUG(CALL, ("m3_pchan_getcaps(dac=%d)\n", ch->dac_idx)); 74371901Sscottl 74471901Sscottl return &m3_playcaps; 74571901Sscottl} 74671901Sscottl 74771901Sscottl/* -------------------------------------------------------------------- */ 74871901Sscottl/* rec channel interface */ 74971901Sscottl 75071901Sscottlstatic void * 75174763Scgm3_rchan_init(kobj_t kobj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir) 75271901Sscottl{ 75371901Sscottl struct sc_info *sc = devinfo; 75471901Sscottl struct sc_rchinfo *ch; 75571901Sscottl u_int32_t bus_addr, i; 75671901Sscottl 757146514Syongari int idx, data_bytes, adc_data; 758146514Syongari int dsp_in_size, dsp_out_size, dsp_in_buf, dsp_out_buf; 75971901Sscottl 760230985Spfg struct data_word { 761230985Spfg u_int16_t addr, val; 762230985Spfg } rv[] = { 763230985Spfg {CDATA_LEFT_VOLUME, M3_DEFAULT_VOL}, 764230985Spfg {CDATA_RIGHT_VOLUME, M3_DEFAULT_VOL}, 765230985Spfg {SRC3_DIRECTION_OFFSET, 1}, 766230985Spfg {SRC3_DIRECTION_OFFSET + 3, 0x0000}, 767230985Spfg {SRC3_DIRECTION_OFFSET + 4, 0}, 768230985Spfg {SRC3_DIRECTION_OFFSET + 5, 0}, 769230985Spfg {SRC3_DIRECTION_OFFSET + 6, 0}, 770230985Spfg {SRC3_DIRECTION_OFFSET + 7, 0}, 771230985Spfg {SRC3_DIRECTION_OFFSET + 8, 0}, 772230985Spfg {SRC3_DIRECTION_OFFSET + 9, 0}, 773230985Spfg {SRC3_DIRECTION_OFFSET + 10, 0x8000}, 774230985Spfg {SRC3_DIRECTION_OFFSET + 11, 0xFF00}, 775230985Spfg {SRC3_DIRECTION_OFFSET + 13, 0}, 776230985Spfg {SRC3_DIRECTION_OFFSET + 14, 0}, 777230985Spfg {SRC3_DIRECTION_OFFSET + 15, 0}, 778230985Spfg {SRC3_DIRECTION_OFFSET + 16, 50}, 779230985Spfg {SRC3_DIRECTION_OFFSET + 17, 8}, 780230985Spfg {SRC3_DIRECTION_OFFSET + 18, 0}, 781230985Spfg {SRC3_DIRECTION_OFFSET + 19, 0}, 782230985Spfg {SRC3_DIRECTION_OFFSET + 20, 0}, 783230985Spfg {SRC3_DIRECTION_OFFSET + 21, 0}, 784230985Spfg {SRC3_DIRECTION_OFFSET + 22, 0xff} 785230985Spfg }; 786230985Spfg 787146514Syongari M3_LOCK(sc); 788146514Syongari idx = sc->rch_cnt; /* adc instance number, no active reuse! */ 78971901Sscottl M3_DEBUG(CHANGE, ("m3_rchan_init(adc=%d)\n", idx)); 79071901Sscottl 79171901Sscottl if (dir != PCMDIR_REC) { 792146514Syongari M3_UNLOCK(sc); 79371901Sscottl device_printf(sc->dev, "m3_pchan_init not PCMDIR_REC\n"); 794146514Syongari return (NULL); 79571901Sscottl } 796146514Syongari 797146514Syongari data_bytes = (((MINISRC_TMP_BUFFER_SIZE & ~1) + 798146514Syongari (MINISRC_IN_BUFFER_SIZE & ~1) + 799146514Syongari (MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255) &~ 255; 800146514Syongari adc_data = 0x1100 + (data_bytes * idx) + data_bytes/2; 801146514Syongari dsp_in_size = MINISRC_IN_BUFFER_SIZE + (0x10 * 2); 802146514Syongari dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x10 * 2); 803146514Syongari dsp_in_buf = adc_data + (MINISRC_TMP_BUFFER_SIZE / 2); 804146514Syongari dsp_out_buf = dsp_in_buf + (dsp_in_size / 2) + 1; 805146514Syongari 80671901Sscottl ch = &sc->rch[idx]; 80771901Sscottl ch->adc_idx = idx; 80871901Sscottl ch->adc_data = adc_data; 80971901Sscottl if (ch->adc_data + data_bytes/2 >= 0x1c00) { 810146514Syongari M3_UNLOCK(sc); 81171901Sscottl device_printf(sc->dev, "m3_rchan_init: revb mem exhausted\n"); 812146514Syongari return (NULL); 81371901Sscottl } 81471901Sscottl 81571901Sscottl ch->buffer = b; 81671901Sscottl ch->parent = sc; 81771901Sscottl ch->channel = c; 818193640Sariff ch->fmt = SND_FORMAT(AFMT_U8, 1, 0); 81971901Sscottl ch->spd = DSP_DEFAULT_SPEED; 820146514Syongari M3_UNLOCK(sc); /* XXX */ 821168847Sariff if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0) { 82271901Sscottl device_printf(sc->dev, "m3_rchan_init chn_allocbuf failed\n"); 823146514Syongari return (NULL); 82471901Sscottl } 825146514Syongari M3_LOCK(sc); 82671901Sscottl ch->bufsize = sndbuf_getsize(ch->buffer); 82774797Scg 82871901Sscottl /* host dma buffer pointers */ 829111183Scognet bus_addr = sndbuf_getbufaddr(ch->buffer); 83071901Sscottl if (bus_addr & 3) { 83171901Sscottl device_printf(sc->dev, "m3_rchan_init unaligned bus_addr\n"); 83271901Sscottl bus_addr = (bus_addr + 4) & ~3; 83371901Sscottl } 83471901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_ADDRL, LO(bus_addr)); 83571901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_ADDRH, HI(bus_addr)); 83674797Scg m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_END_PLUS_1L, 83771901Sscottl LO(bus_addr + ch->bufsize)); 83874797Scg m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_END_PLUS_1H, 83971901Sscottl HI(bus_addr + ch->bufsize)); 84074797Scg m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTL, 84171901Sscottl LO(bus_addr)); 84274797Scg m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTH, 84371901Sscottl HI(bus_addr)); 84471901Sscottl 84571901Sscottl /* dsp buffers */ 84671901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_BEGIN, dsp_in_buf); 84771901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_END_PLUS_1, 84871901Sscottl dsp_in_buf + dsp_in_size/2); 84971901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_HEAD, dsp_in_buf); 85071901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_TAIL, dsp_in_buf); 85171901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_BEGIN, dsp_out_buf); 85271901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_END_PLUS_1, 85371901Sscottl dsp_out_buf + dsp_out_size/2); 85471901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_HEAD, dsp_out_buf); 85571901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_TAIL, dsp_out_buf); 85671901Sscottl 85771901Sscottl /* some per client initializers */ 85874797Scg m3_wr_assp_data(sc, ch->adc_data + SRC3_DIRECTION_OFFSET + 12, 85971901Sscottl ch->adc_data + 40 + 8); 86071901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_DMA_CONTROL, 86174797Scg DMACONTROL_DIRECTION + DMACONTROL_AUTOREPEAT + 86271901Sscottl DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR); 86371901Sscottl 86471901Sscottl /* set an armload of static initializers */ 86571901Sscottl for(i = 0 ; i < (sizeof(rv) / sizeof(rv[0])) ; i++) { 86671901Sscottl m3_wr_assp_data(sc, ch->adc_data + rv[i].addr, rv[i].val); 86771901Sscottl } 86871901Sscottl 86971901Sscottl /* put us in the packed task lists */ 87074797Scg m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC + 87174797Scg (sc->pch_cnt + sc->rch_cnt), 87271901Sscottl ch->adc_data >> DP_SHIFT_COUNT); 87371901Sscottl m3_wr_assp_data(sc, KDATA_DMA_XFER0 + (sc->pch_cnt + sc->rch_cnt), 87471901Sscottl ch->adc_data >> DP_SHIFT_COUNT); 87574797Scg m3_wr_assp_data(sc, KDATA_ADC1_XFER0 + sc->rch_cnt, 87671901Sscottl ch->adc_data >> DP_SHIFT_COUNT); 87771901Sscottl 878146514Syongari /* gotta start before stop */ 879146514Syongari m3_rchan_trigger_locked(NULL, ch, PCMTRIG_START); 880146514Syongari /* stop on init */ 881146514Syongari m3_rchan_trigger_locked(NULL, ch, PCMTRIG_STOP); 88274797Scg 88371901Sscottl sc->rch_cnt++; 884146514Syongari M3_UNLOCK(sc); 885146514Syongari 886146514Syongari return (ch); 88771901Sscottl} 88871901Sscottl 88971901Sscottlstatic int 89071901Sscottlm3_rchan_free(kobj_t kobj, void *chdata) 89171901Sscottl{ 89271901Sscottl struct sc_rchinfo *ch = chdata; 89371901Sscottl struct sc_info *sc = ch->parent; 89471901Sscottl 895146514Syongari M3_LOCK(sc); 89671901Sscottl M3_DEBUG(CHANGE, ("m3_rchan_free(adc=%d)\n", ch->adc_idx)); 89771901Sscottl 89871901Sscottl /* 89971901Sscottl * should remove this exact instance from the packed lists, but all 90071901Sscottl * are released at once (and in a stopped state) so this is ok. 90171901Sscottl */ 90274797Scg m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC + 90371901Sscottl (sc->rch_cnt - 1) + sc->pch_cnt, 0); 90474797Scg m3_wr_assp_data(sc, KDATA_DMA_XFER0 + 90571901Sscottl (sc->rch_cnt - 1) + sc->pch_cnt, 0); 90671901Sscottl m3_wr_assp_data(sc, KDATA_ADC1_XFER0 + (sc->rch_cnt - 1), 0); 907146514Syongari sc->rch_cnt--; 908146514Syongari M3_UNLOCK(sc); 90971901Sscottl 910146514Syongari return (0); 91171901Sscottl} 91271901Sscottl 91371901Sscottlstatic int 91471901Sscottlm3_rchan_setformat(kobj_t kobj, void *chdata, u_int32_t format) 91571901Sscottl{ 91671901Sscottl struct sc_rchinfo *ch = chdata; 91771901Sscottl struct sc_info *sc = ch->parent; 91871901Sscottl u_int32_t data; 91974797Scg 920146514Syongari M3_LOCK(sc); 92174797Scg M3_DEBUG(CHANGE, 92274797Scg ("m3_rchan_setformat(dac=%d, format=0x%x{%s-%s})\n", 92371901Sscottl ch->adc_idx, format, 92471901Sscottl format & (AFMT_U8|AFMT_S8) ? "8bit":"16bit", 925193640Sariff (AFMT_CHANNEL(format) > 1) ? "STEREO":"MONO")); 92674797Scg 92771901Sscottl /* mono word */ 928193640Sariff data = (AFMT_CHANNEL(format) > 1) ? 0 : 1; 92971901Sscottl m3_wr_assp_data(sc, ch->adc_data + SRC3_MODE_OFFSET, data); 93074797Scg 93171901Sscottl /* 8bit word */ 93271901Sscottl data = ((format & AFMT_U8) || (format & AFMT_S8)) ? 1 : 0; 93371901Sscottl m3_wr_assp_data(sc, ch->adc_data + SRC3_WORD_LENGTH_OFFSET, data); 934146514Syongari ch->fmt = format; 935146514Syongari M3_UNLOCK(sc); 93674797Scg 937146514Syongari return (0); 93871901Sscottl} 93971901Sscottl 940193640Sariffstatic u_int32_t 94171901Sscottlm3_rchan_setspeed(kobj_t kobj, void *chdata, u_int32_t speed) 94271901Sscottl{ 94371901Sscottl struct sc_rchinfo *ch = chdata; 94471901Sscottl struct sc_info *sc = ch->parent; 94571901Sscottl u_int32_t freq; 94674797Scg 947146514Syongari M3_LOCK(sc); 94874797Scg M3_DEBUG(CHANGE, ("m3_rchan_setspeed(adc=%d, speed=%d)\n", 94971901Sscottl ch->adc_idx, speed)); 95071901Sscottl 95171901Sscottl if ((freq = ((speed << 15) + 24000) / 48000) != 0) { 95271901Sscottl freq--; 95371901Sscottl } 95471901Sscottl 95571901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_FREQUENCY, freq); 956146514Syongari ch->spd = speed; 957146514Syongari M3_UNLOCK(sc); 95871901Sscottl 959146514Syongari /* return closest possible speed */ 960146514Syongari return (speed); 96171901Sscottl} 96271901Sscottl 963193640Sariffstatic u_int32_t 96471901Sscottlm3_rchan_setblocksize(kobj_t kobj, void *chdata, u_int32_t blocksize) 96571901Sscottl{ 96671901Sscottl struct sc_rchinfo *ch = chdata; 96771901Sscottl 96874797Scg M3_DEBUG(CHANGE, ("m3_rchan_setblocksize(adc=%d, blocksize=%d)\n", 96971901Sscottl ch->adc_idx, blocksize)); 97071901Sscottl 971167355Sariff return (sndbuf_getblksz(ch->buffer)); 97271901Sscottl} 97371901Sscottl 97471901Sscottlstatic int 97571901Sscottlm3_rchan_trigger(kobj_t kobj, void *chdata, int go) 97671901Sscottl{ 97771901Sscottl struct sc_rchinfo *ch = chdata; 97871901Sscottl struct sc_info *sc = ch->parent; 979146514Syongari int ret; 980146514Syongari 981170521Sariff if (!PCMTRIG_COMMON(go)) 982170521Sariff return (0); 983170521Sariff 984146514Syongari M3_LOCK(sc); 985146514Syongari ret = m3_rchan_trigger_locked(kobj, chdata, go); 986146514Syongari M3_UNLOCK(sc); 987146514Syongari 988146514Syongari return (ret); 989146514Syongari} 990146514Syongari 991146514Syongaristatic int 992146514Syongarim3_rchan_trigger_locked(kobj_t kobj, void *chdata, int go) 993146514Syongari{ 994146514Syongari struct sc_rchinfo *ch = chdata; 995146514Syongari struct sc_info *sc = ch->parent; 99671901Sscottl u_int32_t data; 99771901Sscottl 998146514Syongari M3_LOCK_ASSERT(sc); 99971901Sscottl M3_DEBUG(go == PCMTRIG_START ? CHANGE : 100071901Sscottl go == PCMTRIG_STOP ? CHANGE : 100171901Sscottl go == PCMTRIG_ABORT ? CHANGE : 100271901Sscottl CALL, 100371901Sscottl ("m3_rchan_trigger(adc=%d, go=0x%x{%s})\n", ch->adc_idx, go, 100471901Sscottl go == PCMTRIG_START ? "PCMTRIG_START" : 100571901Sscottl go == PCMTRIG_STOP ? "PCMTRIG_STOP" : 100671901Sscottl go == PCMTRIG_ABORT ? "PCMTRIG_ABORT" : "ignore")); 100771901Sscottl 100871901Sscottl switch(go) { 100971901Sscottl case PCMTRIG_START: 101071901Sscottl if (ch->active) { 101171901Sscottl return 0; 101271901Sscottl } 101371901Sscottl ch->active = 1; 1014167355Sariff ch->ptr = 0; 1015167355Sariff ch->prevptr = 0; 101674797Scg 101771901Sscottl /*[[inc_timer_users]]*/ 1018167355Sariff if (m3_chan_active(sc) == 1) { 1019167355Sariff m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 240); 1020167355Sariff m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 240); 1021167355Sariff data = m3_rd_2(sc, HOST_INT_CTRL); 1022167355Sariff m3_wr_2(sc, HOST_INT_CTRL, data | CLKRUN_GEN_ENABLE); 1023167355Sariff } 102474797Scg 102571901Sscottl m3_wr_assp_data(sc, KDATA_ADC1_REQUEST, 1); 102671901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_INSTANCE_READY, 1); 102771901Sscottl break; 102871901Sscottl 102971901Sscottl case PCMTRIG_STOP: 103071901Sscottl case PCMTRIG_ABORT: 103171901Sscottl if (ch->active == 0) { 103271901Sscottl return 0; 103371901Sscottl } 103471901Sscottl ch->active = 0; 103571901Sscottl 103671901Sscottl /*[[dec_timer_users]]*/ 1037167355Sariff if (m3_chan_active(sc) == 0) { 1038167355Sariff m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 0); 1039167355Sariff m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 0); 1040167355Sariff data = m3_rd_2(sc, HOST_INT_CTRL); 1041167355Sariff m3_wr_2(sc, HOST_INT_CTRL, data & ~CLKRUN_GEN_ENABLE); 1042167355Sariff } 104374797Scg 104471901Sscottl m3_wr_assp_data(sc, ch->adc_data + CDATA_INSTANCE_READY, 0); 104571901Sscottl m3_wr_assp_data(sc, KDATA_ADC1_REQUEST, 0); 104671901Sscottl break; 104771901Sscottl 104871901Sscottl case PCMTRIG_EMLDMAWR: 104971901Sscottl /* got play irq, transfer next buffer - ignore if using dma */ 105071901Sscottl case PCMTRIG_EMLDMARD: 105171901Sscottl /* got rec irq, transfer next buffer - ignore if using dma */ 105271901Sscottl default: 105371901Sscottl break; 105471901Sscottl } 105571901Sscottl return 0; 105671901Sscottl} 105771901Sscottl 1058167355Sariffstatic u_int32_t 1059167355Sariffm3_rchan_getptr_internal(struct sc_rchinfo *ch) 106071901Sscottl{ 106171901Sscottl struct sc_info *sc = ch->parent; 1062146514Syongari u_int32_t hi, lo, bus_base, bus_crnt; 106371901Sscottl 1064146514Syongari bus_base = sndbuf_getbufaddr(ch->buffer); 106571901Sscottl hi = m3_rd_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTH); 106671901Sscottl lo = m3_rd_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTL); 106771901Sscottl bus_crnt = lo | (hi << 16); 106871901Sscottl 106974797Scg M3_DEBUG(CALL, ("m3_rchan_getptr(adc=%d) result=%d\n", 107071901Sscottl ch->adc_idx, bus_crnt - bus_base)); 107171901Sscottl 107271901Sscottl return (bus_crnt - bus_base); /* current byte offset of channel */ 107371901Sscottl} 107471901Sscottl 1075167355Sariffstatic u_int32_t 1076167355Sariffm3_rchan_getptr(kobj_t kobj, void *chdata) 1077167355Sariff{ 1078167355Sariff struct sc_rchinfo *ch = chdata; 1079167355Sariff struct sc_info *sc = ch->parent; 1080167355Sariff u_int32_t ptr; 1081167355Sariff 1082167355Sariff M3_LOCK(sc); 1083167355Sariff ptr = ch->ptr; 1084167355Sariff M3_UNLOCK(sc); 1085167355Sariff 1086167355Sariff return (ptr); 1087167355Sariff} 1088167355Sariff 108974763Scgstatic struct pcmchan_caps * 109071901Sscottlm3_rchan_getcaps(kobj_t kobj, void *chdata) 109171901Sscottl{ 109271901Sscottl struct sc_rchinfo *ch = chdata; 109371901Sscottl 109471901Sscottl M3_DEBUG(CALL, ("m3_rchan_getcaps(adc=%d)\n", ch->adc_idx)); 109571901Sscottl 109671901Sscottl return &m3_reccaps; 109771901Sscottl} 109871901Sscottl 109971901Sscottl/* -------------------------------------------------------------------- */ 110071901Sscottl/* The interrupt handler */ 110171901Sscottl 110271901Sscottlstatic void 110371901Sscottlm3_intr(void *p) 110471901Sscottl{ 110571901Sscottl struct sc_info *sc = (struct sc_info *)p; 1106167355Sariff struct sc_pchinfo *pch; 1107167355Sariff struct sc_rchinfo *rch; 1108167355Sariff u_int32_t status, ctl, i, delta; 110974797Scg 111071901Sscottl M3_DEBUG(INTR, ("m3_intr\n")); 111171901Sscottl 1112146514Syongari M3_LOCK(sc); 111371901Sscottl status = m3_rd_1(sc, HOST_INT_STATUS); 1114146514Syongari if (!status) { 1115146514Syongari M3_UNLOCK(sc); 111671901Sscottl return; 1117146514Syongari } 111871901Sscottl 111971901Sscottl m3_wr_1(sc, HOST_INT_STATUS, 0xff); /* ack the int? */ 112071901Sscottl 112171901Sscottl if (status & HV_INT_PENDING) { 112271901Sscottl u_int8_t event; 112371901Sscottl 112471901Sscottl event = m3_rd_1(sc, HW_VOL_COUNTER_MASTER); 112571901Sscottl switch (event) { 112671901Sscottl case 0x99: 112771901Sscottl mixer_hwvol_mute(sc->dev); 112871901Sscottl break; 112971901Sscottl case 0xaa: 113071901Sscottl mixer_hwvol_step(sc->dev, 1, 1); 113171901Sscottl break; 113271901Sscottl case 0x66: 113371901Sscottl mixer_hwvol_step(sc->dev, -1, -1); 113471901Sscottl break; 113571901Sscottl case 0x88: 113671901Sscottl break; 113771901Sscottl default: 113871901Sscottl device_printf(sc->dev, "Unknown HWVOL event\n"); 113971901Sscottl } 114071901Sscottl m3_wr_1(sc, HW_VOL_COUNTER_MASTER, 0x88); 114174797Scg 114271901Sscottl } 114371901Sscottl 114471901Sscottl if (status & ASSP_INT_PENDING) { 114571901Sscottl ctl = m3_rd_1(sc, ASSP_CONTROL_B); 114671901Sscottl if (!(ctl & STOP_ASSP_CLOCK)) { 114771901Sscottl ctl = m3_rd_1(sc, ASSP_HOST_INT_STATUS); 114871901Sscottl if (ctl & DSP2HOST_REQ_TIMER) { 114974797Scg m3_wr_1(sc, ASSP_HOST_INT_STATUS, 115071901Sscottl DSP2HOST_REQ_TIMER); 115171901Sscottl /*[[ess_update_ptr]]*/ 1152167355Sariff goto m3_handle_channel_intr; 115371901Sscottl } 115471901Sscottl } 115571901Sscottl } 115674797Scg 1157167355Sariff goto m3_handle_channel_intr_out; 1158167355Sariff 1159167355Sariffm3_handle_channel_intr: 116071901Sscottl for (i=0 ; i<sc->pch_cnt ; i++) { 1161167355Sariff pch = &sc->pch[i]; 1162167355Sariff if (pch->active) { 1163167355Sariff pch->ptr = m3_pchan_getptr_internal(pch); 1164167355Sariff delta = pch->bufsize + pch->ptr - pch->prevptr; 1165167355Sariff delta %= pch->bufsize; 1166167355Sariff if (delta < sndbuf_getblksz(pch->buffer)) 1167167355Sariff continue; 1168167355Sariff pch->prevptr = pch->ptr; 1169146514Syongari M3_UNLOCK(sc); 1170167355Sariff chn_intr(pch->channel); 1171146514Syongari M3_LOCK(sc); 117271901Sscottl } 117371901Sscottl } 117471901Sscottl for (i=0 ; i<sc->rch_cnt ; i++) { 1175167355Sariff rch = &sc->rch[i]; 1176167355Sariff if (rch->active) { 1177167355Sariff rch->ptr = m3_rchan_getptr_internal(rch); 1178167355Sariff delta = rch->bufsize + rch->ptr - rch->prevptr; 1179167355Sariff delta %= rch->bufsize; 1180167355Sariff if (delta < sndbuf_getblksz(rch->buffer)) 1181167355Sariff continue; 1182167355Sariff rch->prevptr = rch->ptr; 1183146514Syongari M3_UNLOCK(sc); 1184167355Sariff chn_intr(rch->channel); 1185146514Syongari M3_LOCK(sc); 118671901Sscottl } 118771901Sscottl } 1188146514Syongari 1189167355Sariffm3_handle_channel_intr_out: 1190146514Syongari M3_UNLOCK(sc); 119171901Sscottl} 119271901Sscottl 119371901Sscottl/* -------------------------------------------------------------------- */ 119471901Sscottl/* stuff */ 119571901Sscottl 119671901Sscottlstatic int 119771901Sscottlm3_power(struct sc_info *sc, int state) 119871901Sscottl{ 119971901Sscottl u_int32_t data; 120071901Sscottl 120171901Sscottl M3_DEBUG(CHANGE, ("m3_power(%d)\n", state)); 1202146514Syongari M3_LOCK_ASSERT(sc); 120371901Sscottl 120471901Sscottl data = pci_read_config(sc->dev, 0x34, 1); 120571901Sscottl if (pci_read_config(sc->dev, data, 1) == 1) { 120671901Sscottl pci_write_config(sc->dev, data + 4, state, 1); 120771901Sscottl } 120871901Sscottl 120971901Sscottl return 0; 121071901Sscottl} 121171901Sscottl 121271901Sscottlstatic int 121371901Sscottlm3_init(struct sc_info *sc) 121471901Sscottl{ 121571901Sscottl u_int32_t data, i, size; 121671901Sscottl u_int8_t reset_state; 121771901Sscottl 1218146514Syongari M3_LOCK_ASSERT(sc); 121971901Sscottl M3_DEBUG(CHANGE, ("m3_init\n")); 122071901Sscottl 122171901Sscottl /* diable legacy emulations. */ 122271901Sscottl data = pci_read_config(sc->dev, PCI_LEGACY_AUDIO_CTRL, 2); 122371901Sscottl data |= DISABLE_LEGACY; 122471901Sscottl pci_write_config(sc->dev, PCI_LEGACY_AUDIO_CTRL, data, 2); 122571901Sscottl 122671901Sscottl m3_config(sc); 122774797Scg 122871901Sscottl reset_state = m3_assp_halt(sc); 122971901Sscottl 123071901Sscottl m3_codec_reset(sc); 123171901Sscottl 123271901Sscottl /* [m3_assp_init] */ 123371901Sscottl /* zero kernel data */ 123471901Sscottl size = REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA; 123571901Sscottl for(i = 0 ; i < size / 2 ; i++) { 123671901Sscottl m3_wr_assp_data(sc, KDATA_BASE_ADDR + i, 0); 123771901Sscottl } 123871901Sscottl /* zero mixer data? */ 123971901Sscottl size = REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA; 124071901Sscottl for(i = 0 ; i < size / 2 ; i++) { 124171901Sscottl m3_wr_assp_data(sc, KDATA_BASE_ADDR2 + i, 0); 124271901Sscottl } 124371901Sscottl /* init dma pointer */ 124474797Scg m3_wr_assp_data(sc, KDATA_CURRENT_DMA, 124571901Sscottl KDATA_DMA_XFER0); 124671901Sscottl /* write kernel into code memory */ 1247230985Spfg size = sizeof(gaw_kernel_vect_code); 124871901Sscottl for(i = 0 ; i < size / 2; i++) { 124974797Scg m3_wr_assp_code(sc, REV_B_CODE_MEMORY_BEGIN + i, 1250230985Spfg gaw_kernel_vect_code[i]); 125171901Sscottl } 125271901Sscottl /* 125371901Sscottl * We only have this one client and we know that 0x400 is free in 125471901Sscottl * our kernel's mem map, so lets just drop it there. It seems that 125571901Sscottl * the minisrc doesn't need vectors, so we won't bother with them.. 125671901Sscottl */ 1257230985Spfg size = sizeof(gaw_minisrc_code_0400); 125871901Sscottl for(i = 0 ; i < size / 2; i++) { 1259230985Spfg m3_wr_assp_code(sc, 0x400 + i, gaw_minisrc_code_0400[i]); 126071901Sscottl } 126171901Sscottl /* write the coefficients for the low pass filter? */ 1262230985Spfg size = sizeof(minisrc_lpf); 126371901Sscottl for(i = 0; i < size / 2 ; i++) { 126474797Scg m3_wr_assp_code(sc,0x400 + MINISRC_COEF_LOC + i, 1265230985Spfg minisrc_lpf[i]); 126671901Sscottl } 126771901Sscottl m3_wr_assp_code(sc, 0x400 + MINISRC_COEF_LOC + size, 0x8000); 126871901Sscottl /* the minisrc is the only thing on our task list */ 126971901Sscottl m3_wr_assp_data(sc, KDATA_TASK0, 0x400); 127071901Sscottl /* init the mixer number */ 127171901Sscottl m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER, 0); 127271901Sscottl /* extreme kernel master volume */ 1273230985Spfg m3_wr_assp_data(sc, KDATA_DAC_LEFT_VOLUME, M3_DEFAULT_VOL); 1274230985Spfg m3_wr_assp_data(sc, KDATA_DAC_RIGHT_VOLUME, M3_DEFAULT_VOL); 127571901Sscottl 127671901Sscottl m3_amp_enable(sc); 127774797Scg 127871901Sscottl /* [m3_assp_client_init] (only one client at index 0) */ 127971901Sscottl for (i=0x1100 ; i<0x1c00 ; i++) { 128071901Sscottl m3_wr_assp_data(sc, i, 0); /* zero entire dac/adc area */ 128171901Sscottl } 128271901Sscottl 128371901Sscottl /* [m3_assp_continue] */ 128471901Sscottl m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state | REGB_ENABLE_RESET); 128571901Sscottl 128671901Sscottl return 0; 128771901Sscottl} 128871901Sscottl 128971901Sscottlstatic int 129071901Sscottlm3_uninit(struct sc_info *sc) 129171901Sscottl{ 129271901Sscottl M3_DEBUG(CHANGE, ("m3_uninit\n")); 129371901Sscottl return 0; 129471901Sscottl} 129571901Sscottl 129671901Sscottl/* -------------------------------------------------------------------- */ 129771901Sscottl/* Probe and attach the card */ 129871901Sscottl 129971901Sscottlstatic int 130071901Sscottlm3_pci_probe(device_t dev) 130171901Sscottl{ 130271901Sscottl struct m3_card_type *card; 130374797Scg 130471901Sscottl M3_DEBUG(CALL, ("m3_pci_probe(0x%x)\n", pci_get_devid(dev))); 130571901Sscottl 130671901Sscottl for (card = m3_card_types ; card->pci_id ; card++) { 130771901Sscottl if (pci_get_devid(dev) == card->pci_id) { 130871901Sscottl device_set_desc(dev, card->name); 1309142890Simp return BUS_PROBE_DEFAULT; 131071901Sscottl } 131171901Sscottl } 131271901Sscottl return ENXIO; 131371901Sscottl} 131471901Sscottl 131571901Sscottlstatic int 131671901Sscottlm3_pci_attach(device_t dev) 131771901Sscottl{ 131871901Sscottl struct sc_info *sc; 131971901Sscottl struct ac97_info *codec = NULL; 132071901Sscottl char status[SND_STATUSLEN]; 132171901Sscottl struct m3_card_type *card; 1322167355Sariff int i, len, dacn, adcn; 132374797Scg 132471901Sscottl M3_DEBUG(CALL, ("m3_pci_attach\n")); 132571901Sscottl 1326170873Sariff sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); 132771901Sscottl sc->dev = dev; 132871901Sscottl sc->type = pci_get_devid(dev); 1329146514Syongari sc->sc_lock = snd_mtxcreate(device_get_nameunit(dev), 1330167608Sariff "snd_maestro3 softc"); 133171901Sscottl for (card = m3_card_types ; card->pci_id ; card++) { 133271901Sscottl if (sc->type == card->pci_id) { 133371901Sscottl sc->which = card->which; 133471901Sscottl sc->delay1 = card->delay1; 133571901Sscottl sc->delay2 = card->delay2; 133671901Sscottl break; 133771901Sscottl } 133871901Sscottl } 133971901Sscottl 1340167355Sariff if (resource_int_value(device_get_name(dev), device_get_unit(dev), 1341167355Sariff "dac", &i) == 0) { 1342167355Sariff if (i < 1) 1343167355Sariff dacn = 1; 1344167355Sariff else if (i > M3_PCHANS) 1345167355Sariff dacn = M3_PCHANS; 1346167355Sariff else 1347167355Sariff dacn = i; 1348167355Sariff } else 1349167355Sariff dacn = M3_PCHANS; 1350167355Sariff 1351167355Sariff adcn = M3_RCHANS; 1352167355Sariff 1353254306Sscottl pci_enable_busmaster(dev); 135471901Sscottl 1355119690Sjhb sc->regid = PCIR_BAR(0); 135671901Sscottl sc->regtype = SYS_RES_MEMORY; 1357127135Snjl sc->reg = bus_alloc_resource_any(dev, sc->regtype, &sc->regid, 1358127135Snjl RF_ACTIVE); 135971901Sscottl if (!sc->reg) { 136071901Sscottl sc->regtype = SYS_RES_IOPORT; 1361127135Snjl sc->reg = bus_alloc_resource_any(dev, sc->regtype, &sc->regid, 1362127135Snjl RF_ACTIVE); 136371901Sscottl } 136471901Sscottl if (!sc->reg) { 136571901Sscottl device_printf(dev, "unable to allocate register space\n"); 136671901Sscottl goto bad; 136771901Sscottl } 136871901Sscottl sc->st = rman_get_bustag(sc->reg); 136971901Sscottl sc->sh = rman_get_bushandle(sc->reg); 137071901Sscottl 137171901Sscottl sc->irqid = 0; 1372127135Snjl sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, 1373127135Snjl RF_ACTIVE | RF_SHAREABLE); 137471901Sscottl if (!sc->irq) { 137571901Sscottl device_printf(dev, "unable to allocate interrupt\n"); 137671901Sscottl goto bad; 137771901Sscottl } 137871901Sscottl 1379146514Syongari if (snd_setup_intr(dev, sc->irq, INTR_MPSAFE, m3_intr, sc, &sc->ih)) { 138071901Sscottl device_printf(dev, "unable to setup interrupt\n"); 138171901Sscottl goto bad; 138271901Sscottl } 138371901Sscottl 1384167355Sariff sc->bufsz = pcm_getbuffersize(dev, M3_BUFSIZE_MIN, M3_BUFSIZE_DEFAULT, 1385146514Syongari M3_BUFSIZE_MAX); 138684731Sscottl 1387146514Syongari if (bus_dma_tag_create( 1388166904Snetchild bus_get_dma_tag(dev), /* parent */ 1389146514Syongari 2, 0, /* alignment, boundary */ 1390146514Syongari M3_MAXADDR, /* lowaddr */ 1391146514Syongari BUS_SPACE_MAXADDR, /* highaddr */ 1392146514Syongari NULL, NULL, /* filtfunc, filtfuncarg */ 1393146514Syongari sc->bufsz, /* maxsize */ 1394146514Syongari 1, /* nsegments */ 1395146514Syongari 0x3ffff, /* maxsegz */ 1396146514Syongari 0, /* flags */ 1397146514Syongari NULL, /* lockfunc */ 1398146514Syongari NULL, /* lockfuncarg */ 1399146514Syongari &sc->parent_dmat) != 0) { 140071901Sscottl device_printf(dev, "unable to create dma tag\n"); 140171901Sscottl goto bad; 140271901Sscottl } 140371901Sscottl 1404146514Syongari M3_LOCK(sc); 140571901Sscottl m3_power(sc, 0); /* power up */ 140671901Sscottl /* init chip */ 1407146514Syongari i = m3_init(sc); 1408146514Syongari M3_UNLOCK(sc); 1409146514Syongari if (i == -1) { 141071901Sscottl device_printf(dev, "unable to initialize the card\n"); 141171901Sscottl goto bad; 141271901Sscottl } 141371901Sscottl 141471901Sscottl /* create/init mixer */ 141571901Sscottl codec = AC97_CREATE(dev, sc, m3_codec); 141671901Sscottl if (codec == NULL) { 141771901Sscottl device_printf(dev, "ac97_create error\n"); 141871901Sscottl goto bad; 141971901Sscottl } 142071901Sscottl if (mixer_init(dev, ac97_getmixerclass(), codec)) { 142171901Sscottl device_printf(dev, "mixer_init error\n"); 142271901Sscottl goto bad; 142371901Sscottl } 142471901Sscottl 142598764Srobert m3_enable_ints(sc); 142698764Srobert 1427167355Sariff if (pcm_register(dev, sc, dacn, adcn)) { 142871901Sscottl device_printf(dev, "pcm_register error\n"); 142971901Sscottl goto bad; 143071901Sscottl } 1431167355Sariff for (i=0 ; i<dacn ; i++) { 143271901Sscottl if (pcm_addchan(dev, PCMDIR_PLAY, &m3_pch_class, sc)) { 143371901Sscottl device_printf(dev, "pcm_addchan (play) error\n"); 143471901Sscottl goto bad; 143571901Sscottl } 143671901Sscottl } 1437167355Sariff for (i=0 ; i<adcn ; i++) { 143871901Sscottl if (pcm_addchan(dev, PCMDIR_REC, &m3_rch_class, sc)) { 143971901Sscottl device_printf(dev, "pcm_addchan (rec) error\n"); 144071901Sscottl goto bad; 144171901Sscottl } 144271901Sscottl } 1443126695Smatk snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s", 1444146514Syongari (sc->regtype == SYS_RES_IOPORT)? "io" : "memory", 1445146514Syongari rman_get_start(sc->reg), rman_get_start(sc->irq), 1446146514Syongari PCM_KLDSTRING(snd_maestro3)); 144771901Sscottl if (pcm_setstatus(dev, status)) { 144871901Sscottl device_printf(dev, "attach: pcm_setstatus error\n"); 144971901Sscottl goto bad; 145071901Sscottl } 145184926Sscottl 145274763Scg mixer_hwvol_init(dev); 145371901Sscottl 145471901Sscottl /* Create the buffer for saving the card state during suspend */ 145574797Scg len = sizeof(u_int16_t) * (REV_B_CODE_MEMORY_LENGTH + 145671901Sscottl REV_B_DATA_MEMORY_LENGTH); 1457170873Sariff sc->savemem = (u_int16_t*)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 145871901Sscottl 145971901Sscottl return 0; 146071901Sscottl 146171901Sscottl bad: 1462146514Syongari if (codec) 146371901Sscottl ac97_destroy(codec); 1464146514Syongari if (sc->ih) 146571901Sscottl bus_teardown_intr(dev, sc->irq, sc->ih); 1466146514Syongari if (sc->irq) 146771901Sscottl bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 1468146514Syongari if (sc->reg) 1469146514Syongari bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); 1470146514Syongari if (sc->parent_dmat) 147171901Sscottl bus_dma_tag_destroy(sc->parent_dmat); 1472146514Syongari if (sc->sc_lock) 1473146514Syongari snd_mtxfree(sc->sc_lock); 147471901Sscottl free(sc, M_DEVBUF); 147571901Sscottl return ENXIO; 147671901Sscottl} 147771901Sscottl 147871901Sscottlstatic int 147971901Sscottlm3_pci_detach(device_t dev) 148071901Sscottl{ 148171901Sscottl struct sc_info *sc = pcm_getdevinfo(dev); 148271901Sscottl int r; 148371901Sscottl 148471901Sscottl M3_DEBUG(CALL, ("m3_pci_detach\n")); 148571901Sscottl 148671901Sscottl if ((r = pcm_unregister(dev)) != 0) { 148771901Sscottl return r; 148871901Sscottl } 1489146514Syongari 1490146514Syongari M3_LOCK(sc); 149171901Sscottl m3_uninit(sc); /* shutdown chip */ 149271901Sscottl m3_power(sc, 3); /* power off */ 1493146514Syongari M3_UNLOCK(sc); 149471901Sscottl 149571901Sscottl bus_teardown_intr(dev, sc->irq, sc->ih); 149671901Sscottl bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 1497146514Syongari bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); 149871901Sscottl bus_dma_tag_destroy(sc->parent_dmat); 149971901Sscottl 150071901Sscottl free(sc->savemem, M_DEVBUF); 1501146514Syongari snd_mtxfree(sc->sc_lock); 150271901Sscottl free(sc, M_DEVBUF); 150371901Sscottl return 0; 150471901Sscottl} 150571901Sscottl 150671901Sscottlstatic int 150771901Sscottlm3_pci_suspend(device_t dev) 150871901Sscottl{ 150971901Sscottl struct sc_info *sc = pcm_getdevinfo(dev); 151071901Sscottl int i, index = 0; 151171901Sscottl 151271901Sscottl M3_DEBUG(CHANGE, ("m3_pci_suspend\n")); 151371901Sscottl 1514146514Syongari M3_LOCK(sc); 151571901Sscottl for (i=0 ; i<sc->pch_cnt ; i++) { 151671901Sscottl if (sc->pch[i].active) { 1517146514Syongari m3_pchan_trigger_locked(NULL, &sc->pch[i], 1518146514Syongari PCMTRIG_STOP); 151971901Sscottl } 152071901Sscottl } 152171901Sscottl for (i=0 ; i<sc->rch_cnt ; i++) { 152271901Sscottl if (sc->rch[i].active) { 1523146514Syongari m3_rchan_trigger_locked(NULL, &sc->rch[i], 1524146514Syongari PCMTRIG_STOP); 152571901Sscottl } 152671901Sscottl } 152771901Sscottl DELAY(10 * 1000); /* give things a chance to stop */ 152871901Sscottl 152971901Sscottl /* Disable interrupts */ 153071901Sscottl m3_wr_2(sc, HOST_INT_CTRL, 0); 153171901Sscottl m3_wr_1(sc, ASSP_CONTROL_C, 0); 153271901Sscottl 153371901Sscottl m3_assp_halt(sc); 153471901Sscottl 153571901Sscottl /* Save the state of the ASSP */ 153671901Sscottl for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++) 1537102578Sscottl sc->savemem[index++] = m3_rd_assp_code(sc, i); 153871901Sscottl for (i = REV_B_DATA_MEMORY_BEGIN; i <= REV_B_DATA_MEMORY_END; i++) 1539102578Sscottl sc->savemem[index++] = m3_rd_assp_data(sc, i); 154071901Sscottl 154171901Sscottl /* Power down the card to D3 state */ 154271901Sscottl m3_power(sc, 3); 1543146514Syongari M3_UNLOCK(sc); 154471901Sscottl 154571901Sscottl return 0; 154671901Sscottl} 154771901Sscottl 154871901Sscottlstatic int 154971901Sscottlm3_pci_resume(device_t dev) 155071901Sscottl{ 155171901Sscottl struct sc_info *sc = pcm_getdevinfo(dev); 155271901Sscottl int i, index = 0; 155371901Sscottl u_int8_t reset_state; 155471901Sscottl 155571901Sscottl M3_DEBUG(CHANGE, ("m3_pci_resume\n")); 155671901Sscottl 1557146514Syongari M3_LOCK(sc); 155871901Sscottl /* Power the card back to D0 */ 155971901Sscottl m3_power(sc, 0); 156071901Sscottl 156171901Sscottl m3_config(sc); 156274797Scg 156371901Sscottl reset_state = m3_assp_halt(sc); 156471901Sscottl 156587393Sguido m3_codec_reset(sc); 156687393Sguido 156771901Sscottl /* Restore the ASSP state */ 156871901Sscottl for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++) 1569102924Sscottl m3_wr_assp_code(sc, i, sc->savemem[index++]); 157071901Sscottl for (i = REV_B_DATA_MEMORY_BEGIN; i <= REV_B_DATA_MEMORY_END; i++) 1571102924Sscottl m3_wr_assp_data(sc, i, sc->savemem[index++]); 157271901Sscottl 157371901Sscottl /* Restart the DMA engine */ 157471901Sscottl m3_wr_assp_data(sc, KDATA_DMA_ACTIVE, 0); 157571901Sscottl 157671901Sscottl /* [m3_assp_continue] */ 157771901Sscottl m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state | REGB_ENABLE_RESET); 157871901Sscottl 157971901Sscottl m3_amp_enable(sc); 158071901Sscottl 158199586Srobert m3_enable_ints(sc); 158299586Srobert 1583146514Syongari M3_UNLOCK(sc); /* XXX */ 158487393Sguido if (mixer_reinit(dev) == -1) { 158587393Sguido device_printf(dev, "unable to reinitialize the mixer\n"); 1586146514Syongari return (ENXIO); 158787393Sguido } 1588146514Syongari M3_LOCK(sc); 158987393Sguido 159071901Sscottl /* Turn the channels back on */ 159171901Sscottl for (i=0 ; i<sc->pch_cnt ; i++) { 159271901Sscottl if (sc->pch[i].active) { 1593146514Syongari m3_pchan_trigger_locked(NULL, &sc->pch[i], 1594146514Syongari PCMTRIG_START); 159571901Sscottl } 159671901Sscottl } 159771901Sscottl for (i=0 ; i<sc->rch_cnt ; i++) { 159871901Sscottl if (sc->rch[i].active) { 1599146514Syongari m3_rchan_trigger_locked(NULL, &sc->rch[i], 1600146514Syongari PCMTRIG_START); 160171901Sscottl } 160271901Sscottl } 160371901Sscottl 1604146514Syongari M3_UNLOCK(sc); 160571901Sscottl return 0; 160671901Sscottl} 160771901Sscottl 160871901Sscottlstatic int 160971901Sscottlm3_pci_shutdown(device_t dev) 161071901Sscottl{ 161171901Sscottl struct sc_info *sc = pcm_getdevinfo(dev); 161274797Scg 161371901Sscottl M3_DEBUG(CALL, ("m3_pci_shutdown\n")); 161471901Sscottl 1615146514Syongari M3_LOCK(sc); 161671901Sscottl m3_power(sc, 3); /* power off */ 1617146514Syongari M3_UNLOCK(sc); 1618146514Syongari 161971901Sscottl return 0; 162071901Sscottl} 162171901Sscottl 162271901Sscottlstatic u_int8_t 162371901Sscottlm3_assp_halt(struct sc_info *sc) 162471901Sscottl{ 162571901Sscottl u_int8_t data, reset_state; 162671901Sscottl 1627146514Syongari M3_LOCK_ASSERT(sc); 1628146514Syongari 162971901Sscottl data = m3_rd_1(sc, DSP_PORT_CONTROL_REG_B); 163071901Sscottl reset_state = data & ~REGB_STOP_CLOCK; /* remember for continue */ 163171901Sscottl DELAY(10 * 1000); 163271901Sscottl m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state & ~REGB_ENABLE_RESET); 163371901Sscottl DELAY(10 * 1000); /* necessary? */ 163471901Sscottl 163571901Sscottl return reset_state; 163671901Sscottl} 163771901Sscottl 163871901Sscottlstatic void 163971901Sscottlm3_config(struct sc_info *sc) 164071901Sscottl{ 164184926Sscottl u_int32_t data, hv_cfg; 164284926Sscottl int hint; 164371901Sscottl 1644146514Syongari M3_LOCK_ASSERT(sc); 1645150075Syongari 1646150075Syongari M3_UNLOCK(sc); 164784926Sscottl /* 164884926Sscottl * The volume buttons can be wired up via two different sets of pins. 164984926Sscottl * This presents a problem since we can't tell which way it's 165084926Sscottl * configured. Allow the user to set a hint in order to twiddle 165184926Sscottl * the proper bits. 165284926Sscottl */ 165384926Sscottl if (resource_int_value(device_get_name(sc->dev), 165484926Sscottl device_get_unit(sc->dev), 165584926Sscottl "hwvol_config", &hint) == 0) 165684926Sscottl hv_cfg = (hint > 0) ? HV_BUTTON_FROM_GD : 0; 165784926Sscottl else 165884926Sscottl hv_cfg = HV_BUTTON_FROM_GD; 1659150075Syongari M3_LOCK(sc); 166084926Sscottl 166171901Sscottl data = pci_read_config(sc->dev, PCI_ALLEGRO_CONFIG, 4); 166298961Sscottl data &= ~HV_BUTTON_FROM_GD; 166384926Sscottl data |= REDUCED_DEBOUNCE | HV_CTRL_ENABLE | hv_cfg; 166471901Sscottl data |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; 166571901Sscottl pci_write_config(sc->dev, PCI_ALLEGRO_CONFIG, data, 4); 166671901Sscottl 166771901Sscottl m3_wr_1(sc, ASSP_CONTROL_B, RESET_ASSP); 166871901Sscottl data = pci_read_config(sc->dev, PCI_ALLEGRO_CONFIG, 4); 166971901Sscottl data &= ~INT_CLK_SELECT; 167071901Sscottl if (sc->which == ESS_MAESTRO3) { 167171901Sscottl data &= ~INT_CLK_MULT_ENABLE; 167271901Sscottl data |= INT_CLK_SRC_NOT_PCI; 167371901Sscottl } 167471901Sscottl data &= ~(CLK_MULT_MODE_SELECT | CLK_MULT_MODE_SELECT_2); 167571901Sscottl pci_write_config(sc->dev, PCI_ALLEGRO_CONFIG, data, 4); 167671901Sscottl 167771901Sscottl if (sc->which == ESS_ALLEGRO_1) { 167871901Sscottl data = pci_read_config(sc->dev, PCI_USER_CONFIG, 4); 167971901Sscottl data |= IN_CLK_12MHZ_SELECT; 168071901Sscottl pci_write_config(sc->dev, PCI_USER_CONFIG, data, 4); 168171901Sscottl } 168271901Sscottl 168371901Sscottl data = m3_rd_1(sc, ASSP_CONTROL_A); 168471901Sscottl data &= ~(DSP_CLK_36MHZ_SELECT | ASSP_CLK_49MHZ_SELECT); 168571901Sscottl data |= ASSP_CLK_49MHZ_SELECT; /*XXX assumes 49MHZ dsp XXX*/ 168671901Sscottl data |= ASSP_0_WS_ENABLE; 168771901Sscottl m3_wr_1(sc, ASSP_CONTROL_A, data); 168871901Sscottl 168971901Sscottl m3_wr_1(sc, ASSP_CONTROL_B, RUN_ASSP); 169071901Sscottl} 169171901Sscottl 169271901Sscottlstatic void 169371901Sscottlm3_enable_ints(struct sc_info *sc) 169471901Sscottl{ 169571901Sscottl u_int8_t data; 169671901Sscottl 169771901Sscottl m3_wr_2(sc, HOST_INT_CTRL, ASSP_INT_ENABLE | HV_INT_ENABLE); 169871901Sscottl data = m3_rd_1(sc, ASSP_CONTROL_C); 169971901Sscottl m3_wr_1(sc, ASSP_CONTROL_C, data | ASSP_HOST_INT_ENABLE); 170071901Sscottl} 170171901Sscottl 170271901Sscottlstatic void 170371901Sscottlm3_amp_enable(struct sc_info *sc) 170471901Sscottl{ 170571901Sscottl u_int32_t gpo, polarity_port, polarity; 170671901Sscottl u_int16_t data; 170771901Sscottl 1708146514Syongari M3_LOCK_ASSERT(sc); 1709146514Syongari 171071901Sscottl switch (sc->which) { 171171901Sscottl case ESS_ALLEGRO_1: 171271901Sscottl polarity_port = 0x1800; 171371901Sscottl break; 171471901Sscottl case ESS_MAESTRO3: 171571901Sscottl polarity_port = 0x1100; 171671901Sscottl break; 171771901Sscottl default: 171871901Sscottl panic("bad sc->which"); 171971901Sscottl } 172071901Sscottl gpo = (polarity_port >> 8) & 0x0f; 172171901Sscottl polarity = polarity_port >> 12; 172271901Sscottl polarity = !polarity; /* enable */ 172371901Sscottl polarity = polarity << gpo; 172471901Sscottl gpo = 1 << gpo; 172571901Sscottl m3_wr_2(sc, GPIO_MASK, ~gpo); 172671901Sscottl data = m3_rd_2(sc, GPIO_DIRECTION); 172771901Sscottl m3_wr_2(sc, GPIO_DIRECTION, data | gpo); 172871901Sscottl data = GPO_SECONDARY_AC97 | GPO_PRIMARY_AC97 | polarity; 172971901Sscottl m3_wr_2(sc, GPIO_DATA, data); 173071901Sscottl m3_wr_2(sc, GPIO_MASK, ~0); 173171901Sscottl} 173271901Sscottl 173371901Sscottlstatic void 173471901Sscottlm3_codec_reset(struct sc_info *sc) 173571901Sscottl{ 173671901Sscottl u_int16_t data, dir; 173771901Sscottl int retry = 0; 173871901Sscottl 1739146514Syongari M3_LOCK_ASSERT(sc); 174071901Sscottl do { 174171901Sscottl data = m3_rd_2(sc, GPIO_DIRECTION); 174271901Sscottl dir = data | 0x10; /* assuming pci bus master? */ 174371901Sscottl 174471901Sscottl /* [[remote_codec_config]] */ 174571901Sscottl data = m3_rd_2(sc, RING_BUS_CTRL_B); 174671901Sscottl m3_wr_2(sc, RING_BUS_CTRL_B, data & ~SECOND_CODEC_ID_MASK); 174771901Sscottl data = m3_rd_2(sc, SDO_OUT_DEST_CTRL); 174871901Sscottl m3_wr_2(sc, SDO_OUT_DEST_CTRL, data & ~COMMAND_ADDR_OUT); 174971901Sscottl data = m3_rd_2(sc, SDO_IN_DEST_CTRL); 175071901Sscottl m3_wr_2(sc, SDO_IN_DEST_CTRL, data & ~STATUS_ADDR_IN); 175174797Scg 175271901Sscottl m3_wr_2(sc, RING_BUS_CTRL_A, IO_SRAM_ENABLE); 175371901Sscottl DELAY(20); 175474797Scg 175571901Sscottl m3_wr_2(sc, GPIO_DIRECTION, dir & ~GPO_PRIMARY_AC97); 175671901Sscottl m3_wr_2(sc, GPIO_MASK, ~GPO_PRIMARY_AC97); 175771901Sscottl m3_wr_2(sc, GPIO_DATA, 0); 175871901Sscottl m3_wr_2(sc, GPIO_DIRECTION, dir | GPO_PRIMARY_AC97); 175971901Sscottl DELAY(sc->delay1 * 1000); /*delay1 (ALLEGRO:50, MAESTRO3:20)*/ 176071901Sscottl m3_wr_2(sc, GPIO_DATA, GPO_PRIMARY_AC97); 176171901Sscottl DELAY(5); 176274797Scg m3_wr_2(sc, RING_BUS_CTRL_A, IO_SRAM_ENABLE | 176371901Sscottl SERIAL_AC_LINK_ENABLE); 176471901Sscottl m3_wr_2(sc, GPIO_MASK, ~0); 176571901Sscottl DELAY(sc->delay2 * 1000); /*delay2 (ALLEGRO:800, MAESTRO3:500)*/ 176674797Scg 176771901Sscottl /* [[try read vendor]] */ 176871901Sscottl data = m3_rdcd(NULL, sc, 0x7c); 176971901Sscottl if ((data == 0) || (data == 0xffff)) { 177071901Sscottl retry++; 177171901Sscottl if (retry > 3) { 177271901Sscottl device_printf(sc->dev, "Codec reset failed\n"); 177371901Sscottl break; 177471901Sscottl } 177571901Sscottl device_printf(sc->dev, "Codec reset retry\n"); 177671901Sscottl } else retry = 0; 177771901Sscottl } while (retry); 177871901Sscottl} 177971901Sscottl 178071901Sscottlstatic device_method_t m3_methods[] = { 178171901Sscottl DEVMETHOD(device_probe, m3_pci_probe), 178271901Sscottl DEVMETHOD(device_attach, m3_pci_attach), 178371901Sscottl DEVMETHOD(device_detach, m3_pci_detach), 178471901Sscottl DEVMETHOD(device_suspend, m3_pci_suspend), 178571901Sscottl DEVMETHOD(device_resume, m3_pci_resume), 178671901Sscottl DEVMETHOD(device_shutdown, m3_pci_shutdown), 178771901Sscottl { 0, 0 } 178871901Sscottl}; 178971901Sscottl 179071901Sscottlstatic driver_t m3_driver = { 179171901Sscottl "pcm", 179271901Sscottl m3_methods, 179382180Scg PCM_SOFTC_SIZE, 179471901Sscottl}; 179571901Sscottl 179671901SscottlDRIVER_MODULE(snd_maestro3, pci, m3_driver, pcm_devclass, 0, 0); 1797132236StanimuraMODULE_DEPEND(snd_maestro3, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 179871901SscottlMODULE_VERSION(snd_maestro3, 1); 1799