1a5108eaeSScott Long /*- 2a5108eaeSScott Long * Copyright (c) 2001 Scott Long <scottl@freebsd.org> 3a5108eaeSScott Long * Copyright (c) 2001 Darrell Anderson <anderson@cs.duke.edu> 4a5108eaeSScott Long * All rights reserved. 5a5108eaeSScott Long * 6a5108eaeSScott Long * Redistribution and use in source and binary forms, with or without 7a5108eaeSScott Long * modification, are permitted provided that the following conditions 8a5108eaeSScott Long * are met: 9a5108eaeSScott Long * 1. Redistributions of source code must retain the above copyright 10a5108eaeSScott Long * notice, this list of conditions and the following disclaimer. 11a5108eaeSScott Long * 2. Redistributions in binary form must reproduce the above copyright 12a5108eaeSScott Long * notice, this list of conditions and the following disclaimer in the 13a5108eaeSScott Long * documentation and/or other materials provided with the distribution. 14a5108eaeSScott Long * 15a5108eaeSScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16a5108eaeSScott Long * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17a5108eaeSScott Long * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18a5108eaeSScott Long * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19a5108eaeSScott Long * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20a5108eaeSScott Long * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21a5108eaeSScott Long * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22a5108eaeSScott Long * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23a5108eaeSScott Long * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24a5108eaeSScott Long * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25a5108eaeSScott Long * SUCH DAMAGE. 26a5108eaeSScott Long * 27a5108eaeSScott Long * $FreeBSD$ 28a5108eaeSScott Long */ 29a5108eaeSScott Long 30a5108eaeSScott Long /* 31a5108eaeSScott Long * Maestro-3/Allegro FreeBSD pcm sound driver 32a5108eaeSScott Long * 33a5108eaeSScott Long * executive status summary: 34a5108eaeSScott Long * (+) /dev/dsp multiple concurrent play channels. 35a5108eaeSScott Long * (+) /dev/dsp config (speed, mono/stereo, 8/16 bit). 36a5108eaeSScott Long * (+) /dev/mixer sets left/right volumes. 37a5108eaeSScott Long * (+) /dev/dsp recording works. Tested successfully with the cdrom channel 38a5108eaeSScott Long * (+) apm suspend/resume works, and works properly!. 39a5108eaeSScott Long * (-) hardware volme controls don't work =-( 40a5108eaeSScott Long * (-) setblocksize() does nothing. 41a5108eaeSScott Long * 42a5108eaeSScott Long * The real credit goes to: 43a5108eaeSScott Long * 44a5108eaeSScott Long * Zach Brown for his Linux driver core and helpful technical comments. 45a5108eaeSScott Long * <zab@zabbo.net>, http://www.zabbo.net/maestro3 46a5108eaeSScott Long * 47a5108eaeSScott Long * Cameron Grant created the pcm framework used here nearly verbatim. 48a5108eaeSScott Long * <cg@freebsd.org>, http://people.freebsd.org/~cg/template.c 49a5108eaeSScott Long * 50a5108eaeSScott Long * Taku YAMAMOTO for his Maestro-1/2 FreeBSD driver and sanity reference. 51a5108eaeSScott Long * <taku@cent.saitama-u.ac.jp> 52a5108eaeSScott Long * 53a5108eaeSScott Long * ESS docs explained a few magic registers and numbers. 54a5108eaeSScott Long * http://virgo.caltech.edu/~dmoore/maestro3.pdf.gz 55a5108eaeSScott Long */ 56a5108eaeSScott Long 57a5108eaeSScott Long #include <dev/sound/pcm/sound.h> 58a5108eaeSScott Long #include <dev/sound/pcm/ac97.h> 59a5108eaeSScott Long 60a5108eaeSScott Long #include <pci/pcireg.h> 61a5108eaeSScott Long #include <pci/pcivar.h> 62a5108eaeSScott Long 63a5108eaeSScott Long #include <gnu/dev/sound/pci/maestro3_reg.h> 64a5108eaeSScott Long #include <gnu/dev/sound/pci/maestro3_dsp.h> 65a5108eaeSScott Long 66a5108eaeSScott Long /* -------------------------------------------------------------------- */ 67a5108eaeSScott Long 68a5108eaeSScott Long enum {CHANGE=0, CALL=1, INTR=2, BORING=3, NONE=-1}; 69a5108eaeSScott Long #ifndef M3_DEBUG_LEVEL 70a5108eaeSScott Long #define M3_DEBUG_LEVEL NONE 71a5108eaeSScott Long #endif 72a5108eaeSScott Long #define M3_DEBUG(level, _msg) {if ((level) <= M3_DEBUG_LEVEL) {printf _msg;}} 73a5108eaeSScott Long 74a5108eaeSScott Long /* -------------------------------------------------------------------- */ 75a5108eaeSScott Long enum { 76a5108eaeSScott Long ESS_ALLEGRO_1, 77a5108eaeSScott Long ESS_MAESTRO3 78a5108eaeSScott Long }; 79a5108eaeSScott Long 80a5108eaeSScott Long static struct m3_card_type { 81a5108eaeSScott Long u_int32_t pci_id; int which; int delay1; int delay2; char *name; 82a5108eaeSScott Long } m3_card_types[] = { 83a5108eaeSScott Long { 0x1988125d, ESS_ALLEGRO_1, 50, 800, "ESS Technology Allegro-1" }, 84a5108eaeSScott Long { 0x1998125d, ESS_MAESTRO3, 20, 500, "ESS Technology Maestro3" }, 85a5108eaeSScott Long { 0x199a125d, ESS_MAESTRO3, 20, 500, "ESS Technology Maestro3" }, 86a5108eaeSScott Long { 0, 0, 0, 0, NULL } 87a5108eaeSScott Long }; 88a5108eaeSScott Long 89a5108eaeSScott Long #define M3_BUFSIZE 4096 90a5108eaeSScott Long #define M3_PCHANS 4 /* create /dev/dsp0.[0-N] to use more than one */ 91a5108eaeSScott Long #define M3_RCHANS 1 92a5108eaeSScott Long 93a5108eaeSScott Long struct sc_info; 94a5108eaeSScott Long 95a5108eaeSScott Long struct sc_pchinfo { 96a5108eaeSScott Long u_int32_t spd; 97a5108eaeSScott Long u_int32_t fmt; 98a5108eaeSScott Long snd_dbuf *buffer; 99a5108eaeSScott Long pcm_channel *channel; 100a5108eaeSScott Long struct sc_info *parent; 101a5108eaeSScott Long u_int32_t bufsize; 102a5108eaeSScott Long u_int32_t dac_data; 103a5108eaeSScott Long u_int32_t dac_idx; 104a5108eaeSScott Long u_int32_t active; 105a5108eaeSScott Long }; 106a5108eaeSScott Long 107a5108eaeSScott Long struct sc_rchinfo { 108a5108eaeSScott Long u_int32_t spd; 109a5108eaeSScott Long u_int32_t fmt; 110a5108eaeSScott Long snd_dbuf *buffer; 111a5108eaeSScott Long pcm_channel *channel; 112a5108eaeSScott Long struct sc_info *parent; 113a5108eaeSScott Long u_int32_t bufsize; 114a5108eaeSScott Long u_int32_t adc_data; 115a5108eaeSScott Long u_int32_t adc_idx; 116a5108eaeSScott Long u_int32_t active; 117a5108eaeSScott Long }; 118a5108eaeSScott Long 119a5108eaeSScott Long struct sc_info { 120a5108eaeSScott Long device_t dev; 121a5108eaeSScott Long u_int32_t type; 122a5108eaeSScott Long int which; 123a5108eaeSScott Long int delay1; 124a5108eaeSScott Long int delay2; 125a5108eaeSScott Long 126a5108eaeSScott Long bus_space_tag_t st; 127a5108eaeSScott Long bus_space_handle_t sh; 128a5108eaeSScott Long bus_dma_tag_t parent_dmat; 129a5108eaeSScott Long 130a5108eaeSScott Long struct resource *reg; 131a5108eaeSScott Long struct resource *irq; 132a5108eaeSScott Long int regtype; 133a5108eaeSScott Long int regid; 134a5108eaeSScott Long int irqid; 135a5108eaeSScott Long void *ih; 136a5108eaeSScott Long 137a5108eaeSScott Long struct sc_pchinfo pch[M3_PCHANS]; 138a5108eaeSScott Long struct sc_rchinfo rch[M3_RCHANS]; 139a5108eaeSScott Long int pch_cnt; 140a5108eaeSScott Long int rch_cnt; 141a5108eaeSScott Long int pch_active_cnt; 142a5108eaeSScott Long u_int16_t *savemem; 143a5108eaeSScott Long }; 144a5108eaeSScott Long 145a5108eaeSScott Long /* -------------------------------------------------------------------- */ 146a5108eaeSScott Long 147a5108eaeSScott Long /* play channel interface */ 148a5108eaeSScott Long static void *m3_pchan_init(kobj_t, void *, snd_dbuf *, pcm_channel *, int); 149a5108eaeSScott Long static int m3_pchan_free(kobj_t, void *); 150a5108eaeSScott Long static int m3_pchan_setformat(kobj_t, void *, u_int32_t); 151a5108eaeSScott Long static int m3_pchan_setspeed(kobj_t, void *, u_int32_t); 152a5108eaeSScott Long static int m3_pchan_setblocksize(kobj_t, void *, u_int32_t); 153a5108eaeSScott Long static int m3_pchan_trigger(kobj_t, void *, int); 154a5108eaeSScott Long static int m3_pchan_getptr(kobj_t, void *); 155a5108eaeSScott Long static pcmchan_caps *m3_pchan_getcaps(kobj_t, void *); 156a5108eaeSScott Long 157a5108eaeSScott Long /* record channel interface */ 158a5108eaeSScott Long static void *m3_rchan_init(kobj_t, void *, snd_dbuf *, pcm_channel *, int); 159a5108eaeSScott Long static int m3_rchan_free(kobj_t, void *); 160a5108eaeSScott Long static int m3_rchan_setformat(kobj_t, void *, u_int32_t); 161a5108eaeSScott Long static int m3_rchan_setspeed(kobj_t, void *, u_int32_t); 162a5108eaeSScott Long static int m3_rchan_setblocksize(kobj_t, void *, u_int32_t); 163a5108eaeSScott Long static int m3_rchan_trigger(kobj_t, void *, int); 164a5108eaeSScott Long static int m3_rchan_getptr(kobj_t, void *); 165a5108eaeSScott Long static pcmchan_caps *m3_rchan_getcaps(kobj_t, void *); 166a5108eaeSScott Long 167a5108eaeSScott Long /* talk to the codec - called from ac97.c */ 168a5108eaeSScott Long static int m3_initcd(kobj_t, void *); 169a5108eaeSScott Long static int m3_rdcd(kobj_t, void *, int); 170a5108eaeSScott Long static int m3_wrcd(kobj_t, void *, int, u_int32_t); 171a5108eaeSScott Long 172a5108eaeSScott Long /* stuff */ 173a5108eaeSScott Long static void m3_intr(void *); 174a5108eaeSScott Long static int m3_power(struct sc_info *, int); 175a5108eaeSScott Long static int m3_init(struct sc_info *); 176a5108eaeSScott Long static int m3_uninit(struct sc_info *); 177a5108eaeSScott Long static u_int8_t m3_assp_halt(struct sc_info *); 178a5108eaeSScott Long static void m3_config(struct sc_info *); 179a5108eaeSScott Long static void m3_amp_enable(struct sc_info *); 180a5108eaeSScott Long static void m3_enable_ints(struct sc_info *); 181a5108eaeSScott Long static void m3_codec_reset(struct sc_info *); 182a5108eaeSScott Long 183a5108eaeSScott Long /* -------------------------------------------------------------------- */ 184a5108eaeSScott Long /* Codec descriptor */ 185a5108eaeSScott Long static kobj_method_t m3_codec_methods[] = { 186a5108eaeSScott Long KOBJMETHOD(ac97_init, m3_initcd), 187a5108eaeSScott Long KOBJMETHOD(ac97_read, m3_rdcd), 188a5108eaeSScott Long KOBJMETHOD(ac97_write, m3_wrcd), 189a5108eaeSScott Long { 0, 0 } 190a5108eaeSScott Long }; 191a5108eaeSScott Long AC97_DECLARE(m3_codec); 192a5108eaeSScott Long 193a5108eaeSScott Long /* -------------------------------------------------------------------- */ 194a5108eaeSScott Long /* channel descriptors */ 195a5108eaeSScott Long 196a5108eaeSScott Long static u_int32_t m3_playfmt[] = { 197a5108eaeSScott Long AFMT_U8, 198a5108eaeSScott Long AFMT_STEREO | AFMT_U8, 199a5108eaeSScott Long AFMT_S16_LE, 200a5108eaeSScott Long AFMT_STEREO | AFMT_S16_LE, 201a5108eaeSScott Long 0 202a5108eaeSScott Long }; 203a5108eaeSScott Long static pcmchan_caps m3_playcaps = {8000, 48000, m3_playfmt, 0}; 204a5108eaeSScott Long 205a5108eaeSScott Long static kobj_method_t m3_pch_methods[] = { 206a5108eaeSScott Long KOBJMETHOD(channel_init, m3_pchan_init), 207a5108eaeSScott Long KOBJMETHOD(channel_setformat, m3_pchan_setformat), 208a5108eaeSScott Long KOBJMETHOD(channel_setspeed, m3_pchan_setspeed), 209a5108eaeSScott Long KOBJMETHOD(channel_setblocksize, m3_pchan_setblocksize), 210a5108eaeSScott Long KOBJMETHOD(channel_trigger, m3_pchan_trigger), 211a5108eaeSScott Long KOBJMETHOD(channel_getptr, m3_pchan_getptr), 212a5108eaeSScott Long KOBJMETHOD(channel_getcaps, m3_pchan_getcaps), 213a5108eaeSScott Long KOBJMETHOD(channel_free, m3_pchan_free), 214a5108eaeSScott Long { 0, 0 } 215a5108eaeSScott Long }; 216a5108eaeSScott Long CHANNEL_DECLARE(m3_pch); 217a5108eaeSScott Long 218a5108eaeSScott Long static u_int32_t m3_recfmt[] = { 219a5108eaeSScott Long AFMT_U8, 220a5108eaeSScott Long AFMT_STEREO | AFMT_U8, 221a5108eaeSScott Long AFMT_S16_LE, 222a5108eaeSScott Long AFMT_STEREO | AFMT_S16_LE, 223a5108eaeSScott Long 0 224a5108eaeSScott Long }; 225a5108eaeSScott Long static pcmchan_caps m3_reccaps = {8000, 48000, m3_recfmt, 0}; 226a5108eaeSScott Long 227a5108eaeSScott Long static kobj_method_t m3_rch_methods[] = { 228a5108eaeSScott Long KOBJMETHOD(channel_init, m3_rchan_init), 229a5108eaeSScott Long KOBJMETHOD(channel_setformat, m3_rchan_setformat), 230a5108eaeSScott Long KOBJMETHOD(channel_setspeed, m3_rchan_setspeed), 231a5108eaeSScott Long KOBJMETHOD(channel_setblocksize, m3_rchan_setblocksize), 232a5108eaeSScott Long KOBJMETHOD(channel_trigger, m3_rchan_trigger), 233a5108eaeSScott Long KOBJMETHOD(channel_getptr, m3_rchan_getptr), 234a5108eaeSScott Long KOBJMETHOD(channel_getcaps, m3_rchan_getcaps), 235a5108eaeSScott Long KOBJMETHOD(channel_free, m3_rchan_free), 236a5108eaeSScott Long { 0, 0 } 237a5108eaeSScott Long }; 238a5108eaeSScott Long CHANNEL_DECLARE(m3_rch); 239a5108eaeSScott Long 240a5108eaeSScott Long /* -------------------------------------------------------------------- */ 241a5108eaeSScott Long /* some i/o convenience functions */ 242a5108eaeSScott Long 243a5108eaeSScott Long #define m3_rd_1(sc, regno) bus_space_read_1(sc->st, sc->sh, regno) 244a5108eaeSScott Long #define m3_rd_2(sc, regno) bus_space_read_2(sc->st, sc->sh, regno) 245a5108eaeSScott Long #define m3_rd_4(sc, regno) bus_space_read_4(sc->st, sc->sh, regno) 246a5108eaeSScott Long #define m3_wr_1(sc, regno, data) bus_space_write_1(sc->st, sc->sh, regno, data) 247a5108eaeSScott Long #define m3_wr_2(sc, regno, data) bus_space_write_2(sc->st, sc->sh, regno, data) 248a5108eaeSScott Long #define m3_wr_4(sc, regno, data) bus_space_write_4(sc->st, sc->sh, regno, data) 249a5108eaeSScott Long #define m3_rd_assp_code(sc, index) \ 250a5108eaeSScott Long m3_rd_assp(sc, MEMTYPE_INTERNAL_CODE, index) 251a5108eaeSScott Long #define m3_wr_assp_code(sc, index, data) \ 252a5108eaeSScott Long m3_wr_assp(sc, MEMTYPE_INTERNAL_CODE, index, data) 253a5108eaeSScott Long #define m3_rd_assp_data(sc, index) \ 254a5108eaeSScott Long m3_rd_assp(sc, MEMTYPE_INTERNAL_DATA, index) 255a5108eaeSScott Long #define m3_wr_assp_data(sc, index, data) \ 256a5108eaeSScott Long m3_wr_assp(sc, MEMTYPE_INTERNAL_DATA, index, data) 257a5108eaeSScott Long 258a5108eaeSScott Long static __inline u_int16_t 259a5108eaeSScott Long m3_rd_assp(struct sc_info *sc, u_int16_t region, u_int16_t index) 260a5108eaeSScott Long { 261a5108eaeSScott Long m3_wr_2(sc, DSP_PORT_MEMORY_TYPE, region & MEMTYPE_MASK); 262a5108eaeSScott Long m3_wr_2(sc, DSP_PORT_MEMORY_INDEX, index); 263a5108eaeSScott Long return m3_rd_2(sc, DSP_PORT_MEMORY_DATA); 264a5108eaeSScott Long } 265a5108eaeSScott Long 266a5108eaeSScott Long static __inline void 267a5108eaeSScott Long m3_wr_assp(struct sc_info *sc, u_int16_t region, u_int16_t index, 268a5108eaeSScott Long u_int16_t data) 269a5108eaeSScott Long { 270a5108eaeSScott Long m3_wr_2(sc, DSP_PORT_MEMORY_TYPE, region & MEMTYPE_MASK); 271a5108eaeSScott Long m3_wr_2(sc, DSP_PORT_MEMORY_INDEX, index); 272a5108eaeSScott Long m3_wr_2(sc, DSP_PORT_MEMORY_DATA, data); 273a5108eaeSScott Long } 274a5108eaeSScott Long 275a5108eaeSScott Long static __inline int 276a5108eaeSScott Long m3_wait(struct sc_info *sc) 277a5108eaeSScott Long { 278a5108eaeSScott Long int i; 279a5108eaeSScott Long 280a5108eaeSScott Long for (i=0 ; i<20 ; i++) { 281a5108eaeSScott Long if ((m3_rd_1(sc, CODEC_STATUS) & 1) == 0) { 282a5108eaeSScott Long return 0; 283a5108eaeSScott Long } 284a5108eaeSScott Long DELAY(2); 285a5108eaeSScott Long } 286a5108eaeSScott Long return -1; 287a5108eaeSScott Long } 288a5108eaeSScott Long 289a5108eaeSScott Long /* -------------------------------------------------------------------- */ 290a5108eaeSScott Long /* ac97 codec */ 291a5108eaeSScott Long 292a5108eaeSScott Long static int 293a5108eaeSScott Long m3_initcd(kobj_t kobj, void *devinfo) 294a5108eaeSScott Long { 295a5108eaeSScott Long struct sc_info *sc = (struct sc_info *)devinfo; 296a5108eaeSScott Long u_int32_t data; 297a5108eaeSScott Long 298a5108eaeSScott Long M3_DEBUG(CALL, ("m3_initcd\n")); 299a5108eaeSScott Long 300a5108eaeSScott Long /* init ac-link */ 301a5108eaeSScott Long 302a5108eaeSScott Long data = m3_rd_1(sc, CODEC_COMMAND); 303a5108eaeSScott Long return ((data & 0x1) ? 0 : 1); 304a5108eaeSScott Long } 305a5108eaeSScott Long 306a5108eaeSScott Long static int 307a5108eaeSScott Long m3_rdcd(kobj_t kobj, void *devinfo, int regno) 308a5108eaeSScott Long { 309a5108eaeSScott Long struct sc_info *sc = (struct sc_info *)devinfo; 310a5108eaeSScott Long u_int32_t data; 311a5108eaeSScott Long 312a5108eaeSScott Long if (m3_wait(sc)) { 313a5108eaeSScott Long device_printf(sc->dev, "m3_rdcd timed out.\n"); 314a5108eaeSScott Long return -1; 315a5108eaeSScott Long } 316a5108eaeSScott Long m3_wr_1(sc, CODEC_COMMAND, (regno & 0x7f) | 0x80); 317a5108eaeSScott Long DELAY(21); /* ac97 cycle = 20.8 usec */ 318a5108eaeSScott Long if (m3_wait(sc)) { 319a5108eaeSScott Long device_printf(sc->dev, "m3_rdcd timed out.\n"); 320a5108eaeSScott Long return -1; 321a5108eaeSScott Long } 322a5108eaeSScott Long data = m3_rd_2(sc, CODEC_DATA); 323a5108eaeSScott Long return data; 324a5108eaeSScott Long } 325a5108eaeSScott Long 326a5108eaeSScott Long static int 327a5108eaeSScott Long m3_wrcd(kobj_t kobj, void *devinfo, int regno, u_int32_t data) 328a5108eaeSScott Long { 329a5108eaeSScott Long struct sc_info *sc = (struct sc_info *)devinfo; 330a5108eaeSScott Long if (m3_wait(sc)) { 331a5108eaeSScott Long device_printf(sc->dev, "m3_wrcd timed out.\n"); 332a5108eaeSScott Long return -1;; 333a5108eaeSScott Long } 334a5108eaeSScott Long m3_wr_2(sc, CODEC_DATA, data); 335a5108eaeSScott Long m3_wr_1(sc, CODEC_COMMAND, regno & 0x7f); 336a5108eaeSScott Long return 0; 337a5108eaeSScott Long } 338a5108eaeSScott Long 339a5108eaeSScott Long /* -------------------------------------------------------------------- */ 340a5108eaeSScott Long /* play channel interface */ 341a5108eaeSScott Long 342a5108eaeSScott Long #define LO(x) (((x) & 0x0000ffff) ) 343a5108eaeSScott Long #define HI(x) (((x) & 0xffff0000) >> 16) 344a5108eaeSScott Long 345a5108eaeSScott Long static void * 346a5108eaeSScott Long m3_pchan_init(kobj_t kobj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 347a5108eaeSScott Long { 348a5108eaeSScott Long struct sc_info *sc = devinfo; 349a5108eaeSScott Long struct sc_pchinfo *ch; 350a5108eaeSScott Long u_int32_t bus_addr, i; 351a5108eaeSScott Long 352a5108eaeSScott Long int idx = sc->pch_cnt; /* dac instance number, no active reuse! */ 353a5108eaeSScott Long int data_bytes = (((MINISRC_TMP_BUFFER_SIZE & ~1) + 354a5108eaeSScott Long (MINISRC_IN_BUFFER_SIZE & ~1) + 355a5108eaeSScott Long (MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255) &~ 255; 356a5108eaeSScott Long int dac_data = 0x1100 + (data_bytes * idx); 357a5108eaeSScott Long 358a5108eaeSScott Long int dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x20 * 2); 359a5108eaeSScott Long int dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x20 * 2); 360a5108eaeSScott Long int dsp_in_buf = dac_data + (MINISRC_TMP_BUFFER_SIZE/2); 361a5108eaeSScott Long int dsp_out_buf = dsp_in_buf + (dsp_in_size/2) + 1; 362a5108eaeSScott Long 363a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_pchan_init(dac=%d)\n", idx)); 364a5108eaeSScott Long 365a5108eaeSScott Long if (dir != PCMDIR_PLAY) { 366a5108eaeSScott Long device_printf(sc->dev, "m3_pchan_init not PCMDIR_PLAY\n"); 367a5108eaeSScott Long return NULL; 368a5108eaeSScott Long } 369a5108eaeSScott Long ch = &sc->pch[idx]; 370a5108eaeSScott Long 371a5108eaeSScott Long ch->dac_idx = idx; 372a5108eaeSScott Long ch->dac_data = dac_data; 373a5108eaeSScott Long if (ch->dac_data + data_bytes/2 >= 0x1c00) { 374a5108eaeSScott Long device_printf(sc->dev, "m3_pchan_init: revb mem exhausted\n"); 375a5108eaeSScott Long return NULL; 376a5108eaeSScott Long } 377a5108eaeSScott Long 378a5108eaeSScott Long ch->buffer = b; 379a5108eaeSScott Long ch->parent = sc; 380a5108eaeSScott Long ch->channel = c; 381a5108eaeSScott Long ch->fmt = AFMT_U8; 382a5108eaeSScott Long ch->spd = DSP_DEFAULT_SPEED; 383a5108eaeSScott Long if (sndbuf_alloc(ch->buffer, sc->parent_dmat, M3_BUFSIZE) == -1) { 384a5108eaeSScott Long device_printf(sc->dev, "m3_pchan_init chn_allocbuf failed\n"); 385a5108eaeSScott Long return NULL; 386a5108eaeSScott Long } 387a5108eaeSScott Long ch->bufsize = sndbuf_getsize(ch->buffer); 388a5108eaeSScott Long 389a5108eaeSScott Long /* host dma buffer pointers */ 390a5108eaeSScott Long bus_addr = vtophys(sndbuf_getbuf(ch->buffer)); 391a5108eaeSScott Long if (bus_addr & 3) { 392a5108eaeSScott Long device_printf(sc->dev, "m3_pchan_init unaligned bus_addr\n"); 393a5108eaeSScott Long bus_addr = (bus_addr + 4) & ~3; 394a5108eaeSScott Long } 395a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_ADDRL, LO(bus_addr)); 396a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_ADDRH, HI(bus_addr)); 397a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_END_PLUS_1L, 398a5108eaeSScott Long LO(bus_addr + ch->bufsize)); 399a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_END_PLUS_1H, 400a5108eaeSScott Long HI(bus_addr + ch->bufsize)); 401a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTL, 402a5108eaeSScott Long LO(bus_addr)); 403a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTH, 404a5108eaeSScott Long HI(bus_addr)); 405a5108eaeSScott Long 406a5108eaeSScott Long /* dsp buffers */ 407a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_BEGIN, dsp_in_buf); 408a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_END_PLUS_1, 409a5108eaeSScott Long dsp_in_buf + dsp_in_size/2); 410a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_HEAD, dsp_in_buf); 411a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_TAIL, dsp_in_buf); 412a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_BEGIN, dsp_out_buf); 413a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_END_PLUS_1, 414a5108eaeSScott Long dsp_out_buf + dsp_out_size/2); 415a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_HEAD, dsp_out_buf); 416a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_TAIL, dsp_out_buf); 417a5108eaeSScott Long 418a5108eaeSScott Long /* some per client initializers */ 419a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 12, 420a5108eaeSScott Long ch->dac_data + 40 + 8); 421a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 19, 422a5108eaeSScott Long 0x400 + MINISRC_COEF_LOC); 423a5108eaeSScott Long /* enable or disable low pass filter? (0xff if rate> 45000) */ 424a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 22, 0); 425a5108eaeSScott Long /* tell it which way dma is going? */ 426a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_DMA_CONTROL, 427a5108eaeSScott Long DMACONTROL_AUTOREPEAT + DMAC_PAGE3_SELECTOR + 428a5108eaeSScott Long DMAC_BLOCKF_SELECTOR); 429a5108eaeSScott Long 430a5108eaeSScott Long /* set an armload of static initializers */ 431a5108eaeSScott Long for(i = 0 ; i < (sizeof(pv) / sizeof(pv[0])) ; i++) { 432a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + pv[i].addr, pv[i].val); 433a5108eaeSScott Long } 434a5108eaeSScott Long 435a5108eaeSScott Long /* put us in the packed task lists */ 436a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC + 437a5108eaeSScott Long (sc->pch_cnt + sc->rch_cnt), 438a5108eaeSScott Long ch->dac_data >> DP_SHIFT_COUNT); 439a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_DMA_XFER0 + (sc->pch_cnt + sc->rch_cnt), 440a5108eaeSScott Long ch->dac_data >> DP_SHIFT_COUNT); 441a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_MIXER_XFER0 + sc->pch_cnt, 442a5108eaeSScott Long ch->dac_data >> DP_SHIFT_COUNT); 443a5108eaeSScott Long 444a5108eaeSScott Long m3_pchan_trigger(NULL, ch, PCMTRIG_START); /* gotta start before stop */ 445a5108eaeSScott Long m3_pchan_trigger(NULL, ch, PCMTRIG_STOP); /* silence noise on load */ 446a5108eaeSScott Long 447a5108eaeSScott Long sc->pch_cnt++; 448a5108eaeSScott Long return ch; 449a5108eaeSScott Long } 450a5108eaeSScott Long 451a5108eaeSScott Long static int 452a5108eaeSScott Long m3_pchan_free(kobj_t kobj, void *chdata) 453a5108eaeSScott Long { 454a5108eaeSScott Long struct sc_pchinfo *ch = chdata; 455a5108eaeSScott Long struct sc_info *sc = ch->parent; 456a5108eaeSScott Long 457a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_pchan_free(dac=%d)\n", ch->dac_idx)); 458a5108eaeSScott Long 459a5108eaeSScott Long /* 460a5108eaeSScott Long * should remove this exact instance from the packed lists, but all 461a5108eaeSScott Long * are released at once (and in a stopped state) so this is ok. 462a5108eaeSScott Long */ 463a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC + 464a5108eaeSScott Long (sc->pch_cnt - 1) + sc->rch_cnt, 0); 465a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_DMA_XFER0 + 466a5108eaeSScott Long (sc->pch_cnt - 1) + sc->rch_cnt, 0); 467a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_MIXER_XFER0 + (sc->pch_cnt-1), 0); 468a5108eaeSScott Long 469a5108eaeSScott Long sc->pch_cnt--; 470a5108eaeSScott Long return 0; 471a5108eaeSScott Long } 472a5108eaeSScott Long 473a5108eaeSScott Long static int 474a5108eaeSScott Long m3_pchan_setformat(kobj_t kobj, void *chdata, u_int32_t format) 475a5108eaeSScott Long { 476a5108eaeSScott Long struct sc_pchinfo *ch = chdata; 477a5108eaeSScott Long struct sc_info *sc = ch->parent; 478a5108eaeSScott Long u_int32_t data; 479a5108eaeSScott Long 480a5108eaeSScott Long M3_DEBUG(CHANGE, 481a5108eaeSScott Long ("m3_pchan_setformat(dac=%d, format=0x%x{%s-%s})\n", 482a5108eaeSScott Long ch->dac_idx, format, 483a5108eaeSScott Long format & (AFMT_U8|AFMT_S8) ? "8bit":"16bit", 484a5108eaeSScott Long format & AFMT_STEREO ? "STEREO":"MONO")); 485a5108eaeSScott Long 486a5108eaeSScott Long /* mono word */ 487a5108eaeSScott Long data = (format & AFMT_STEREO) ? 0 : 1; 488a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + SRC3_MODE_OFFSET, data); 489a5108eaeSScott Long 490a5108eaeSScott Long /* 8bit word */ 491a5108eaeSScott Long data = ((format & AFMT_U8) || (format & AFMT_S8)) ? 1 : 0; 492a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + SRC3_WORD_LENGTH_OFFSET, data); 493a5108eaeSScott Long 494a5108eaeSScott Long ch->fmt = format; 495a5108eaeSScott Long return format; 496a5108eaeSScott Long } 497a5108eaeSScott Long 498a5108eaeSScott Long static int 499a5108eaeSScott Long m3_pchan_setspeed(kobj_t kobj, void *chdata, u_int32_t speed) 500a5108eaeSScott Long { 501a5108eaeSScott Long struct sc_pchinfo *ch = chdata; 502a5108eaeSScott Long struct sc_info *sc = ch->parent; 503a5108eaeSScott Long u_int32_t freq; 504a5108eaeSScott Long 505a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_pchan_setspeed(dac=%d, speed=%d)\n", 506a5108eaeSScott Long ch->dac_idx, speed)); 507a5108eaeSScott Long 508a5108eaeSScott Long if ((freq = ((speed << 15) + 24000) / 48000) != 0) { 509a5108eaeSScott Long freq--; 510a5108eaeSScott Long } 511a5108eaeSScott Long 512a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_FREQUENCY, freq); 513a5108eaeSScott Long 514a5108eaeSScott Long ch->spd = speed; 515a5108eaeSScott Long return speed; /* return closest possible speed */ 516a5108eaeSScott Long } 517a5108eaeSScott Long 518a5108eaeSScott Long static int 519a5108eaeSScott Long m3_pchan_setblocksize(kobj_t kobj, void *chdata, u_int32_t blocksize) 520a5108eaeSScott Long { 521a5108eaeSScott Long struct sc_pchinfo *ch = chdata; 522a5108eaeSScott Long 523a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_pchan_setblocksize(dac=%d, blocksize=%d)\n", 524a5108eaeSScott Long ch->dac_idx, blocksize)); 525a5108eaeSScott Long 526a5108eaeSScott Long return blocksize; 527a5108eaeSScott Long } 528a5108eaeSScott Long 529a5108eaeSScott Long static int 530a5108eaeSScott Long m3_pchan_trigger(kobj_t kobj, void *chdata, int go) 531a5108eaeSScott Long { 532a5108eaeSScott Long struct sc_pchinfo *ch = chdata; 533a5108eaeSScott Long struct sc_info *sc = ch->parent; 534a5108eaeSScott Long u_int32_t data; 535a5108eaeSScott Long 536a5108eaeSScott Long M3_DEBUG(go == PCMTRIG_START ? CHANGE : 537a5108eaeSScott Long go == PCMTRIG_STOP ? CHANGE : 538a5108eaeSScott Long go == PCMTRIG_ABORT ? CHANGE : 539a5108eaeSScott Long CALL, 540a5108eaeSScott Long ("m3_pchan_trigger(dac=%d, go=0x%x{%s})\n", ch->dac_idx, go, 541a5108eaeSScott Long go == PCMTRIG_START ? "PCMTRIG_START" : 542a5108eaeSScott Long go == PCMTRIG_STOP ? "PCMTRIG_STOP" : 543a5108eaeSScott Long go == PCMTRIG_ABORT ? "PCMTRIG_ABORT" : "ignore")); 544a5108eaeSScott Long 545a5108eaeSScott Long switch(go) { 546a5108eaeSScott Long case PCMTRIG_START: 547a5108eaeSScott Long if (ch->active) { 548a5108eaeSScott Long return 0; 549a5108eaeSScott Long } 550a5108eaeSScott Long ch->active = 1; 551a5108eaeSScott Long sc->pch_active_cnt++; 552a5108eaeSScott Long 553a5108eaeSScott Long /*[[inc_timer_users]]*/ 554a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 240); 555a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 240); 556a5108eaeSScott Long data = m3_rd_2(sc, HOST_INT_CTRL); 557a5108eaeSScott Long m3_wr_2(sc, HOST_INT_CTRL, data | CLKRUN_GEN_ENABLE); 558a5108eaeSScott Long 559a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_INSTANCE_READY, 1); 560a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER, 561a5108eaeSScott Long sc->pch_active_cnt); 562a5108eaeSScott Long break; 563a5108eaeSScott Long 564a5108eaeSScott Long case PCMTRIG_STOP: 565a5108eaeSScott Long case PCMTRIG_ABORT: 566a5108eaeSScott Long if (ch->active == 0) { 567a5108eaeSScott Long return 0; 568a5108eaeSScott Long } 569a5108eaeSScott Long ch->active = 0; 570a5108eaeSScott Long sc->pch_active_cnt--; 571a5108eaeSScott Long 572a5108eaeSScott Long /* XXX should the channel be drained? */ 573a5108eaeSScott Long /*[[dec_timer_users]]*/ 574a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 0); 575a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 0); 576a5108eaeSScott Long data = m3_rd_2(sc, HOST_INT_CTRL); 577a5108eaeSScott Long m3_wr_2(sc, HOST_INT_CTRL, data & ~CLKRUN_GEN_ENABLE); 578a5108eaeSScott Long 579a5108eaeSScott Long m3_wr_assp_data(sc, ch->dac_data + CDATA_INSTANCE_READY, 0); 580a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER, 581a5108eaeSScott Long sc->pch_active_cnt); 582a5108eaeSScott Long break; 583a5108eaeSScott Long 584a5108eaeSScott Long case PCMTRIG_EMLDMAWR: 585a5108eaeSScott Long /* got play irq, transfer next buffer - ignore if using dma */ 586a5108eaeSScott Long case PCMTRIG_EMLDMARD: 587a5108eaeSScott Long /* got rec irq, transfer next buffer - ignore if using dma */ 588a5108eaeSScott Long default: 589a5108eaeSScott Long break; 590a5108eaeSScott Long } 591a5108eaeSScott Long return 0; 592a5108eaeSScott Long } 593a5108eaeSScott Long 594a5108eaeSScott Long static int 595a5108eaeSScott Long m3_pchan_getptr(kobj_t kobj, void *chdata) 596a5108eaeSScott Long { 597a5108eaeSScott Long struct sc_pchinfo *ch = chdata; 598a5108eaeSScott Long struct sc_info *sc = ch->parent; 599a5108eaeSScott Long u_int32_t hi, lo, bus_crnt; 600a5108eaeSScott Long u_int32_t bus_base = vtophys(sndbuf_getbuf(ch->buffer)); 601a5108eaeSScott Long 602a5108eaeSScott Long hi = m3_rd_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTH); 603a5108eaeSScott Long lo = m3_rd_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTL); 604a5108eaeSScott Long bus_crnt = lo | (hi << 16); 605a5108eaeSScott Long 606a5108eaeSScott Long M3_DEBUG(CALL, ("m3_pchan_getptr(dac=%d) result=%d\n", 607a5108eaeSScott Long ch->dac_idx, bus_crnt - bus_base)); 608a5108eaeSScott Long 609a5108eaeSScott Long return (bus_crnt - bus_base); /* current byte offset of channel */ 610a5108eaeSScott Long } 611a5108eaeSScott Long 612a5108eaeSScott Long static pcmchan_caps * 613a5108eaeSScott Long m3_pchan_getcaps(kobj_t kobj, void *chdata) 614a5108eaeSScott Long { 615a5108eaeSScott Long struct sc_pchinfo *ch = chdata; 616a5108eaeSScott Long 617a5108eaeSScott Long M3_DEBUG(CALL, ("m3_pchan_getcaps(dac=%d)\n", ch->dac_idx)); 618a5108eaeSScott Long 619a5108eaeSScott Long return &m3_playcaps; 620a5108eaeSScott Long } 621a5108eaeSScott Long 622a5108eaeSScott Long /* -------------------------------------------------------------------- */ 623a5108eaeSScott Long /* rec channel interface */ 624a5108eaeSScott Long 625a5108eaeSScott Long static void * 626a5108eaeSScott Long m3_rchan_init(kobj_t kobj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 627a5108eaeSScott Long { 628a5108eaeSScott Long struct sc_info *sc = devinfo; 629a5108eaeSScott Long struct sc_rchinfo *ch; 630a5108eaeSScott Long u_int32_t bus_addr, i; 631a5108eaeSScott Long 632a5108eaeSScott Long int idx = sc->rch_cnt; /* adc instance number, no active reuse! */ 633a5108eaeSScott Long int data_bytes = (((MINISRC_TMP_BUFFER_SIZE & ~1) + 634a5108eaeSScott Long (MINISRC_IN_BUFFER_SIZE & ~1) + 635a5108eaeSScott Long (MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255) &~ 255; 636a5108eaeSScott Long int adc_data = 0x1100 + (data_bytes * idx) + data_bytes/2; 637a5108eaeSScott Long 638a5108eaeSScott Long int dsp_in_size = MINISRC_IN_BUFFER_SIZE + (0x10 * 2); 639a5108eaeSScott Long int dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x10 * 2); 640a5108eaeSScott Long int dsp_in_buf = adc_data + (MINISRC_TMP_BUFFER_SIZE / 2); 641a5108eaeSScott Long int dsp_out_buf = dsp_in_buf + (dsp_in_size / 2) + 1; 642a5108eaeSScott Long 643a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_rchan_init(adc=%d)\n", idx)); 644a5108eaeSScott Long 645a5108eaeSScott Long if (dir != PCMDIR_REC) { 646a5108eaeSScott Long device_printf(sc->dev, "m3_pchan_init not PCMDIR_REC\n"); 647a5108eaeSScott Long return NULL; 648a5108eaeSScott Long } 649a5108eaeSScott Long ch = &sc->rch[idx]; 650a5108eaeSScott Long 651a5108eaeSScott Long ch->adc_idx = idx; 652a5108eaeSScott Long ch->adc_data = adc_data; 653a5108eaeSScott Long if (ch->adc_data + data_bytes/2 >= 0x1c00) { 654a5108eaeSScott Long device_printf(sc->dev, "m3_rchan_init: revb mem exhausted\n"); 655a5108eaeSScott Long return NULL; 656a5108eaeSScott Long } 657a5108eaeSScott Long 658a5108eaeSScott Long ch->buffer = b; 659a5108eaeSScott Long ch->parent = sc; 660a5108eaeSScott Long ch->channel = c; 661a5108eaeSScott Long ch->fmt = AFMT_U8; 662a5108eaeSScott Long ch->spd = DSP_DEFAULT_SPEED; 663a5108eaeSScott Long if (sndbuf_alloc(ch->buffer, sc->parent_dmat, M3_BUFSIZE) == -1) { 664a5108eaeSScott Long device_printf(sc->dev, "m3_rchan_init chn_allocbuf failed\n"); 665a5108eaeSScott Long return NULL; 666a5108eaeSScott Long } 667a5108eaeSScott Long ch->bufsize = sndbuf_getsize(ch->buffer); 668a5108eaeSScott Long 669a5108eaeSScott Long /* host dma buffer pointers */ 670a5108eaeSScott Long bus_addr = vtophys(sndbuf_getbuf(ch->buffer)); 671a5108eaeSScott Long if (bus_addr & 3) { 672a5108eaeSScott Long device_printf(sc->dev, "m3_rchan_init unaligned bus_addr\n"); 673a5108eaeSScott Long bus_addr = (bus_addr + 4) & ~3; 674a5108eaeSScott Long } 675a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_ADDRL, LO(bus_addr)); 676a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_ADDRH, HI(bus_addr)); 677a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_END_PLUS_1L, 678a5108eaeSScott Long LO(bus_addr + ch->bufsize)); 679a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_END_PLUS_1H, 680a5108eaeSScott Long HI(bus_addr + ch->bufsize)); 681a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTL, 682a5108eaeSScott Long LO(bus_addr)); 683a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTH, 684a5108eaeSScott Long HI(bus_addr)); 685a5108eaeSScott Long 686a5108eaeSScott Long /* dsp buffers */ 687a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_BEGIN, dsp_in_buf); 688a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_END_PLUS_1, 689a5108eaeSScott Long dsp_in_buf + dsp_in_size/2); 690a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_HEAD, dsp_in_buf); 691a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_TAIL, dsp_in_buf); 692a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_BEGIN, dsp_out_buf); 693a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_END_PLUS_1, 694a5108eaeSScott Long dsp_out_buf + dsp_out_size/2); 695a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_HEAD, dsp_out_buf); 696a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_TAIL, dsp_out_buf); 697a5108eaeSScott Long 698a5108eaeSScott Long /* some per client initializers */ 699a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + SRC3_DIRECTION_OFFSET + 12, 700a5108eaeSScott Long ch->adc_data + 40 + 8); 701a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_DMA_CONTROL, 702a5108eaeSScott Long DMACONTROL_DIRECTION + DMACONTROL_AUTOREPEAT + 703a5108eaeSScott Long DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR); 704a5108eaeSScott Long 705a5108eaeSScott Long /* set an armload of static initializers */ 706a5108eaeSScott Long for(i = 0 ; i < (sizeof(rv) / sizeof(rv[0])) ; i++) { 707a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + rv[i].addr, rv[i].val); 708a5108eaeSScott Long } 709a5108eaeSScott Long 710a5108eaeSScott Long /* put us in the packed task lists */ 711a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC + 712a5108eaeSScott Long (sc->pch_cnt + sc->rch_cnt), 713a5108eaeSScott Long ch->adc_data >> DP_SHIFT_COUNT); 714a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_DMA_XFER0 + (sc->pch_cnt + sc->rch_cnt), 715a5108eaeSScott Long ch->adc_data >> DP_SHIFT_COUNT); 716a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_ADC1_XFER0 + sc->rch_cnt, 717a5108eaeSScott Long ch->adc_data >> DP_SHIFT_COUNT); 718a5108eaeSScott Long 719a5108eaeSScott Long m3_rchan_trigger(NULL, ch, PCMTRIG_START); /* gotta start before stop */ 720a5108eaeSScott Long m3_rchan_trigger(NULL, ch, PCMTRIG_STOP); /* stop on init */ 721a5108eaeSScott Long 722a5108eaeSScott Long sc->rch_cnt++; 723a5108eaeSScott Long return ch; 724a5108eaeSScott Long } 725a5108eaeSScott Long 726a5108eaeSScott Long static int 727a5108eaeSScott Long m3_rchan_free(kobj_t kobj, void *chdata) 728a5108eaeSScott Long { 729a5108eaeSScott Long struct sc_rchinfo *ch = chdata; 730a5108eaeSScott Long struct sc_info *sc = ch->parent; 731a5108eaeSScott Long 732a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_rchan_free(adc=%d)\n", ch->adc_idx)); 733a5108eaeSScott Long 734a5108eaeSScott Long /* 735a5108eaeSScott Long * should remove this exact instance from the packed lists, but all 736a5108eaeSScott Long * are released at once (and in a stopped state) so this is ok. 737a5108eaeSScott Long */ 738a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC + 739a5108eaeSScott Long (sc->rch_cnt - 1) + sc->pch_cnt, 0); 740a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_DMA_XFER0 + 741a5108eaeSScott Long (sc->rch_cnt - 1) + sc->pch_cnt, 0); 742a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_ADC1_XFER0 + (sc->rch_cnt - 1), 0); 743a5108eaeSScott Long 744a5108eaeSScott Long sc->rch_cnt--; 745a5108eaeSScott Long return 0; 746a5108eaeSScott Long } 747a5108eaeSScott Long 748a5108eaeSScott Long static int 749a5108eaeSScott Long m3_rchan_setformat(kobj_t kobj, void *chdata, u_int32_t format) 750a5108eaeSScott Long { 751a5108eaeSScott Long struct sc_rchinfo *ch = chdata; 752a5108eaeSScott Long struct sc_info *sc = ch->parent; 753a5108eaeSScott Long u_int32_t data; 754a5108eaeSScott Long 755a5108eaeSScott Long M3_DEBUG(CHANGE, 756a5108eaeSScott Long ("m3_rchan_setformat(dac=%d, format=0x%x{%s-%s})\n", 757a5108eaeSScott Long ch->adc_idx, format, 758a5108eaeSScott Long format & (AFMT_U8|AFMT_S8) ? "8bit":"16bit", 759a5108eaeSScott Long format & AFMT_STEREO ? "STEREO":"MONO")); 760a5108eaeSScott Long 761a5108eaeSScott Long /* mono word */ 762a5108eaeSScott Long data = (format & AFMT_STEREO) ? 0 : 1; 763a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + SRC3_MODE_OFFSET, data); 764a5108eaeSScott Long 765a5108eaeSScott Long /* 8bit word */ 766a5108eaeSScott Long data = ((format & AFMT_U8) || (format & AFMT_S8)) ? 1 : 0; 767a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + SRC3_WORD_LENGTH_OFFSET, data); 768a5108eaeSScott Long 769a5108eaeSScott Long ch->fmt = format; 770a5108eaeSScott Long return format; 771a5108eaeSScott Long } 772a5108eaeSScott Long 773a5108eaeSScott Long static int 774a5108eaeSScott Long m3_rchan_setspeed(kobj_t kobj, void *chdata, u_int32_t speed) 775a5108eaeSScott Long { 776a5108eaeSScott Long struct sc_rchinfo *ch = chdata; 777a5108eaeSScott Long struct sc_info *sc = ch->parent; 778a5108eaeSScott Long u_int32_t freq; 779a5108eaeSScott Long 780a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_rchan_setspeed(adc=%d, speed=%d)\n", 781a5108eaeSScott Long ch->adc_idx, speed)); 782a5108eaeSScott Long 783a5108eaeSScott Long if ((freq = ((speed << 15) + 24000) / 48000) != 0) { 784a5108eaeSScott Long freq--; 785a5108eaeSScott Long } 786a5108eaeSScott Long 787a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_FREQUENCY, freq); 788a5108eaeSScott Long 789a5108eaeSScott Long ch->spd = speed; 790a5108eaeSScott Long return speed; /* return closest possible speed */ 791a5108eaeSScott Long } 792a5108eaeSScott Long 793a5108eaeSScott Long static int 794a5108eaeSScott Long m3_rchan_setblocksize(kobj_t kobj, void *chdata, u_int32_t blocksize) 795a5108eaeSScott Long { 796a5108eaeSScott Long struct sc_rchinfo *ch = chdata; 797a5108eaeSScott Long 798a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_rchan_setblocksize(adc=%d, blocksize=%d)\n", 799a5108eaeSScott Long ch->adc_idx, blocksize)); 800a5108eaeSScott Long 801a5108eaeSScott Long return blocksize; 802a5108eaeSScott Long } 803a5108eaeSScott Long 804a5108eaeSScott Long static int 805a5108eaeSScott Long m3_rchan_trigger(kobj_t kobj, void *chdata, int go) 806a5108eaeSScott Long { 807a5108eaeSScott Long struct sc_rchinfo *ch = chdata; 808a5108eaeSScott Long struct sc_info *sc = ch->parent; 809a5108eaeSScott Long u_int32_t data; 810a5108eaeSScott Long 811a5108eaeSScott Long M3_DEBUG(go == PCMTRIG_START ? CHANGE : 812a5108eaeSScott Long go == PCMTRIG_STOP ? CHANGE : 813a5108eaeSScott Long go == PCMTRIG_ABORT ? CHANGE : 814a5108eaeSScott Long CALL, 815a5108eaeSScott Long ("m3_rchan_trigger(adc=%d, go=0x%x{%s})\n", ch->adc_idx, go, 816a5108eaeSScott Long go == PCMTRIG_START ? "PCMTRIG_START" : 817a5108eaeSScott Long go == PCMTRIG_STOP ? "PCMTRIG_STOP" : 818a5108eaeSScott Long go == PCMTRIG_ABORT ? "PCMTRIG_ABORT" : "ignore")); 819a5108eaeSScott Long 820a5108eaeSScott Long switch(go) { 821a5108eaeSScott Long case PCMTRIG_START: 822a5108eaeSScott Long if (ch->active) { 823a5108eaeSScott Long return 0; 824a5108eaeSScott Long } 825a5108eaeSScott Long ch->active = 1; 826a5108eaeSScott Long 827a5108eaeSScott Long /*[[inc_timer_users]]*/ 828a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 240); 829a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 240); 830a5108eaeSScott Long data = m3_rd_2(sc, HOST_INT_CTRL); 831a5108eaeSScott Long m3_wr_2(sc, HOST_INT_CTRL, data | CLKRUN_GEN_ENABLE); 832a5108eaeSScott Long 833a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_ADC1_REQUEST, 1); 834a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_INSTANCE_READY, 1); 835a5108eaeSScott Long break; 836a5108eaeSScott Long 837a5108eaeSScott Long case PCMTRIG_STOP: 838a5108eaeSScott Long case PCMTRIG_ABORT: 839a5108eaeSScott Long if (ch->active == 0) { 840a5108eaeSScott Long return 0; 841a5108eaeSScott Long } 842a5108eaeSScott Long ch->active = 0; 843a5108eaeSScott Long 844a5108eaeSScott Long /*[[dec_timer_users]]*/ 845a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 0); 846a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 0); 847a5108eaeSScott Long data = m3_rd_2(sc, HOST_INT_CTRL); 848a5108eaeSScott Long m3_wr_2(sc, HOST_INT_CTRL, data & ~CLKRUN_GEN_ENABLE); 849a5108eaeSScott Long 850a5108eaeSScott Long m3_wr_assp_data(sc, ch->adc_data + CDATA_INSTANCE_READY, 0); 851a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_ADC1_REQUEST, 0); 852a5108eaeSScott Long break; 853a5108eaeSScott Long 854a5108eaeSScott Long case PCMTRIG_EMLDMAWR: 855a5108eaeSScott Long /* got play irq, transfer next buffer - ignore if using dma */ 856a5108eaeSScott Long case PCMTRIG_EMLDMARD: 857a5108eaeSScott Long /* got rec irq, transfer next buffer - ignore if using dma */ 858a5108eaeSScott Long default: 859a5108eaeSScott Long break; 860a5108eaeSScott Long } 861a5108eaeSScott Long return 0; 862a5108eaeSScott Long } 863a5108eaeSScott Long 864a5108eaeSScott Long static int 865a5108eaeSScott Long m3_rchan_getptr(kobj_t kobj, void *chdata) 866a5108eaeSScott Long { 867a5108eaeSScott Long struct sc_rchinfo *ch = chdata; 868a5108eaeSScott Long struct sc_info *sc = ch->parent; 869a5108eaeSScott Long u_int32_t hi, lo, bus_crnt; 870a5108eaeSScott Long u_int32_t bus_base = vtophys(sndbuf_getbuf(ch->buffer)); 871a5108eaeSScott Long 872a5108eaeSScott Long hi = m3_rd_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTH); 873a5108eaeSScott Long lo = m3_rd_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTL); 874a5108eaeSScott Long bus_crnt = lo | (hi << 16); 875a5108eaeSScott Long 876a5108eaeSScott Long M3_DEBUG(CALL, ("m3_rchan_getptr(adc=%d) result=%d\n", 877a5108eaeSScott Long ch->adc_idx, bus_crnt - bus_base)); 878a5108eaeSScott Long 879a5108eaeSScott Long return (bus_crnt - bus_base); /* current byte offset of channel */ 880a5108eaeSScott Long } 881a5108eaeSScott Long 882a5108eaeSScott Long static pcmchan_caps * 883a5108eaeSScott Long m3_rchan_getcaps(kobj_t kobj, void *chdata) 884a5108eaeSScott Long { 885a5108eaeSScott Long struct sc_rchinfo *ch = chdata; 886a5108eaeSScott Long 887a5108eaeSScott Long M3_DEBUG(CALL, ("m3_rchan_getcaps(adc=%d)\n", ch->adc_idx)); 888a5108eaeSScott Long 889a5108eaeSScott Long return &m3_reccaps; 890a5108eaeSScott Long } 891a5108eaeSScott Long 892a5108eaeSScott Long /* -------------------------------------------------------------------- */ 893a5108eaeSScott Long /* The interrupt handler */ 894a5108eaeSScott Long 895a5108eaeSScott Long static void 896a5108eaeSScott Long m3_intr(void *p) 897a5108eaeSScott Long { 898a5108eaeSScott Long struct sc_info *sc = (struct sc_info *)p; 899a5108eaeSScott Long u_int32_t status, ctl, i; 900a5108eaeSScott Long 901a5108eaeSScott Long M3_DEBUG(INTR, ("m3_intr\n")); 902a5108eaeSScott Long 903a5108eaeSScott Long status = m3_rd_1(sc, HOST_INT_STATUS); 904a5108eaeSScott Long if (!status) 905a5108eaeSScott Long return; 906a5108eaeSScott Long 907a5108eaeSScott Long m3_wr_1(sc, HOST_INT_STATUS, 0xff); /* ack the int? */ 908a5108eaeSScott Long 909a5108eaeSScott Long if (status & HV_INT_PENDING) { 910a5108eaeSScott Long u_int8_t event; 911a5108eaeSScott Long 912a5108eaeSScott Long device_printf(sc->dev, "Hardware Volume Interrupt\n"); 913a5108eaeSScott Long event = m3_rd_1(sc, HW_VOL_COUNTER_MASTER); 914a5108eaeSScott Long switch (event) { 915a5108eaeSScott Long case 0x99: 916a5108eaeSScott Long mixer_hwvol_mute(sc->dev); 917a5108eaeSScott Long break; 918a5108eaeSScott Long case 0xaa: 919a5108eaeSScott Long mixer_hwvol_step(sc->dev, 1, 1); 920a5108eaeSScott Long break; 921a5108eaeSScott Long case 0x66: 922a5108eaeSScott Long mixer_hwvol_step(sc->dev, -1, -1); 923a5108eaeSScott Long break; 924a5108eaeSScott Long case 0x88: 925a5108eaeSScott Long break; 926a5108eaeSScott Long default: 927a5108eaeSScott Long device_printf(sc->dev, "Unknown HWVOL event\n"); 928a5108eaeSScott Long } 929a5108eaeSScott Long m3_wr_1(sc, HW_VOL_COUNTER_MASTER, 0x88); 930a5108eaeSScott Long 931a5108eaeSScott Long } 932a5108eaeSScott Long 933a5108eaeSScott Long if (status & ASSP_INT_PENDING) { 934a5108eaeSScott Long ctl = m3_rd_1(sc, ASSP_CONTROL_B); 935a5108eaeSScott Long if (!(ctl & STOP_ASSP_CLOCK)) { 936a5108eaeSScott Long ctl = m3_rd_1(sc, ASSP_HOST_INT_STATUS); 937a5108eaeSScott Long if (ctl & DSP2HOST_REQ_TIMER) { 938a5108eaeSScott Long m3_wr_1(sc, ASSP_HOST_INT_STATUS, 939a5108eaeSScott Long DSP2HOST_REQ_TIMER); 940a5108eaeSScott Long /*[[ess_update_ptr]]*/ 941a5108eaeSScott Long } 942a5108eaeSScott Long } 943a5108eaeSScott Long } 944a5108eaeSScott Long 945a5108eaeSScott Long for (i=0 ; i<sc->pch_cnt ; i++) { 946a5108eaeSScott Long if (sc->pch[i].active) { 947a5108eaeSScott Long chn_intr(sc->pch[i].channel); 948a5108eaeSScott Long } 949a5108eaeSScott Long } 950a5108eaeSScott Long for (i=0 ; i<sc->rch_cnt ; i++) { 951a5108eaeSScott Long if (sc->rch[i].active) { 952a5108eaeSScott Long chn_intr(sc->rch[i].channel); 953a5108eaeSScott Long } 954a5108eaeSScott Long } 955a5108eaeSScott Long } 956a5108eaeSScott Long 957a5108eaeSScott Long /* -------------------------------------------------------------------- */ 958a5108eaeSScott Long /* stuff */ 959a5108eaeSScott Long 960a5108eaeSScott Long static int 961a5108eaeSScott Long m3_power(struct sc_info *sc, int state) 962a5108eaeSScott Long { 963a5108eaeSScott Long u_int32_t data; 964a5108eaeSScott Long 965a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_power(%d)\n", state)); 966a5108eaeSScott Long 967a5108eaeSScott Long data = pci_read_config(sc->dev, 0x34, 1); 968a5108eaeSScott Long if (pci_read_config(sc->dev, data, 1) == 1) { 969a5108eaeSScott Long pci_write_config(sc->dev, data + 4, state, 1); 970a5108eaeSScott Long } 971a5108eaeSScott Long 972a5108eaeSScott Long return 0; 973a5108eaeSScott Long } 974a5108eaeSScott Long 975a5108eaeSScott Long static int 976a5108eaeSScott Long m3_init(struct sc_info *sc) 977a5108eaeSScott Long { 978a5108eaeSScott Long u_int32_t data, i, size; 979a5108eaeSScott Long u_int8_t reset_state; 980a5108eaeSScott Long 981a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_init\n")); 982a5108eaeSScott Long 983a5108eaeSScott Long /* diable legacy emulations. */ 984a5108eaeSScott Long data = pci_read_config(sc->dev, PCI_LEGACY_AUDIO_CTRL, 2); 985a5108eaeSScott Long data |= DISABLE_LEGACY; 986a5108eaeSScott Long pci_write_config(sc->dev, PCI_LEGACY_AUDIO_CTRL, data, 2); 987a5108eaeSScott Long 988a5108eaeSScott Long m3_config(sc); 989a5108eaeSScott Long 990a5108eaeSScott Long reset_state = m3_assp_halt(sc); 991a5108eaeSScott Long 992a5108eaeSScott Long m3_codec_reset(sc); 993a5108eaeSScott Long 994a5108eaeSScott Long /* [m3_assp_init] */ 995a5108eaeSScott Long /* zero kernel data */ 996a5108eaeSScott Long size = REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA; 997a5108eaeSScott Long for(i = 0 ; i < size / 2 ; i++) { 998a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_BASE_ADDR + i, 0); 999a5108eaeSScott Long } 1000a5108eaeSScott Long /* zero mixer data? */ 1001a5108eaeSScott Long size = REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA; 1002a5108eaeSScott Long for(i = 0 ; i < size / 2 ; i++) { 1003a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_BASE_ADDR2 + i, 0); 1004a5108eaeSScott Long } 1005a5108eaeSScott Long /* init dma pointer */ 1006a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_CURRENT_DMA, 1007a5108eaeSScott Long KDATA_DMA_XFER0); 1008a5108eaeSScott Long /* write kernel into code memory */ 1009a5108eaeSScott Long size = sizeof(assp_kernel_image); 1010a5108eaeSScott Long for(i = 0 ; i < size / 2; i++) { 1011a5108eaeSScott Long m3_wr_assp_code(sc, REV_B_CODE_MEMORY_BEGIN + i, 1012a5108eaeSScott Long assp_kernel_image[i]); 1013a5108eaeSScott Long } 1014a5108eaeSScott Long /* 1015a5108eaeSScott Long * We only have this one client and we know that 0x400 is free in 1016a5108eaeSScott Long * our kernel's mem map, so lets just drop it there. It seems that 1017a5108eaeSScott Long * the minisrc doesn't need vectors, so we won't bother with them.. 1018a5108eaeSScott Long */ 1019a5108eaeSScott Long size = sizeof(assp_minisrc_image); 1020a5108eaeSScott Long for(i = 0 ; i < size / 2; i++) { 1021a5108eaeSScott Long m3_wr_assp_code(sc, 0x400 + i, assp_minisrc_image[i]); 1022a5108eaeSScott Long } 1023a5108eaeSScott Long /* write the coefficients for the low pass filter? */ 1024a5108eaeSScott Long size = sizeof(minisrc_lpf_image); 1025a5108eaeSScott Long for(i = 0; i < size / 2 ; i++) { 1026a5108eaeSScott Long m3_wr_assp_code(sc,0x400 + MINISRC_COEF_LOC + i, 1027a5108eaeSScott Long minisrc_lpf_image[i]); 1028a5108eaeSScott Long } 1029a5108eaeSScott Long m3_wr_assp_code(sc, 0x400 + MINISRC_COEF_LOC + size, 0x8000); 1030a5108eaeSScott Long /* the minisrc is the only thing on our task list */ 1031a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_TASK0, 0x400); 1032a5108eaeSScott Long /* init the mixer number */ 1033a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER, 0); 1034a5108eaeSScott Long /* extreme kernel master volume */ 1035a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_DAC_LEFT_VOLUME, ARB_VOLUME); 1036a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_DAC_RIGHT_VOLUME, ARB_VOLUME); 1037a5108eaeSScott Long 1038a5108eaeSScott Long m3_amp_enable(sc); 1039a5108eaeSScott Long 1040a5108eaeSScott Long /* [m3_assp_client_init] (only one client at index 0) */ 1041a5108eaeSScott Long for (i=0x1100 ; i<0x1c00 ; i++) { 1042a5108eaeSScott Long m3_wr_assp_data(sc, i, 0); /* zero entire dac/adc area */ 1043a5108eaeSScott Long } 1044a5108eaeSScott Long 1045a5108eaeSScott Long m3_enable_ints(sc); 1046a5108eaeSScott Long 1047a5108eaeSScott Long /* [m3_assp_continue] */ 1048a5108eaeSScott Long m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state | REGB_ENABLE_RESET); 1049a5108eaeSScott Long 1050a5108eaeSScott Long return 0; 1051a5108eaeSScott Long } 1052a5108eaeSScott Long 1053a5108eaeSScott Long static int 1054a5108eaeSScott Long m3_uninit(struct sc_info *sc) 1055a5108eaeSScott Long { 1056a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_uninit\n")); 1057a5108eaeSScott Long return 0; 1058a5108eaeSScott Long } 1059a5108eaeSScott Long 1060a5108eaeSScott Long /* -------------------------------------------------------------------- */ 1061a5108eaeSScott Long /* Probe and attach the card */ 1062a5108eaeSScott Long 1063a5108eaeSScott Long static int 1064a5108eaeSScott Long m3_pci_probe(device_t dev) 1065a5108eaeSScott Long { 1066a5108eaeSScott Long struct m3_card_type *card; 1067a5108eaeSScott Long 1068a5108eaeSScott Long M3_DEBUG(CALL, ("m3_pci_probe(0x%x)\n", pci_get_devid(dev))); 1069a5108eaeSScott Long 1070a5108eaeSScott Long for (card = m3_card_types ; card->pci_id ; card++) { 1071a5108eaeSScott Long if (pci_get_devid(dev) == card->pci_id) { 1072a5108eaeSScott Long device_set_desc(dev, card->name); 1073a5108eaeSScott Long return 0; 1074a5108eaeSScott Long } 1075a5108eaeSScott Long } 1076a5108eaeSScott Long return ENXIO; 1077a5108eaeSScott Long } 1078a5108eaeSScott Long 1079a5108eaeSScott Long static int 1080a5108eaeSScott Long m3_pci_attach(device_t dev) 1081a5108eaeSScott Long { 1082a5108eaeSScott Long struct sc_info *sc; 1083a5108eaeSScott Long struct ac97_info *codec = NULL; 1084a5108eaeSScott Long u_int32_t data, i; 1085a5108eaeSScott Long char status[SND_STATUSLEN]; 1086a5108eaeSScott Long struct m3_card_type *card; 1087a5108eaeSScott Long int len; 1088a5108eaeSScott Long 1089a5108eaeSScott Long M3_DEBUG(CALL, ("m3_pci_attach\n")); 1090a5108eaeSScott Long 1091a5108eaeSScott Long if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { 1092a5108eaeSScott Long device_printf(dev, "cannot allocate softc\n"); 1093a5108eaeSScott Long return ENXIO; 1094a5108eaeSScott Long } 1095a5108eaeSScott Long 1096a5108eaeSScott Long sc->dev = dev; 1097a5108eaeSScott Long sc->type = pci_get_devid(dev); 1098a5108eaeSScott Long 1099a5108eaeSScott Long for (card = m3_card_types ; card->pci_id ; card++) { 1100a5108eaeSScott Long if (sc->type == card->pci_id) { 1101a5108eaeSScott Long sc->which = card->which; 1102a5108eaeSScott Long sc->delay1 = card->delay1; 1103a5108eaeSScott Long sc->delay2 = card->delay2; 1104a5108eaeSScott Long break; 1105a5108eaeSScott Long } 1106a5108eaeSScott Long } 1107a5108eaeSScott Long 1108a5108eaeSScott Long data = pci_read_config(dev, PCIR_COMMAND, 2); 1109a5108eaeSScott Long data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); 1110a5108eaeSScott Long pci_write_config(dev, PCIR_COMMAND, data, 2); 1111a5108eaeSScott Long 1112a5108eaeSScott Long sc->regid = PCIR_MAPS; 1113a5108eaeSScott Long sc->regtype = SYS_RES_MEMORY; 1114a5108eaeSScott Long sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, 1115a5108eaeSScott Long 0, ~0, 1, RF_ACTIVE); 1116a5108eaeSScott Long if (!sc->reg) { 1117a5108eaeSScott Long sc->regtype = SYS_RES_IOPORT; 1118a5108eaeSScott Long sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, 1119a5108eaeSScott Long 0, ~0, 1, RF_ACTIVE); 1120a5108eaeSScott Long } 1121a5108eaeSScott Long if (!sc->reg) { 1122a5108eaeSScott Long device_printf(dev, "unable to allocate register space\n"); 1123a5108eaeSScott Long goto bad; 1124a5108eaeSScott Long } 1125a5108eaeSScott Long sc->st = rman_get_bustag(sc->reg); 1126a5108eaeSScott Long sc->sh = rman_get_bushandle(sc->reg); 1127a5108eaeSScott Long 1128a5108eaeSScott Long sc->irqid = 0; 1129a5108eaeSScott Long sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, 1130a5108eaeSScott Long 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 1131a5108eaeSScott Long if (!sc->irq) { 1132a5108eaeSScott Long device_printf(dev, "unable to allocate interrupt\n"); 1133a5108eaeSScott Long goto bad; 1134a5108eaeSScott Long } 1135a5108eaeSScott Long 1136a5108eaeSScott Long if (bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, m3_intr, sc, 1137a5108eaeSScott Long &sc->ih)) { 1138a5108eaeSScott Long device_printf(dev, "unable to setup interrupt\n"); 1139a5108eaeSScott Long goto bad; 1140a5108eaeSScott Long } 1141a5108eaeSScott Long 1142a5108eaeSScott Long if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 1143a5108eaeSScott Long /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 1144a5108eaeSScott Long /*highaddr*/BUS_SPACE_MAXADDR, 1145a5108eaeSScott Long /*filter*/NULL, /*filterarg*/NULL, 1146a5108eaeSScott Long /*maxsize*/M3_BUFSIZE, /*nsegments*/1, 1147a5108eaeSScott Long /*maxsegz*/0x3ffff, 1148a5108eaeSScott Long /*flags*/0, &sc->parent_dmat) != 0) { 1149a5108eaeSScott Long device_printf(dev, "unable to create dma tag\n"); 1150a5108eaeSScott Long goto bad; 1151a5108eaeSScott Long } 1152a5108eaeSScott Long 1153a5108eaeSScott Long m3_power(sc, 0); /* power up */ 1154a5108eaeSScott Long 1155a5108eaeSScott Long /* init chip */ 1156a5108eaeSScott Long if (m3_init(sc) == -1) { 1157a5108eaeSScott Long device_printf(dev, "unable to initialize the card\n"); 1158a5108eaeSScott Long goto bad; 1159a5108eaeSScott Long } 1160a5108eaeSScott Long 1161a5108eaeSScott Long /* create/init mixer */ 1162a5108eaeSScott Long codec = AC97_CREATE(dev, sc, m3_codec); 1163a5108eaeSScott Long if (codec == NULL) { 1164a5108eaeSScott Long device_printf(dev, "ac97_create error\n"); 1165a5108eaeSScott Long goto bad; 1166a5108eaeSScott Long } 1167a5108eaeSScott Long if (mixer_init(dev, ac97_getmixerclass(), codec)) { 1168a5108eaeSScott Long device_printf(dev, "mixer_init error\n"); 1169a5108eaeSScott Long goto bad; 1170a5108eaeSScott Long } 1171a5108eaeSScott Long 1172a5108eaeSScott Long if (pcm_register(dev, sc, M3_PCHANS, M3_RCHANS)) { 1173a5108eaeSScott Long device_printf(dev, "pcm_register error\n"); 1174a5108eaeSScott Long goto bad; 1175a5108eaeSScott Long } 1176a5108eaeSScott Long for (i=0 ; i<M3_PCHANS ; i++) { 1177a5108eaeSScott Long if (pcm_addchan(dev, PCMDIR_PLAY, &m3_pch_class, sc)) { 1178a5108eaeSScott Long device_printf(dev, "pcm_addchan (play) error\n"); 1179a5108eaeSScott Long goto bad; 1180a5108eaeSScott Long } 1181a5108eaeSScott Long } 1182a5108eaeSScott Long for (i=0 ; i<M3_RCHANS ; i++) { 1183a5108eaeSScott Long if (pcm_addchan(dev, PCMDIR_REC, &m3_rch_class, sc)) { 1184a5108eaeSScott Long device_printf(dev, "pcm_addchan (rec) error\n"); 1185a5108eaeSScott Long goto bad; 1186a5108eaeSScott Long } 1187a5108eaeSScott Long } 1188a5108eaeSScott Long snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld", 1189a5108eaeSScott Long (sc->regtype == SYS_RES_IOPORT)? "io" : "memory", 1190a5108eaeSScott Long rman_get_start(sc->reg), rman_get_start(sc->irq)); 1191a5108eaeSScott Long if (pcm_setstatus(dev, status)) { 1192a5108eaeSScott Long device_printf(dev, "attach: pcm_setstatus error\n"); 1193a5108eaeSScott Long goto bad; 1194a5108eaeSScott Long } 1195a5108eaeSScott Long 1196a5108eaeSScott Long /* Create the buffer for saving the card state during suspend */ 1197a5108eaeSScott Long len = sizeof(u_int16_t) * (REV_B_CODE_MEMORY_LENGTH + 1198a5108eaeSScott Long REV_B_DATA_MEMORY_LENGTH); 1199a5108eaeSScott Long sc->savemem = (u_int16_t*)malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO); 1200a5108eaeSScott Long if (sc->savemem == NULL) { 1201a5108eaeSScott Long device_printf(dev, "Failed to create suspend buffer\n"); 1202a5108eaeSScott Long goto bad; 1203a5108eaeSScott Long } 1204a5108eaeSScott Long 1205a5108eaeSScott Long return 0; 1206a5108eaeSScott Long 1207a5108eaeSScott Long bad: 1208a5108eaeSScott Long if (codec) { 1209a5108eaeSScott Long ac97_destroy(codec); 1210a5108eaeSScott Long } 1211a5108eaeSScott Long if (sc->reg) { 1212a5108eaeSScott Long bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); 1213a5108eaeSScott Long } 1214a5108eaeSScott Long if (sc->ih) { 1215a5108eaeSScott Long bus_teardown_intr(dev, sc->irq, sc->ih); 1216a5108eaeSScott Long } 1217a5108eaeSScott Long if (sc->irq) { 1218a5108eaeSScott Long bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 1219a5108eaeSScott Long } 1220a5108eaeSScott Long if (sc->parent_dmat) { 1221a5108eaeSScott Long bus_dma_tag_destroy(sc->parent_dmat); 1222a5108eaeSScott Long } 1223a5108eaeSScott Long free(sc, M_DEVBUF); 1224a5108eaeSScott Long return ENXIO; 1225a5108eaeSScott Long } 1226a5108eaeSScott Long 1227a5108eaeSScott Long static int 1228a5108eaeSScott Long m3_pci_detach(device_t dev) 1229a5108eaeSScott Long { 1230a5108eaeSScott Long struct sc_info *sc = pcm_getdevinfo(dev); 1231a5108eaeSScott Long int r; 1232a5108eaeSScott Long 1233a5108eaeSScott Long M3_DEBUG(CALL, ("m3_pci_detach\n")); 1234a5108eaeSScott Long 1235a5108eaeSScott Long if ((r = pcm_unregister(dev)) != 0) { 1236a5108eaeSScott Long return r; 1237a5108eaeSScott Long } 1238a5108eaeSScott Long m3_uninit(sc); /* shutdown chip */ 1239a5108eaeSScott Long m3_power(sc, 3); /* power off */ 1240a5108eaeSScott Long 1241a5108eaeSScott Long bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); 1242a5108eaeSScott Long bus_teardown_intr(dev, sc->irq, sc->ih); 1243a5108eaeSScott Long bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 1244a5108eaeSScott Long bus_dma_tag_destroy(sc->parent_dmat); 1245a5108eaeSScott Long 1246a5108eaeSScott Long free(sc->savemem, M_DEVBUF); 1247a5108eaeSScott Long free(sc, M_DEVBUF); 1248a5108eaeSScott Long return 0; 1249a5108eaeSScott Long } 1250a5108eaeSScott Long 1251a5108eaeSScott Long static int 1252a5108eaeSScott Long m3_pci_suspend(device_t dev) 1253a5108eaeSScott Long { 1254a5108eaeSScott Long struct sc_info *sc = pcm_getdevinfo(dev); 1255a5108eaeSScott Long int i, index = 0; 1256a5108eaeSScott Long 1257a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_pci_suspend\n")); 1258a5108eaeSScott Long 1259a5108eaeSScott Long for (i=0 ; i<sc->pch_cnt ; i++) { 1260a5108eaeSScott Long if (sc->pch[i].active) { 1261a5108eaeSScott Long m3_pchan_trigger(NULL, &sc->pch[i], PCMTRIG_STOP); 1262a5108eaeSScott Long } 1263a5108eaeSScott Long } 1264a5108eaeSScott Long for (i=0 ; i<sc->rch_cnt ; i++) { 1265a5108eaeSScott Long if (sc->rch[i].active) { 1266a5108eaeSScott Long m3_rchan_trigger(NULL, &sc->rch[i], PCMTRIG_STOP); 1267a5108eaeSScott Long } 1268a5108eaeSScott Long } 1269a5108eaeSScott Long DELAY(10 * 1000); /* give things a chance to stop */ 1270a5108eaeSScott Long 1271a5108eaeSScott Long /* Disable interrupts */ 1272a5108eaeSScott Long m3_wr_2(sc, HOST_INT_CTRL, 0); 1273a5108eaeSScott Long m3_wr_1(sc, ASSP_CONTROL_C, 0); 1274a5108eaeSScott Long 1275a5108eaeSScott Long m3_assp_halt(sc); 1276a5108eaeSScott Long 1277a5108eaeSScott Long /* Save the state of the ASSP */ 1278a5108eaeSScott Long for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++) 1279a5108eaeSScott Long sc->savemem[index++] = m3_rd_assp_code(sc, i); 1280a5108eaeSScott Long for (i = REV_B_DATA_MEMORY_BEGIN; i <= REV_B_DATA_MEMORY_END; i++) 1281a5108eaeSScott Long sc->savemem[index++] = m3_rd_assp_data(sc, i); 1282a5108eaeSScott Long 1283a5108eaeSScott Long /* Power down the card to D3 state */ 1284a5108eaeSScott Long m3_power(sc, 3); 1285a5108eaeSScott Long 1286a5108eaeSScott Long return 0; 1287a5108eaeSScott Long } 1288a5108eaeSScott Long 1289a5108eaeSScott Long static int 1290a5108eaeSScott Long m3_pci_resume(device_t dev) 1291a5108eaeSScott Long { 1292a5108eaeSScott Long struct sc_info *sc = pcm_getdevinfo(dev); 1293a5108eaeSScott Long int i, index = 0; 1294a5108eaeSScott Long u_int8_t reset_state; 1295a5108eaeSScott Long 1296a5108eaeSScott Long M3_DEBUG(CHANGE, ("m3_pci_resume\n")); 1297a5108eaeSScott Long 1298a5108eaeSScott Long /* Power the card back to D0 */ 1299a5108eaeSScott Long m3_power(sc, 0); 1300a5108eaeSScott Long 1301a5108eaeSScott Long m3_config(sc); 1302a5108eaeSScott Long 1303a5108eaeSScott Long reset_state = m3_assp_halt(sc); 1304a5108eaeSScott Long 1305a5108eaeSScott Long m3_codec_reset(sc); 1306a5108eaeSScott Long 1307a5108eaeSScott Long /* Restore the ASSP state */ 1308a5108eaeSScott Long for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++) 1309a5108eaeSScott Long m3_wr_assp_code(sc, i, sc->savemem[index++]); 1310a5108eaeSScott Long for (i = REV_B_DATA_MEMORY_BEGIN; i <= REV_B_DATA_MEMORY_END; i++) 1311a5108eaeSScott Long m3_wr_assp_data(sc, i, sc->savemem[index++]); 1312a5108eaeSScott Long 1313a5108eaeSScott Long /* Restart the DMA engine */ 1314a5108eaeSScott Long m3_wr_assp_data(sc, KDATA_DMA_ACTIVE, 0); 1315a5108eaeSScott Long 1316a5108eaeSScott Long /* [m3_assp_continue] */ 1317a5108eaeSScott Long m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state | REGB_ENABLE_RESET); 1318a5108eaeSScott Long 1319a5108eaeSScott Long m3_enable_ints(sc); 1320a5108eaeSScott Long 1321a5108eaeSScott Long m3_amp_enable(sc); 1322a5108eaeSScott Long 1323a5108eaeSScott Long /* Turn the channels back on */ 1324a5108eaeSScott Long for (i=0 ; i<sc->pch_cnt ; i++) { 1325a5108eaeSScott Long if (sc->pch[i].active) { 1326a5108eaeSScott Long m3_pchan_trigger(NULL, &sc->pch[i], PCMTRIG_START); 1327a5108eaeSScott Long } 1328a5108eaeSScott Long } 1329a5108eaeSScott Long for (i=0 ; i<sc->rch_cnt ; i++) { 1330a5108eaeSScott Long if (sc->rch[i].active) { 1331a5108eaeSScott Long m3_rchan_trigger(NULL, &sc->rch[i], PCMTRIG_START); 1332a5108eaeSScott Long } 1333a5108eaeSScott Long } 1334a5108eaeSScott Long 1335a5108eaeSScott Long return 0; 1336a5108eaeSScott Long } 1337a5108eaeSScott Long 1338a5108eaeSScott Long static int 1339a5108eaeSScott Long m3_pci_shutdown(device_t dev) 1340a5108eaeSScott Long { 1341a5108eaeSScott Long struct sc_info *sc = pcm_getdevinfo(dev); 1342a5108eaeSScott Long 1343a5108eaeSScott Long M3_DEBUG(CALL, ("m3_pci_shutdown\n")); 1344a5108eaeSScott Long 1345a5108eaeSScott Long m3_power(sc, 3); /* power off */ 1346a5108eaeSScott Long return 0; 1347a5108eaeSScott Long } 1348a5108eaeSScott Long 1349a5108eaeSScott Long static u_int8_t 1350a5108eaeSScott Long m3_assp_halt(struct sc_info *sc) 1351a5108eaeSScott Long { 1352a5108eaeSScott Long u_int8_t data, reset_state; 1353a5108eaeSScott Long 1354a5108eaeSScott Long data = m3_rd_1(sc, DSP_PORT_CONTROL_REG_B); 1355a5108eaeSScott Long reset_state = data & ~REGB_STOP_CLOCK; /* remember for continue */ 1356a5108eaeSScott Long DELAY(10 * 1000); 1357a5108eaeSScott Long m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state & ~REGB_ENABLE_RESET); 1358a5108eaeSScott Long DELAY(10 * 1000); /* necessary? */ 1359a5108eaeSScott Long 1360a5108eaeSScott Long return reset_state; 1361a5108eaeSScott Long } 1362a5108eaeSScott Long 1363a5108eaeSScott Long static void 1364a5108eaeSScott Long m3_config(struct sc_info *sc) 1365a5108eaeSScott Long { 1366a5108eaeSScott Long u_int32_t data; 1367a5108eaeSScott Long 1368a5108eaeSScott Long data = pci_read_config(sc->dev, PCI_ALLEGRO_CONFIG, 4); 1369a5108eaeSScott Long data &= REDUCED_DEBOUNCE; 1370a5108eaeSScott Long data |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; 1371a5108eaeSScott Long pci_write_config(sc->dev, PCI_ALLEGRO_CONFIG, data, 4); 1372a5108eaeSScott Long 1373a5108eaeSScott Long m3_wr_1(sc, ASSP_CONTROL_B, RESET_ASSP); 1374a5108eaeSScott Long data = pci_read_config(sc->dev, PCI_ALLEGRO_CONFIG, 4); 1375a5108eaeSScott Long data &= ~INT_CLK_SELECT; 1376a5108eaeSScott Long if (sc->which == ESS_MAESTRO3) { 1377a5108eaeSScott Long data &= ~INT_CLK_MULT_ENABLE; 1378a5108eaeSScott Long data |= INT_CLK_SRC_NOT_PCI; 1379a5108eaeSScott Long } 1380a5108eaeSScott Long data &= ~(CLK_MULT_MODE_SELECT | CLK_MULT_MODE_SELECT_2); 1381a5108eaeSScott Long pci_write_config(sc->dev, PCI_ALLEGRO_CONFIG, data, 4); 1382a5108eaeSScott Long 1383a5108eaeSScott Long if (sc->which == ESS_ALLEGRO_1) { 1384a5108eaeSScott Long data = pci_read_config(sc->dev, PCI_USER_CONFIG, 4); 1385a5108eaeSScott Long data |= IN_CLK_12MHZ_SELECT; 1386a5108eaeSScott Long pci_write_config(sc->dev, PCI_USER_CONFIG, data, 4); 1387a5108eaeSScott Long } 1388a5108eaeSScott Long 1389a5108eaeSScott Long data = m3_rd_1(sc, ASSP_CONTROL_A); 1390a5108eaeSScott Long data &= ~(DSP_CLK_36MHZ_SELECT | ASSP_CLK_49MHZ_SELECT); 1391a5108eaeSScott Long data |= ASSP_CLK_49MHZ_SELECT; /*XXX assumes 49MHZ dsp XXX*/ 1392a5108eaeSScott Long data |= ASSP_0_WS_ENABLE; 1393a5108eaeSScott Long m3_wr_1(sc, ASSP_CONTROL_A, data); 1394a5108eaeSScott Long 1395a5108eaeSScott Long m3_wr_1(sc, ASSP_CONTROL_B, RUN_ASSP); 1396a5108eaeSScott Long } 1397a5108eaeSScott Long 1398a5108eaeSScott Long static void 1399a5108eaeSScott Long m3_enable_ints(struct sc_info *sc) 1400a5108eaeSScott Long { 1401a5108eaeSScott Long u_int8_t data; 1402a5108eaeSScott Long 1403a5108eaeSScott Long m3_wr_2(sc, HOST_INT_CTRL, ASSP_INT_ENABLE | HV_INT_ENABLE); 1404a5108eaeSScott Long data = m3_rd_1(sc, ASSP_CONTROL_C); 1405a5108eaeSScott Long m3_wr_1(sc, ASSP_CONTROL_C, data | ASSP_HOST_INT_ENABLE); 1406a5108eaeSScott Long } 1407a5108eaeSScott Long 1408a5108eaeSScott Long static void 1409a5108eaeSScott Long m3_amp_enable(struct sc_info *sc) 1410a5108eaeSScott Long { 1411a5108eaeSScott Long u_int32_t gpo, polarity_port, polarity; 1412a5108eaeSScott Long u_int16_t data; 1413a5108eaeSScott Long 1414a5108eaeSScott Long switch (sc->which) { 1415a5108eaeSScott Long case ESS_ALLEGRO_1: 1416a5108eaeSScott Long polarity_port = 0x1800; 1417a5108eaeSScott Long break; 1418a5108eaeSScott Long case ESS_MAESTRO3: 1419a5108eaeSScott Long polarity_port = 0x1100; 1420a5108eaeSScott Long break; 1421a5108eaeSScott Long default: 1422a5108eaeSScott Long panic("bad sc->which"); 1423a5108eaeSScott Long } 1424a5108eaeSScott Long gpo = (polarity_port >> 8) & 0x0f; 1425a5108eaeSScott Long polarity = polarity_port >> 12; 1426a5108eaeSScott Long polarity = !polarity; /* enable */ 1427a5108eaeSScott Long polarity = polarity << gpo; 1428a5108eaeSScott Long gpo = 1 << gpo; 1429a5108eaeSScott Long m3_wr_2(sc, GPIO_MASK, ~gpo); 1430a5108eaeSScott Long data = m3_rd_2(sc, GPIO_DIRECTION); 1431a5108eaeSScott Long m3_wr_2(sc, GPIO_DIRECTION, data | gpo); 1432a5108eaeSScott Long data = GPO_SECONDARY_AC97 | GPO_PRIMARY_AC97 | polarity; 1433a5108eaeSScott Long m3_wr_2(sc, GPIO_DATA, data); 1434a5108eaeSScott Long m3_wr_2(sc, GPIO_MASK, ~0); 1435a5108eaeSScott Long } 1436a5108eaeSScott Long 1437a5108eaeSScott Long static void 1438a5108eaeSScott Long m3_codec_reset(struct sc_info *sc) 1439a5108eaeSScott Long { 1440a5108eaeSScott Long u_int16_t data, dir; 1441a5108eaeSScott Long int retry = 0; 1442a5108eaeSScott Long 1443a5108eaeSScott Long do { 1444a5108eaeSScott Long data = m3_rd_2(sc, GPIO_DIRECTION); 1445a5108eaeSScott Long dir = data | 0x10; /* assuming pci bus master? */ 1446a5108eaeSScott Long 1447a5108eaeSScott Long /* [[remote_codec_config]] */ 1448a5108eaeSScott Long data = m3_rd_2(sc, RING_BUS_CTRL_B); 1449a5108eaeSScott Long m3_wr_2(sc, RING_BUS_CTRL_B, data & ~SECOND_CODEC_ID_MASK); 1450a5108eaeSScott Long data = m3_rd_2(sc, SDO_OUT_DEST_CTRL); 1451a5108eaeSScott Long m3_wr_2(sc, SDO_OUT_DEST_CTRL, data & ~COMMAND_ADDR_OUT); 1452a5108eaeSScott Long data = m3_rd_2(sc, SDO_IN_DEST_CTRL); 1453a5108eaeSScott Long m3_wr_2(sc, SDO_IN_DEST_CTRL, data & ~STATUS_ADDR_IN); 1454a5108eaeSScott Long 1455a5108eaeSScott Long m3_wr_2(sc, RING_BUS_CTRL_A, IO_SRAM_ENABLE); 1456a5108eaeSScott Long DELAY(20); 1457a5108eaeSScott Long 1458a5108eaeSScott Long m3_wr_2(sc, GPIO_DIRECTION, dir & ~GPO_PRIMARY_AC97); 1459a5108eaeSScott Long m3_wr_2(sc, GPIO_MASK, ~GPO_PRIMARY_AC97); 1460a5108eaeSScott Long m3_wr_2(sc, GPIO_DATA, 0); 1461a5108eaeSScott Long m3_wr_2(sc, GPIO_DIRECTION, dir | GPO_PRIMARY_AC97); 1462a5108eaeSScott Long DELAY(sc->delay1 * 1000); /*delay1 (ALLEGRO:50, MAESTRO3:20)*/ 1463a5108eaeSScott Long m3_wr_2(sc, GPIO_DATA, GPO_PRIMARY_AC97); 1464a5108eaeSScott Long DELAY(5); 1465a5108eaeSScott Long m3_wr_2(sc, RING_BUS_CTRL_A, IO_SRAM_ENABLE | 1466a5108eaeSScott Long SERIAL_AC_LINK_ENABLE); 1467a5108eaeSScott Long m3_wr_2(sc, GPIO_MASK, ~0); 1468a5108eaeSScott Long DELAY(sc->delay2 * 1000); /*delay2 (ALLEGRO:800, MAESTRO3:500)*/ 1469a5108eaeSScott Long 1470a5108eaeSScott Long /* [[try read vendor]] */ 1471a5108eaeSScott Long data = m3_rdcd(NULL, sc, 0x7c); 1472a5108eaeSScott Long if ((data == 0) || (data == 0xffff)) { 1473a5108eaeSScott Long retry++; 1474a5108eaeSScott Long if (retry > 3) { 1475a5108eaeSScott Long device_printf(sc->dev, "Codec reset failed\n"); 1476a5108eaeSScott Long break; 1477a5108eaeSScott Long } 1478a5108eaeSScott Long device_printf(sc->dev, "Codec reset retry\n"); 1479a5108eaeSScott Long } else retry = 0; 1480a5108eaeSScott Long } while (retry); 1481a5108eaeSScott Long } 1482a5108eaeSScott Long 1483a5108eaeSScott Long static device_method_t m3_methods[] = { 1484a5108eaeSScott Long DEVMETHOD(device_probe, m3_pci_probe), 1485a5108eaeSScott Long DEVMETHOD(device_attach, m3_pci_attach), 1486a5108eaeSScott Long DEVMETHOD(device_detach, m3_pci_detach), 1487a5108eaeSScott Long DEVMETHOD(device_suspend, m3_pci_suspend), 1488a5108eaeSScott Long DEVMETHOD(device_resume, m3_pci_resume), 1489a5108eaeSScott Long DEVMETHOD(device_shutdown, m3_pci_shutdown), 1490a5108eaeSScott Long { 0, 0 } 1491a5108eaeSScott Long }; 1492a5108eaeSScott Long 1493a5108eaeSScott Long static driver_t m3_driver = { 1494a5108eaeSScott Long "pcm", 1495a5108eaeSScott Long m3_methods, 1496a5108eaeSScott Long sizeof(snddev_info), 1497a5108eaeSScott Long }; 1498a5108eaeSScott Long 1499a5108eaeSScott Long static devclass_t pcm_devclass; 1500a5108eaeSScott Long 1501a5108eaeSScott Long DRIVER_MODULE(snd_maestro3, pci, m3_driver, pcm_devclass, 0, 0); 1502a5108eaeSScott Long MODULE_DEPEND(snd_maestro3, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 1503a5108eaeSScott Long MODULE_VERSION(snd_maestro3, 1); 1504