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