| 1 | /* $NetBSD: esmvar.h,v 1.18 2011/11/23 23:07:35 jmcneill Exp $ */ |
| 2 | |
| 3 | /*- |
| 4 | * Copyright (c) 2002, 2003 Matt Fredette |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Copyright (c) 2000, 2001 Rene Hexel <rh@NetBSD.org> |
| 8 | * All rights reserved. |
| 9 | * |
| 10 | * Copyright (c) 2000 Taku YAMAMOTO <taku@cent.saitama-u.ac.jp> |
| 11 | * All rights reserved. |
| 12 | * |
| 13 | * Redistribution and use in source and binary forms, with or without |
| 14 | * modification, are permitted provided that the following conditions |
| 15 | * are met: |
| 16 | * 1. Redistributions of source code must retain the above copyright |
| 17 | * notice, this list of conditions and the following disclaimer. |
| 18 | * 2. Redistributions in binary form must reproduce the above copyright |
| 19 | * notice, this list of conditions and the following disclaimer in the |
| 20 | * documentation and/or other materials provided with the distribution. |
| 21 | * |
| 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 32 | * SUCH DAMAGE. |
| 33 | * |
| 34 | * Taku Id: maestro.c,v 1.12 2000/09/06 03:32:34 taku Exp |
| 35 | * FreeBSD: /c/ncvs/src/sys/dev/sound/pci/maestro.c,v 1.4 2000/12/18 01:36:35 cg Exp |
| 36 | * |
| 37 | */ |
| 38 | |
| 39 | /* |
| 40 | * Credits: |
| 41 | * |
| 42 | * This code is based on the FreeBSD driver written by Taku YAMAMOTO |
| 43 | * |
| 44 | * |
| 45 | * Original credits from the FreeBSD driver: |
| 46 | * |
| 47 | * Part of this code (especially in many magic numbers) was heavily inspired |
| 48 | * by the Linux driver originally written by |
| 49 | * Alan Cox <alan.cox@linux.org>, modified heavily by |
| 50 | * Zach Brown <zab@zabbo.net>. |
| 51 | * |
| 52 | * busdma()-ize and buffer size reduction were suggested by |
| 53 | * Cameron Grant <gandalf@vilnya.demon.co.uk>. |
| 54 | * Also he showed me the way to use busdma() suite. |
| 55 | * |
| 56 | * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500 |
| 57 | * were looked at by |
| 58 | * Munehiro Matsuda <haro@tk.kubota.co.jp>, |
| 59 | * who brought patches based on the Linux driver with some simplification. |
| 60 | */ |
| 61 | |
| 62 | /* IRQ timer fequency limits */ |
| 63 | #define MAESTRO_MINFREQ 24 |
| 64 | #define MAESTRO_MAXFREQ 48000 |
| 65 | |
| 66 | /* |
| 67 | * This driver allocates a contiguous 256KB region of memory. |
| 68 | * The Maestro's DMA interface, called the WaveCache, is weak |
| 69 | * (or at least incorrectly documented), and forces us to keep |
| 70 | * things very simple. This region is very carefully divided up |
| 71 | * into 64KB quarters, making 64KB a fundamental constant for |
| 72 | * this implementation - and this is as large as we can allow |
| 73 | * the upper-layer playback and record buffers to become. |
| 74 | */ |
| 75 | #define MAESTRO_QUARTER_SZ (64 * 1024) |
| 76 | |
| 77 | /* |
| 78 | * The first quarter of memory is used while recording. The |
| 79 | * first 512 bytes of it is reserved as a scratch area for the |
| 80 | * APUs that want to write (uninteresting, to us) FIFO status |
| 81 | * information. After some guard space, another 512 bytes is |
| 82 | * reserved for the APUs doing mixing. The remainder of this |
| 83 | * quarter of memory is wasted. |
| 84 | */ |
| 85 | #define MAESTRO_FIFO_OFF (MAESTRO_QUARTER_SZ * 0) |
| 86 | #define MAESTRO_FIFO_SZ (512) |
| 87 | #define MAESTRO_MIXBUF_OFF (MAESTRO_FIFO_OFF + 4096) |
| 88 | #define MAESTRO_MIXBUF_SZ (512) |
| 89 | |
| 90 | /* |
| 91 | * The second quarter of memory is the playback buffer. |
| 92 | */ |
| 93 | #define MAESTRO_PLAYBUF_OFF (MAESTRO_QUARTER_SZ * 1) |
| 94 | #define MAESTRO_PLAYBUF_SZ MAESTRO_QUARTER_SZ |
| 95 | |
| 96 | /* |
| 97 | * The third quarter of memory is the mono record buffer. |
| 98 | * This is the only record buffer that the upper layer knows. |
| 99 | * When recording in stereo, our driver combines (in software) |
| 100 | * separately recorded left and right buffers here. |
| 101 | */ |
| 102 | #define MAESTRO_RECBUF_OFF (MAESTRO_QUARTER_SZ * 2) |
| 103 | #define MAESTRO_RECBUF_SZ MAESTRO_QUARTER_SZ |
| 104 | |
| 105 | /* |
| 106 | * The fourth quarter of memory is the stereo record buffer. |
| 107 | * When recording in stereo, the left and right channels are |
| 108 | * recorded separately into the two halves of this buffer. |
| 109 | */ |
| 110 | #define MAESTRO_RECBUF_L_OFF (MAESTRO_QUARTER_SZ * 3) |
| 111 | #define MAESTRO_RECBUF_L_SZ (MAESTRO_QUARTER_SZ / 2) |
| 112 | #define MAESTRO_RECBUF_R_OFF (MAESTRO_RECBUF_L_OFF + MAESTRO_RECBUF_L_SZ) |
| 113 | #define MAESTRO_RECBUF_R_SZ (MAESTRO_QUARTER_SZ / 2) |
| 114 | |
| 115 | /* |
| 116 | * The size and alignment of the entire region. We keep |
| 117 | * the region aligned to a 128KB boundary, since this should |
| 118 | * force A16..A0 on all chip-generated addresses to correspond |
| 119 | * exactly to APU register contents. |
| 120 | */ |
| 121 | #define MAESTRO_DMA_SZ (MAESTRO_QUARTER_SZ * 4) |
| 122 | #define MAESTRO_DMA_ALIGN (128 * 1024) |
| 123 | |
| 124 | struct esm_dma { |
| 125 | bus_dmamap_t map; |
| 126 | void * addr; |
| 127 | bus_dma_segment_t segs[1]; |
| 128 | int nsegs; |
| 129 | size_t size; |
| 130 | struct esm_dma *next; |
| 131 | }; |
| 132 | |
| 133 | #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr) |
| 134 | #define KERNADDR(p) ((void *)((p)->addr)) |
| 135 | |
| 136 | struct esm_chinfo { |
| 137 | uint32_t base; /* DMA base */ |
| 138 | void * buffer; /* upper layer buffer */ |
| 139 | uint32_t offset; /* offset into buffer */ |
| 140 | uint32_t blocksize; /* block size in bytes */ |
| 141 | uint32_t bufsize; /* buffer size in bytes */ |
| 142 | unsigned num; /* logical channel number */ |
| 143 | uint16_t aputype; /* APU channel type */ |
| 144 | uint16_t apubase; /* first sample number */ |
| 145 | uint16_t apublk; /* blk size in samples per ch */ |
| 146 | uint16_t apubuf; /* buf size in samples per ch */ |
| 147 | uint16_t nextirq; /* pos to trigger next IRQ at */ |
| 148 | uint16_t wcreg_tpl; /* wavecache tag and format */ |
| 149 | uint16_t sample_rate; |
| 150 | }; |
| 151 | |
| 152 | struct esm_softc { |
| 153 | device_t sc_dev; |
| 154 | kmutex_t sc_lock; |
| 155 | kmutex_t sc_intr_lock; |
| 156 | |
| 157 | bus_space_tag_t st; |
| 158 | bus_space_handle_t sh; |
| 159 | bus_size_t sz; |
| 160 | |
| 161 | pcitag_t tag; |
| 162 | pci_chipset_tag_t pc; |
| 163 | bus_dma_tag_t dmat; |
| 164 | pcireg_t subid; |
| 165 | |
| 166 | void *ih; |
| 167 | |
| 168 | struct ac97_codec_if *codec_if; |
| 169 | struct ac97_host_if host_if; |
| 170 | enum ac97_host_flags codec_flags; |
| 171 | |
| 172 | struct esm_dma sc_dma; |
| 173 | int rings_alloced; |
| 174 | |
| 175 | int pactive, ractive; |
| 176 | struct esm_chinfo pch; |
| 177 | struct esm_chinfo rch; |
| 178 | |
| 179 | void (*sc_pintr)(void *); |
| 180 | void *sc_parg; |
| 181 | |
| 182 | void (*sc_rintr)(void *); |
| 183 | void *sc_rarg; |
| 184 | }; |
| 185 | |
| 186 | enum esm_quirk_flags { |
| 187 | ESM_QUIRKF_GPIO = 0x1, /* needs GPIO operation */ |
| 188 | ESM_QUIRKF_SWAPPEDCH = 0x2, /* left/right is reversed */ |
| 189 | }; |
| 190 | |
| 191 | struct esm_quirks { |
| 192 | pci_vendor_id_t eq_vendor; /* subsystem vendor */ |
| 193 | pci_product_id_t eq_product; /* and product */ |
| 194 | |
| 195 | enum esm_quirk_flags eq_quirks; /* needed quirks */ |
| 196 | }; |
| 197 | |
| 198 | int esm_read_codec(void *, uint8_t, uint16_t *); |
| 199 | int esm_write_codec(void *, uint8_t, uint16_t); |
| 200 | int esm_attach_codec(void *, struct ac97_codec_if *); |
| 201 | int esm_reset_codec(void *); |
| 202 | enum ac97_host_flags esm_flags_codec(void *); |
| 203 | |
| 204 | void esm_init(struct esm_softc *); |
| 205 | void esm_initcodec(struct esm_softc *); |
| 206 | |
| 207 | int esm_init_output(void *, void *, int); |
| 208 | int esm_init_input(void *, void *, int); |
| 209 | int esm_trigger_output(void *, void *, void *, int, void (*)(void *), |
| 210 | void *, const audio_params_t *); |
| 211 | int esm_trigger_input(void *, void *, void *, int, void (*)(void *), |
| 212 | void *, const audio_params_t *); |
| 213 | int esm_halt_output(void *); |
| 214 | int esm_halt_input(void *); |
| 215 | int esm_getdev(void *, struct audio_device *); |
| 216 | int esm_round_blocksize(void *, int, int, const audio_params_t *); |
| 217 | int esm_query_encoding(void *, struct audio_encoding *); |
| 218 | int esm_set_params(void *, int, int, audio_params_t *, audio_params_t *, |
| 219 | stream_filter_list_t *, stream_filter_list_t *); |
| 220 | int esm_set_port(void *, mixer_ctrl_t *); |
| 221 | int esm_get_port(void *, mixer_ctrl_t *); |
| 222 | int esm_query_devinfo(void *, mixer_devinfo_t *); |
| 223 | void *esm_malloc(void *, int, size_t); |
| 224 | void esm_free(void *, void *, size_t); |
| 225 | size_t esm_round_buffersize(void *, int, size_t); |
| 226 | paddr_t esm_mappage(void *, void *, off_t, int); |
| 227 | int esm_get_props(void *); |
| 228 | void esm_get_locks(void *, kmutex_t **, kmutex_t **); |
| 229 | |
| 230 | enum esm_quirk_flags esm_get_quirks(pcireg_t); |
| 231 | |