1 1.161 riastrad /* $NetBSD: auich.c,v 1.161 2023/05/10 00:11:24 riastradh Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /*- 4 1.139 jmcneill * Copyright (c) 2000, 2004, 2005, 2008 The NetBSD Foundation, Inc. 5 1.1 thorpej * All rights reserved. 6 1.1 thorpej * 7 1.1 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.72 mycroft * by Jason R. Thorpe and by Charles M. Hannum. 9 1.1 thorpej * 10 1.1 thorpej * Redistribution and use in source and binary forms, with or without 11 1.1 thorpej * modification, are permitted provided that the following conditions 12 1.1 thorpej * are met: 13 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.1 thorpej * notice, this list of conditions and the following disclaimer. 15 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.1 thorpej * documentation and/or other materials provided with the distribution. 18 1.1 thorpej * 19 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.1 thorpej */ 31 1.1 thorpej 32 1.1 thorpej /* 33 1.1 thorpej * Copyright (c) 2000 Michael Shalayeff 34 1.1 thorpej * All rights reserved. 35 1.1 thorpej * 36 1.1 thorpej * Redistribution and use in source and binary forms, with or without 37 1.1 thorpej * modification, are permitted provided that the following conditions 38 1.1 thorpej * are met: 39 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 40 1.1 thorpej * notice, this list of conditions and the following disclaimer. 41 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 43 1.1 thorpej * documentation and/or other materials provided with the distribution. 44 1.1 thorpej * 3. The name of the author may not be used to endorse or promote products 45 1.1 thorpej * derived from this software without specific prior written permission. 46 1.1 thorpej * 47 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 48 1.1 thorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 49 1.1 thorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 50 1.1 thorpej * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 51 1.1 thorpej * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 52 1.1 thorpej * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 53 1.1 thorpej * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 55 1.1 thorpej * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 56 1.1 thorpej * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 57 1.1 thorpej * THE POSSIBILITY OF SUCH DAMAGE. 58 1.1 thorpej * 59 1.1 thorpej * from OpenBSD: ich.c,v 1.3 2000/08/11 06:17:18 mickey Exp 60 1.1 thorpej */ 61 1.1 thorpej 62 1.18 kent /* 63 1.18 kent * Copyright (c) 2000 Katsurajima Naoto <raven (at) katsurajima.seya.yokohama.jp> 64 1.18 kent * Copyright (c) 2001 Cameron Grant <cg (at) freebsd.org> 65 1.18 kent * All rights reserved. 66 1.18 kent * 67 1.18 kent * Redistribution and use in source and binary forms, with or without 68 1.18 kent * modification, are permitted provided that the following conditions 69 1.18 kent * are met: 70 1.18 kent * 1. Redistributions of source code must retain the above copyright 71 1.18 kent * notice, this list of conditions and the following disclaimer. 72 1.18 kent * 2. Redistributions in binary form must reproduce the above copyright 73 1.18 kent * notice, this list of conditions and the following disclaimer in the 74 1.18 kent * documentation and/or other materials provided with the distribution. 75 1.18 kent * 76 1.18 kent * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 77 1.18 kent * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 78 1.18 kent * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 79 1.18 kent * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 80 1.18 kent * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 81 1.18 kent * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 82 1.18 kent * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 83 1.18 kent * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 84 1.18 kent * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 85 1.18 kent * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF 86 1.18 kent * SUCH DAMAGE. 87 1.18 kent * 88 1.89 perry * auich_calibrate() was from FreeBSD: ich.c,v 1.22 2002/06/27 22:36:01 scottl Exp 89 1.18 kent */ 90 1.18 kent 91 1.18 kent 92 1.61 soren /* #define AUICH_DEBUG */ 93 1.1 thorpej /* 94 1.1 thorpej * AC'97 audio found on Intel 810/820/440MX chipsets. 95 1.1 thorpej * http://developer.intel.com/design/chipsets/datashts/290655.htm 96 1.1 thorpej * http://developer.intel.com/design/chipsets/manuals/298028.htm 97 1.18 kent * ICH3:http://www.intel.com/design/chipsets/datashts/290716.htm 98 1.18 kent * ICH4:http://www.intel.com/design/chipsets/datashts/290744.htm 99 1.41 kent * ICH5:http://www.intel.com/design/chipsets/datashts/252516.htm 100 1.52 kent * AMD8111: 101 1.52 kent * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24674.pdf 102 1.52 kent * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25720.pdf 103 1.1 thorpej * 104 1.1 thorpej * TODO: 105 1.29 kent * - Add support for the dedicated microphone input. 106 1.33 kent * 107 1.33 kent * NOTE: 108 1.33 kent * - The 440MX B-stepping at running 100MHz has a hardware erratum. 109 1.33 kent * It causes PCI master abort and hangups until cold reboot. 110 1.33 kent * http://www.intel.com/design/chipsets/specupdt/245051.htm 111 1.1 thorpej */ 112 1.5 lukem 113 1.5 lukem #include <sys/cdefs.h> 114 1.161 riastrad __KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.161 2023/05/10 00:11:24 riastradh Exp $"); 115 1.1 thorpej 116 1.1 thorpej #include <sys/param.h> 117 1.1 thorpej #include <sys/systm.h> 118 1.1 thorpej #include <sys/kernel.h> 119 1.139 jmcneill #include <sys/kmem.h> 120 1.1 thorpej #include <sys/device.h> 121 1.1 thorpej #include <sys/fcntl.h> 122 1.1 thorpej #include <sys/proc.h> 123 1.64 kent #include <sys/sysctl.h> 124 1.139 jmcneill #include <sys/audioio.h> 125 1.139 jmcneill #include <sys/bus.h> 126 1.145 riastrad #include <sys/rndsource.h> 127 1.1 thorpej 128 1.1 thorpej #include <dev/pci/pcidevs.h> 129 1.1 thorpej #include <dev/pci/pcivar.h> 130 1.1 thorpej #include <dev/pci/auichreg.h> 131 1.1 thorpej 132 1.155 isaki #include <dev/audio/audio_if.h> 133 1.1 thorpej 134 1.2 thorpej #include <dev/ic/ac97reg.h> 135 1.1 thorpej #include <dev/ic/ac97var.h> 136 1.1 thorpej 137 1.1 thorpej struct auich_dma { 138 1.1 thorpej bus_dmamap_t map; 139 1.117 christos void *addr; 140 1.1 thorpej bus_dma_segment_t segs[1]; 141 1.1 thorpej int nsegs; 142 1.1 thorpej size_t size; 143 1.1 thorpej struct auich_dma *next; 144 1.1 thorpej }; 145 1.1 thorpej 146 1.1 thorpej #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr) 147 1.1 thorpej #define KERNADDR(p) ((void *)((p)->addr)) 148 1.1 thorpej 149 1.1 thorpej struct auich_cdata { 150 1.1 thorpej struct auich_dmalist ic_dmalist_pcmo[ICH_DMALIST_MAX]; 151 1.1 thorpej struct auich_dmalist ic_dmalist_pcmi[ICH_DMALIST_MAX]; 152 1.1 thorpej struct auich_dmalist ic_dmalist_mici[ICH_DMALIST_MAX]; 153 1.1 thorpej }; 154 1.1 thorpej 155 1.1 thorpej #define ICH_CDOFF(x) offsetof(struct auich_cdata, x) 156 1.1 thorpej #define ICH_PCMO_OFF(x) ICH_CDOFF(ic_dmalist_pcmo[(x)]) 157 1.1 thorpej #define ICH_PCMI_OFF(x) ICH_CDOFF(ic_dmalist_pcmi[(x)]) 158 1.1 thorpej #define ICH_MICI_OFF(x) ICH_CDOFF(ic_dmalist_mici[(x)]) 159 1.1 thorpej 160 1.1 thorpej struct auich_softc { 161 1.127 xtraeme device_t sc_dev; 162 1.1 thorpej void *sc_ih; 163 1.139 jmcneill kmutex_t sc_lock; 164 1.139 jmcneill kmutex_t sc_intr_lock; 165 1.1 thorpej 166 1.127 xtraeme device_t sc_audiodev; 167 1.1 thorpej audio_device_t sc_audev; 168 1.1 thorpej 169 1.82 kent pci_chipset_tag_t sc_pc; 170 1.82 kent pcitag_t sc_pt; 171 1.1 thorpej bus_space_tag_t iot; 172 1.1 thorpej bus_space_handle_t mix_ioh; 173 1.82 kent bus_size_t mix_size; 174 1.1 thorpej bus_space_handle_t aud_ioh; 175 1.82 kent bus_size_t aud_size; 176 1.1 thorpej bus_dma_tag_t dmat; 177 1.102 jmcneill pci_intr_handle_t intrh; 178 1.1 thorpej 179 1.1 thorpej struct ac97_codec_if *codec_if; 180 1.1 thorpej struct ac97_host_if host_if; 181 1.94 jmcneill int sc_codecnum; 182 1.94 jmcneill int sc_codectype; 183 1.139 jmcneill int sc_fixedrate; 184 1.105 christos enum ac97_host_flags sc_codecflags; 185 1.116 thorpej bool sc_spdif; 186 1.1 thorpej 187 1.130 sborrill /* multi-channel control bits */ 188 1.130 sborrill int sc_pcm246_mask; 189 1.130 sborrill int sc_pcm2; 190 1.130 sborrill int sc_pcm4; 191 1.130 sborrill int sc_pcm6; 192 1.130 sborrill 193 1.1 thorpej /* DMA scatter-gather lists. */ 194 1.1 thorpej bus_dmamap_t sc_cddmamap; 195 1.1 thorpej #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr 196 1.1 thorpej 197 1.1 thorpej struct auich_cdata *sc_cdata; 198 1.1 thorpej 199 1.73 mycroft struct auich_ring { 200 1.73 mycroft int qptr; 201 1.73 mycroft struct auich_dmalist *dmalist; 202 1.73 mycroft 203 1.85 kent uint32_t start, p, end; 204 1.73 mycroft int blksize; 205 1.73 mycroft 206 1.73 mycroft void (*intr)(void *); 207 1.73 mycroft void *arg; 208 1.73 mycroft } pcmo, pcmi, mici; 209 1.1 thorpej 210 1.1 thorpej struct auich_dma *sc_dmas; 211 1.1 thorpej 212 1.18 kent /* SiS 7012 hack */ 213 1.70 mycroft int sc_sample_shift; 214 1.18 kent int sc_sts_reg; 215 1.34 kent /* 440MX workaround */ 216 1.34 kent int sc_dmamap_flags; 217 1.133 jakllsch /* flags */ 218 1.158 maxv u_int sc_iose :1, 219 1.135 jakllsch :31; 220 1.9 augustss 221 1.64 kent /* sysctl */ 222 1.64 kent struct sysctllog *sc_log; 223 1.64 kent uint32_t sc_ac97_clock; 224 1.64 kent int sc_ac97_clock_mib; 225 1.80 kent 226 1.91 jmcneill int sc_modem_offset; 227 1.91 jmcneill 228 1.91 jmcneill #define AUICH_AUDIO_NFORMATS 3 229 1.91 jmcneill #define AUICH_MODEM_NFORMATS 1 230 1.91 jmcneill struct audio_format sc_audio_formats[AUICH_AUDIO_NFORMATS]; 231 1.91 jmcneill struct audio_format sc_modem_formats[AUICH_MODEM_NFORMATS]; 232 1.148 christos 233 1.148 christos int sc_cas_been_used; 234 1.1 thorpej }; 235 1.1 thorpej 236 1.1 thorpej /* Debug */ 237 1.61 soren #ifdef AUICH_DEBUG 238 1.146 christos #define DPRINTF(l,x) do { if (auich_debug & (l)) aprint_normal_dev x; } while(0) 239 1.1 thorpej int auich_debug = 0xfffe; 240 1.1 thorpej #define ICH_DEBUG_CODECIO 0x0001 241 1.1 thorpej #define ICH_DEBUG_DMA 0x0002 242 1.61 soren #define ICH_DEBUG_INTR 0x0004 243 1.1 thorpej #else 244 1.1 thorpej #define DPRINTF(x,y) /* nothing */ 245 1.1 thorpej #endif 246 1.1 thorpej 247 1.127 xtraeme static int auich_match(device_t, cfdata_t, void *); 248 1.127 xtraeme static void auich_attach(device_t, device_t, void *); 249 1.127 xtraeme static int auich_detach(device_t, int); 250 1.129 dyoung static void auich_childdet(device_t, device_t); 251 1.81 kent static int auich_intr(void *); 252 1.1 thorpej 253 1.129 dyoung CFATTACH_DECL2_NEW(auich, sizeof(struct auich_softc), 254 1.131 dyoung auich_match, auich_attach, auich_detach, NULL, NULL, auich_childdet); 255 1.1 thorpej 256 1.109 kent static int auich_open(void *, int); 257 1.109 kent static void auich_close(void *); 258 1.155 isaki static int auich_query_format(void *, struct audio_format_query *); 259 1.155 isaki static int auich_set_format(void *, int, 260 1.155 isaki const audio_params_t *, const audio_params_t *, 261 1.155 isaki audio_filter_reg_t *, audio_filter_reg_t *); 262 1.90 mycroft static void auich_halt_pipe(struct auich_softc *, int); 263 1.81 kent static int auich_halt_output(void *); 264 1.81 kent static int auich_halt_input(void *); 265 1.81 kent static int auich_getdev(void *, struct audio_device *); 266 1.81 kent static int auich_set_port(void *, mixer_ctrl_t *); 267 1.81 kent static int auich_get_port(void *, mixer_ctrl_t *); 268 1.81 kent static int auich_query_devinfo(void *, mixer_devinfo_t *); 269 1.139 jmcneill static void *auich_allocm(void *, int, size_t); 270 1.139 jmcneill static void auich_freem(void *, void *, size_t); 271 1.81 kent static size_t auich_round_buffersize(void *, int, size_t); 272 1.81 kent static int auich_get_props(void *); 273 1.90 mycroft static void auich_trigger_pipe(struct auich_softc *, int, struct auich_ring *); 274 1.90 mycroft static void auich_intr_pipe(struct auich_softc *, int, struct auich_ring *); 275 1.81 kent static int auich_trigger_output(void *, void *, void *, int, 276 1.84 kent void (*)(void *), void *, const audio_params_t *); 277 1.81 kent static int auich_trigger_input(void *, void *, void *, int, 278 1.84 kent void (*)(void *), void *, const audio_params_t *); 279 1.139 jmcneill static void auich_get_locks(void *, kmutex_t **, kmutex_t **); 280 1.81 kent 281 1.81 kent static int auich_alloc_cdata(struct auich_softc *); 282 1.81 kent 283 1.81 kent static int auich_allocmem(struct auich_softc *, size_t, size_t, 284 1.81 kent struct auich_dma *); 285 1.81 kent static int auich_freemem(struct auich_softc *, struct auich_dma *); 286 1.1 thorpej 287 1.137 dyoung static bool auich_resume(device_t, const pmf_qual_t *); 288 1.81 kent static int auich_set_rate(struct auich_softc *, int, u_long); 289 1.64 kent static int auich_sysctl_verify(SYSCTLFN_ARGS); 290 1.127 xtraeme static void auich_finish_attach(device_t); 291 1.81 kent static void auich_calibrate(struct auich_softc *); 292 1.95 jmcneill static void auich_clear_cas(struct auich_softc *); 293 1.17 augustss 294 1.81 kent static int auich_attach_codec(void *, struct ac97_codec_if *); 295 1.85 kent static int auich_read_codec(void *, uint8_t, uint16_t *); 296 1.85 kent static int auich_write_codec(void *, uint8_t, uint16_t); 297 1.81 kent static int auich_reset_codec(void *); 298 1.105 christos static enum ac97_host_flags auich_flags_codec(void *); 299 1.116 thorpej static void auich_spdif_event(void *, bool); 300 1.9 augustss 301 1.97 thorpej static const struct audio_hw_if auich_hw_if = { 302 1.153 isaki .open = auich_open, 303 1.153 isaki .close = auich_close, 304 1.155 isaki .query_format = auich_query_format, 305 1.155 isaki .set_format = auich_set_format, 306 1.153 isaki .halt_output = auich_halt_output, 307 1.153 isaki .halt_input = auich_halt_input, 308 1.153 isaki .getdev = auich_getdev, 309 1.153 isaki .set_port = auich_set_port, 310 1.153 isaki .get_port = auich_get_port, 311 1.153 isaki .query_devinfo = auich_query_devinfo, 312 1.153 isaki .allocm = auich_allocm, 313 1.153 isaki .freem = auich_freem, 314 1.153 isaki .round_buffersize = auich_round_buffersize, 315 1.153 isaki .get_props = auich_get_props, 316 1.153 isaki .trigger_output = auich_trigger_output, 317 1.153 isaki .trigger_input = auich_trigger_input, 318 1.153 isaki .get_locks = auich_get_locks, 319 1.1 thorpej }; 320 1.1 thorpej 321 1.91 jmcneill #define AUICH_FORMATS_1CH 0 322 1.80 kent #define AUICH_FORMATS_4CH 1 323 1.80 kent #define AUICH_FORMATS_6CH 2 324 1.155 isaki #define AUICH_FORMAT(aumode, ch, chmask) \ 325 1.155 isaki { \ 326 1.155 isaki .mode = (aumode), \ 327 1.155 isaki .encoding = AUDIO_ENCODING_SLINEAR_LE, \ 328 1.155 isaki .validbits = 16, \ 329 1.155 isaki .precision = 16, \ 330 1.155 isaki .channels = (ch), \ 331 1.155 isaki .channel_mask = (chmask), \ 332 1.155 isaki .frequency_type = 0, \ 333 1.155 isaki .frequency = { 8000, 48000 }, \ 334 1.155 isaki } 335 1.91 jmcneill static const struct audio_format auich_audio_formats[AUICH_AUDIO_NFORMATS] = { 336 1.155 isaki AUICH_FORMAT(AUMODE_PLAY | AUMODE_RECORD, 2, AUFMT_STEREO), 337 1.155 isaki AUICH_FORMAT(AUMODE_PLAY , 4, AUFMT_SURROUND4), 338 1.155 isaki AUICH_FORMAT(AUMODE_PLAY , 6, AUFMT_DOLBY_5_1), 339 1.80 kent }; 340 1.80 kent 341 1.109 kent #define AUICH_SPDIF_NFORMATS 1 342 1.109 kent static const struct audio_format auich_spdif_formats[AUICH_SPDIF_NFORMATS] = { 343 1.155 isaki { 344 1.155 isaki .mode = AUMODE_PLAY | AUMODE_RECORD, 345 1.155 isaki .encoding = AUDIO_ENCODING_SLINEAR_LE, 346 1.155 isaki .validbits = 16, 347 1.155 isaki .precision = 16, 348 1.155 isaki .channels = 2, 349 1.155 isaki .channel_mask = AUFMT_STEREO, 350 1.155 isaki .frequency_type = 1, 351 1.155 isaki .frequency = { 48000 }, 352 1.155 isaki }, 353 1.109 kent }; 354 1.109 kent 355 1.91 jmcneill static const struct audio_format auich_modem_formats[AUICH_MODEM_NFORMATS] = { 356 1.155 isaki { 357 1.155 isaki .mode = AUMODE_PLAY | AUMODE_RECORD, 358 1.155 isaki .encoding = AUDIO_ENCODING_SLINEAR_LE, 359 1.155 isaki .validbits = 16, 360 1.155 isaki .precision = 16, 361 1.155 isaki .channels = 1, 362 1.155 isaki .channel_mask = AUFMT_MONAURAL, 363 1.155 isaki .frequency_type = 2, 364 1.155 isaki .frequency = { 8000, 16000 }, 365 1.155 isaki }, 366 1.91 jmcneill }; 367 1.91 jmcneill 368 1.79 kent #define PCI_ID_CODE0(v, p) PCI_ID_CODE(PCI_VENDOR_##v, PCI_PRODUCT_##v##_##p) 369 1.79 kent #define PCIID_ICH PCI_ID_CODE0(INTEL, 82801AA_ACA) 370 1.79 kent #define PCIID_ICH0 PCI_ID_CODE0(INTEL, 82801AB_ACA) 371 1.79 kent #define PCIID_ICH2 PCI_ID_CODE0(INTEL, 82801BA_ACA) 372 1.79 kent #define PCIID_440MX PCI_ID_CODE0(INTEL, 82440MX_ACA) 373 1.79 kent #define PCIID_ICH3 PCI_ID_CODE0(INTEL, 82801CA_AC) 374 1.79 kent #define PCIID_ICH4 PCI_ID_CODE0(INTEL, 82801DB_AC) 375 1.79 kent #define PCIID_ICH5 PCI_ID_CODE0(INTEL, 82801EB_AC) 376 1.79 kent #define PCIID_ICH6 PCI_ID_CODE0(INTEL, 82801FB_AC) 377 1.100 xtraeme #define PCIID_ICH7 PCI_ID_CODE0(INTEL, 82801G_ACA) 378 1.101 xtraeme #define PCIID_I6300ESB PCI_ID_CODE0(INTEL, 6300ESB_ACA) 379 1.79 kent #define PCIID_SIS7012 PCI_ID_CODE0(SIS, 7012_AC) 380 1.79 kent #define PCIID_NFORCE PCI_ID_CODE0(NVIDIA, NFORCE_MCP_AC) 381 1.79 kent #define PCIID_NFORCE2 PCI_ID_CODE0(NVIDIA, NFORCE2_MCPT_AC) 382 1.88 jdolecek #define PCIID_NFORCE2_400 PCI_ID_CODE0(NVIDIA, NFORCE2_400_MCPT_AC) 383 1.79 kent #define PCIID_NFORCE3 PCI_ID_CODE0(NVIDIA, NFORCE3_MCPT_AC) 384 1.79 kent #define PCIID_NFORCE3_250 PCI_ID_CODE0(NVIDIA, NFORCE3_250_MCPT_AC) 385 1.87 kent #define PCIID_NFORCE4 PCI_ID_CODE0(NVIDIA, NFORCE4_AC) 386 1.111 bsh #define PCIID_NFORCE430 PCI_ID_CODE0(NVIDIA, NFORCE430_AC) 387 1.79 kent #define PCIID_AMD768 PCI_ID_CODE0(AMD, PBC768_AC) 388 1.79 kent #define PCIID_AMD8111 PCI_ID_CODE0(AMD, PBC8111_AC) 389 1.79 kent 390 1.93 jmcneill #define PCIID_ICH3MODEM PCI_ID_CODE0(INTEL, 82801CA_MOD) 391 1.91 jmcneill #define PCIID_ICH4MODEM PCI_ID_CODE0(INTEL, 82801DB_MOD) 392 1.118 xtraeme #define PCIID_ICH6MODEM PCI_ID_CODE0(INTEL, 82801FB_ACM) 393 1.91 jmcneill 394 1.91 jmcneill struct auich_devtype { 395 1.79 kent pcireg_t id; 396 1.79 kent const char *name; 397 1.79 kent const char *shortname; /* must be less than 11 characters */ 398 1.91 jmcneill }; 399 1.91 jmcneill 400 1.91 jmcneill static const struct auich_devtype auich_audio_devices[] = { 401 1.79 kent { PCIID_ICH, "i82801AA (ICH) AC-97 Audio", "ICH" }, 402 1.80 kent { PCIID_ICH0, "i82801AB (ICH0) AC-97 Audio", "ICH0" }, 403 1.80 kent { PCIID_ICH2, "i82801BA (ICH2) AC-97 Audio", "ICH2" }, 404 1.80 kent { PCIID_440MX, "i82440MX AC-97 Audio", "440MX" }, 405 1.80 kent { PCIID_ICH3, "i82801CA (ICH3) AC-97 Audio", "ICH3" }, 406 1.80 kent { PCIID_ICH4, "i82801DB/DBM (ICH4/ICH4M) AC-97 Audio", "ICH4" }, 407 1.80 kent { PCIID_ICH5, "i82801EB (ICH5) AC-97 Audio", "ICH5" }, 408 1.80 kent { PCIID_ICH6, "i82801FB (ICH6) AC-97 Audio", "ICH6" }, 409 1.100 xtraeme { PCIID_ICH7, "i82801GB/GR (ICH7) AC-97 Audio", "ICH7" }, 410 1.101 xtraeme { PCIID_I6300ESB, "Intel 6300ESB AC-97 Audio", "I6300ESB" }, 411 1.80 kent { PCIID_SIS7012, "SiS 7012 AC-97 Audio", "SiS7012" }, 412 1.79 kent { PCIID_NFORCE, "nForce MCP AC-97 Audio", "nForce" }, 413 1.79 kent { PCIID_NFORCE2, "nForce2 MCP-T AC-97 Audio", "nForce2" }, 414 1.88 jdolecek { PCIID_NFORCE2_400, "nForce2 400 MCP-T AC-97 Audio", "nForce2" }, 415 1.79 kent { PCIID_NFORCE3, "nForce3 MCP-T AC-97 Audio", "nForce3" }, 416 1.80 kent { PCIID_NFORCE3_250, "nForce3 250 MCP-T AC-97 Audio", "nForce3" }, 417 1.87 kent { PCIID_NFORCE4, "nForce4 AC-97 Audio", "nForce4" }, 418 1.111 bsh { PCIID_NFORCE430, "nForce430 (MCP51) AC-97 Audio", "nForce430" }, 419 1.79 kent { PCIID_AMD768, "AMD768 AC-97 Audio", "AMD768" }, 420 1.79 kent { PCIID_AMD8111,"AMD8111 AC-97 Audio", "AMD8111" }, 421 1.79 kent { 0, NULL, NULL }, 422 1.1 thorpej }; 423 1.1 thorpej 424 1.91 jmcneill static const struct auich_devtype auich_modem_devices[] = { 425 1.91 jmcneill #ifdef AUICH_ATTACH_MODEM 426 1.94 jmcneill { PCIID_ICH3MODEM, "i82801CA (ICH3) AC-97 Modem", "ICH3MODEM" }, 427 1.91 jmcneill { PCIID_ICH4MODEM, "i82801DB (ICH4) AC-97 Modem", "ICH4MODEM" }, 428 1.118 xtraeme { PCIID_ICH6MODEM, "i82801FB (ICH6) AC-97 Modem", "ICH6MODEM" }, 429 1.91 jmcneill #endif 430 1.91 jmcneill { 0, NULL, NULL }, 431 1.91 jmcneill }; 432 1.91 jmcneill 433 1.1 thorpej static const struct auich_devtype * 434 1.91 jmcneill auich_lookup(struct pci_attach_args *pa, const struct auich_devtype *auich_devices) 435 1.1 thorpej { 436 1.1 thorpej const struct auich_devtype *d; 437 1.1 thorpej 438 1.1 thorpej for (d = auich_devices; d->name != NULL; d++) { 439 1.79 kent if (pa->pa_id == d->id) 440 1.85 kent return d; 441 1.1 thorpej } 442 1.1 thorpej 443 1.85 kent return NULL; 444 1.1 thorpej } 445 1.1 thorpej 446 1.81 kent static int 447 1.127 xtraeme auich_match(device_t parent, cfdata_t match, void *aux) 448 1.1 thorpej { 449 1.85 kent struct pci_attach_args *pa; 450 1.1 thorpej 451 1.85 kent pa = aux; 452 1.91 jmcneill if (auich_lookup(pa, auich_audio_devices) != NULL) 453 1.91 jmcneill return 1; 454 1.91 jmcneill if (auich_lookup(pa, auich_modem_devices) != NULL) 455 1.85 kent return 1; 456 1.1 thorpej 457 1.85 kent return 0; 458 1.1 thorpej } 459 1.1 thorpej 460 1.81 kent static void 461 1.127 xtraeme auich_attach(device_t parent, device_t self, void *aux) 462 1.1 thorpej { 463 1.127 xtraeme struct auich_softc *sc = device_private(self); 464 1.85 kent struct pci_attach_args *pa; 465 1.105 christos pcireg_t v, subdev; 466 1.1 thorpej const char *intrstr; 467 1.1 thorpej const struct auich_devtype *d; 468 1.96 atatat const struct sysctlnode *node, *node_ac97clock; 469 1.80 kent int err, node_mib, i; 470 1.143 christos char intrbuf[PCI_INTRSTR_LEN]; 471 1.1 thorpej 472 1.127 xtraeme sc->sc_dev = self; 473 1.85 kent pa = aux; 474 1.35 thorpej 475 1.94 jmcneill if ((d = auich_lookup(pa, auich_modem_devices)) != NULL) { 476 1.91 jmcneill sc->sc_modem_offset = 0x10; 477 1.94 jmcneill sc->sc_codectype = AC97_CODEC_TYPE_MODEM; 478 1.94 jmcneill } else if ((d = auich_lookup(pa, auich_audio_devices)) != NULL) { 479 1.91 jmcneill sc->sc_modem_offset = 0; 480 1.94 jmcneill sc->sc_codectype = AC97_CODEC_TYPE_AUDIO; 481 1.94 jmcneill } else 482 1.1 thorpej panic("auich_attach: impossible"); 483 1.1 thorpej 484 1.94 jmcneill if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) 485 1.91 jmcneill aprint_naive(": Audio controller\n"); 486 1.91 jmcneill else 487 1.91 jmcneill aprint_naive(": Modem controller\n"); 488 1.91 jmcneill 489 1.33 kent sc->sc_pc = pa->pa_pc; 490 1.33 kent sc->sc_pt = pa->pa_tag; 491 1.35 thorpej 492 1.35 thorpej aprint_normal(": %s\n", d->name); 493 1.1 thorpej 494 1.91 jmcneill if (d->id == PCIID_ICH4 || d->id == PCIID_ICH5 || d->id == PCIID_ICH6 495 1.101 xtraeme || d->id == PCIID_ICH7 || d->id == PCIID_I6300ESB 496 1.101 xtraeme || d->id == PCIID_ICH4MODEM) { 497 1.55 kent /* 498 1.101 xtraeme * Use native mode for Intel 6300ESB and ICH4/ICH5/ICH6/ICH7 499 1.55 kent */ 500 1.133 jakllsch 501 1.55 kent if (pci_mapreg_map(pa, ICH_MMBAR, PCI_MAPREG_TYPE_MEM, 0, 502 1.133 jakllsch &sc->iot, &sc->mix_ioh, NULL, &sc->mix_size)) { 503 1.133 jakllsch goto retry_map; 504 1.55 kent } 505 1.55 kent if (pci_mapreg_map(pa, ICH_MBBAR, PCI_MAPREG_TYPE_MEM, 0, 506 1.133 jakllsch &sc->iot, &sc->aud_ioh, NULL, &sc->aud_size)) { 507 1.133 jakllsch goto retry_map; 508 1.55 kent } 509 1.133 jakllsch goto map_done; 510 1.133 jakllsch } else 511 1.133 jakllsch goto non_native_map; 512 1.133 jakllsch 513 1.133 jakllsch retry_map: 514 1.133 jakllsch sc->sc_iose = 1; 515 1.133 jakllsch v = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_CFG); 516 1.133 jakllsch pci_conf_write(pa->pa_pc, pa->pa_tag, ICH_CFG, 517 1.133 jakllsch v | ICH_CFG_IOSE); 518 1.133 jakllsch 519 1.133 jakllsch non_native_map: 520 1.133 jakllsch if (pci_mapreg_map(pa, ICH_NAMBAR, PCI_MAPREG_TYPE_IO, 0, 521 1.133 jakllsch &sc->iot, &sc->mix_ioh, NULL, &sc->mix_size)) { 522 1.133 jakllsch aprint_error_dev(self, "can't map codec i/o space\n"); 523 1.133 jakllsch return; 524 1.133 jakllsch } 525 1.133 jakllsch if (pci_mapreg_map(pa, ICH_NABMBAR, PCI_MAPREG_TYPE_IO, 0, 526 1.133 jakllsch &sc->iot, &sc->aud_ioh, NULL, &sc->aud_size)) { 527 1.133 jakllsch aprint_error_dev(self, "can't map device i/o space\n"); 528 1.133 jakllsch return; 529 1.1 thorpej } 530 1.133 jakllsch 531 1.133 jakllsch map_done: 532 1.1 thorpej sc->dmat = pa->pa_dmat; 533 1.1 thorpej 534 1.1 thorpej /* enable bus mastering */ 535 1.52 kent v = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 536 1.1 thorpej pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 537 1.66 mycroft v | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_BACKTOBACK_ENABLE); 538 1.1 thorpej 539 1.139 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 540 1.140 mrg mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); 541 1.139 jmcneill 542 1.1 thorpej /* Map and establish the interrupt. */ 543 1.102 jmcneill if (pci_intr_map(pa, &sc->intrh)) { 544 1.127 xtraeme aprint_error_dev(self, "can't map interrupt\n"); 545 1.1 thorpej return; 546 1.1 thorpej } 547 1.143 christos intrstr = pci_intr_string(pa->pa_pc, sc->intrh, intrbuf, sizeof(intrbuf)); 548 1.152 jdolecek sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, sc->intrh, IPL_AUDIO, 549 1.152 jdolecek auich_intr, sc, device_xname(sc->sc_dev)); 550 1.1 thorpej if (sc->sc_ih == NULL) { 551 1.127 xtraeme aprint_error_dev(self, "can't establish interrupt"); 552 1.1 thorpej if (intrstr != NULL) 553 1.132 njoly aprint_error(" at %s", intrstr); 554 1.132 njoly aprint_error("\n"); 555 1.1 thorpej return; 556 1.1 thorpej } 557 1.127 xtraeme aprint_normal_dev(self, "interrupting at %s\n", intrstr); 558 1.1 thorpej 559 1.48 kent snprintf(sc->sc_audev.name, MAX_AUDIO_DEV_LEN, "%s AC97", d->shortname); 560 1.48 kent snprintf(sc->sc_audev.version, MAX_AUDIO_DEV_LEN, 561 1.48 kent "0x%02x", PCI_REVISION(pa->pa_class)); 562 1.127 xtraeme strlcpy(sc->sc_audev.config, device_xname(self), MAX_AUDIO_DEV_LEN); 563 1.1 thorpej 564 1.18 kent /* SiS 7012 needs special handling */ 565 1.79 kent if (d->id == PCIID_SIS7012) { 566 1.18 kent sc->sc_sts_reg = ICH_PICB; 567 1.70 mycroft sc->sc_sample_shift = 0; 568 1.130 sborrill sc->sc_pcm246_mask = ICH_SIS_PCM246_MASK; 569 1.130 sborrill sc->sc_pcm2 = ICH_SIS_PCM2; 570 1.130 sborrill sc->sc_pcm4 = ICH_SIS_PCM4; 571 1.130 sborrill sc->sc_pcm6 = ICH_SIS_PCM6; 572 1.83 cube /* Un-mute output. From Linux. */ 573 1.83 cube bus_space_write_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL, 574 1.83 cube bus_space_read_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL) | 575 1.83 cube ICH_SIS_CTL_UNMUTE); 576 1.18 kent } else { 577 1.18 kent sc->sc_sts_reg = ICH_STS; 578 1.70 mycroft sc->sc_sample_shift = 1; 579 1.130 sborrill sc->sc_pcm246_mask = ICH_PCM246_MASK; 580 1.130 sborrill sc->sc_pcm2 = ICH_PCM2; 581 1.130 sborrill sc->sc_pcm4 = ICH_PCM4; 582 1.130 sborrill sc->sc_pcm6 = ICH_PCM6; 583 1.18 kent } 584 1.38 kent 585 1.34 kent /* Workaround for a 440MX B-stepping erratum */ 586 1.34 kent sc->sc_dmamap_flags = BUS_DMA_COHERENT; 587 1.79 kent if (d->id == PCIID_440MX) { 588 1.34 kent sc->sc_dmamap_flags |= BUS_DMA_NOCACHE; 589 1.127 xtraeme aprint_normal_dev(self, "DMA bug workaround enabled\n"); 590 1.34 kent } 591 1.18 kent 592 1.1 thorpej /* Set up DMA lists. */ 593 1.73 mycroft sc->pcmo.qptr = sc->pcmi.qptr = sc->mici.qptr = 0; 594 1.1 thorpej auich_alloc_cdata(sc); 595 1.1 thorpej 596 1.146 christos DPRINTF(ICH_DEBUG_DMA, (sc->sc_dev, "%s: lists %p %p %p\n", 597 1.146 christos __func__, sc->pcmo.dmalist, sc->pcmi.dmalist, sc->mici.dmalist)); 598 1.1 thorpej 599 1.94 jmcneill /* Modem codecs are always the secondary codec on ICH */ 600 1.94 jmcneill sc->sc_codecnum = sc->sc_codectype == AC97_CODEC_TYPE_MODEM ? 1 : 0; 601 1.91 jmcneill 602 1.1 thorpej sc->host_if.arg = sc; 603 1.1 thorpej sc->host_if.attach = auich_attach_codec; 604 1.1 thorpej sc->host_if.read = auich_read_codec; 605 1.1 thorpej sc->host_if.write = auich_write_codec; 606 1.1 thorpej sc->host_if.reset = auich_reset_codec; 607 1.105 christos sc->host_if.flags = auich_flags_codec; 608 1.109 kent sc->host_if.spdif_event = auich_spdif_event; 609 1.105 christos 610 1.105 christos subdev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 611 1.105 christos switch (subdev) { 612 1.105 christos case 0x202f161f: /* Gateway 7326GZ */ 613 1.105 christos case 0x203a161f: /* Gateway 4028GZ */ 614 1.105 christos case 0x204c161f: /* Kvazar-Micro Senator 3592XT */ 615 1.105 christos case 0x8144104d: /* Sony VAIO PCG-TR* */ 616 1.106 jmcneill case 0x8197104d: /* Sony S1XP */ 617 1.105 christos case 0x81c0104d: /* Sony VAIO type T */ 618 1.106 jmcneill case 0x81c5104d: /* Sony VAIO VGN-B1XP */ 619 1.105 christos sc->sc_codecflags = AC97_HOST_INVERTED_EAMP; 620 1.105 christos break; 621 1.105 christos default: 622 1.105 christos sc->sc_codecflags = 0; 623 1.105 christos break; 624 1.105 christos } 625 1.1 thorpej 626 1.139 jmcneill if (ac97_attach_type(&sc->host_if, self, sc->sc_codectype, 627 1.139 jmcneill &sc->sc_lock) != 0) 628 1.1 thorpej return; 629 1.139 jmcneill 630 1.139 jmcneill mutex_enter(&sc->sc_lock); 631 1.109 kent sc->codec_if->vtbl->unlock(sc->codec_if); 632 1.139 jmcneill sc->sc_fixedrate = AC97_IS_FIXED_RATE(sc->codec_if); 633 1.1 thorpej 634 1.80 kent /* setup audio_format */ 635 1.94 jmcneill if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) { 636 1.149 msaitoh memcpy(sc->sc_audio_formats, auich_audio_formats, 637 1.149 msaitoh sizeof(auich_audio_formats)); 638 1.91 jmcneill if (!AC97_IS_4CH(sc->codec_if)) 639 1.91 jmcneill AUFMT_INVALIDATE(&sc->sc_audio_formats[AUICH_FORMATS_4CH]); 640 1.91 jmcneill if (!AC97_IS_6CH(sc->codec_if)) 641 1.91 jmcneill AUFMT_INVALIDATE(&sc->sc_audio_formats[AUICH_FORMATS_6CH]); 642 1.91 jmcneill if (AC97_IS_FIXED_RATE(sc->codec_if)) { 643 1.91 jmcneill for (i = 0; i < AUICH_AUDIO_NFORMATS; i++) { 644 1.91 jmcneill sc->sc_audio_formats[i].frequency_type = 1; 645 1.91 jmcneill sc->sc_audio_formats[i].frequency[0] = 48000; 646 1.91 jmcneill } 647 1.80 kent } 648 1.139 jmcneill mutex_exit(&sc->sc_lock); 649 1.91 jmcneill } else { 650 1.139 jmcneill mutex_exit(&sc->sc_lock); 651 1.149 msaitoh memcpy(sc->sc_modem_formats, auich_modem_formats, 652 1.149 msaitoh sizeof(auich_modem_formats)); 653 1.80 kent } 654 1.80 kent 655 1.9 augustss /* Watch for power change */ 656 1.120 jmcneill if (!pmf_device_register(self, NULL, auich_resume)) 657 1.120 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 658 1.29 kent 659 1.42 mycroft config_interrupts(self, auich_finish_attach); 660 1.64 kent 661 1.64 kent /* sysctl setup */ 662 1.139 jmcneill if (sc->sc_fixedrate && sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) 663 1.64 kent return; 664 1.91 jmcneill 665 1.64 kent err = sysctl_createv(&sc->sc_log, 0, NULL, &node, 0, 666 1.127 xtraeme CTLTYPE_NODE, device_xname(self), NULL, NULL, 0, 667 1.64 kent NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL); 668 1.64 kent if (err != 0) 669 1.64 kent goto sysctl_err; 670 1.64 kent node_mib = node->sysctl_num; 671 1.91 jmcneill 672 1.139 jmcneill if (!sc->sc_fixedrate) { 673 1.91 jmcneill /* passing the sc address instead of &sc->sc_ac97_clock */ 674 1.91 jmcneill err = sysctl_createv(&sc->sc_log, 0, NULL, &node_ac97clock, 675 1.91 jmcneill CTLFLAG_READWRITE, 676 1.91 jmcneill CTLTYPE_INT, "ac97rate", 677 1.91 jmcneill SYSCTL_DESCR("AC'97 codec link rate"), 678 1.141 dsl auich_sysctl_verify, 0, (void *)sc, 0, 679 1.91 jmcneill CTL_HW, node_mib, CTL_CREATE, CTL_EOL); 680 1.91 jmcneill if (err != 0) 681 1.91 jmcneill goto sysctl_err; 682 1.91 jmcneill sc->sc_ac97_clock_mib = node_ac97clock->sysctl_num; 683 1.91 jmcneill } 684 1.64 kent 685 1.64 kent return; 686 1.64 kent 687 1.64 kent sysctl_err: 688 1.146 christos aprint_error_dev(self, "failed to add sysctl nodes. (%d)\n", err); 689 1.64 kent return; /* failure of sysctl is not fatal. */ 690 1.64 kent } 691 1.64 kent 692 1.129 dyoung static void 693 1.129 dyoung auich_childdet(device_t self, device_t child) 694 1.129 dyoung { 695 1.129 dyoung struct auich_softc *sc = device_private(self); 696 1.129 dyoung 697 1.129 dyoung KASSERT(sc->sc_audiodev == child); 698 1.129 dyoung sc->sc_audiodev = NULL; 699 1.129 dyoung } 700 1.82 kent 701 1.81 kent static int 702 1.128 dyoung auich_detach(device_t self, int flags) 703 1.64 kent { 704 1.128 dyoung struct auich_softc *sc = device_private(self); 705 1.161 riastrad int error; 706 1.82 kent 707 1.64 kent /* audio */ 708 1.161 riastrad error = config_detach_children(self, flags); 709 1.161 riastrad if (error) 710 1.161 riastrad return error; 711 1.82 kent 712 1.82 kent /* sysctl */ 713 1.82 kent sysctl_teardown(&sc->sc_log); 714 1.82 kent 715 1.139 jmcneill mutex_enter(&sc->sc_lock); 716 1.139 jmcneill 717 1.82 kent /* ac97 */ 718 1.82 kent if (sc->codec_if != NULL) 719 1.82 kent sc->codec_if->vtbl->detach(sc->codec_if); 720 1.82 kent 721 1.139 jmcneill mutex_exit(&sc->sc_lock); 722 1.139 jmcneill mutex_destroy(&sc->sc_lock); 723 1.139 jmcneill mutex_destroy(&sc->sc_intr_lock); 724 1.139 jmcneill 725 1.82 kent /* PCI */ 726 1.82 kent if (sc->sc_ih != NULL) 727 1.82 kent pci_intr_disestablish(sc->sc_pc, sc->sc_ih); 728 1.82 kent if (sc->mix_size != 0) 729 1.82 kent bus_space_unmap(sc->iot, sc->mix_ioh, sc->mix_size); 730 1.82 kent if (sc->aud_size != 0) 731 1.82 kent bus_space_unmap(sc->iot, sc->aud_ioh, sc->aud_size); 732 1.64 kent return 0; 733 1.64 kent } 734 1.64 kent 735 1.64 kent static int 736 1.64 kent auich_sysctl_verify(SYSCTLFN_ARGS) 737 1.64 kent { 738 1.64 kent int error, tmp; 739 1.64 kent struct sysctlnode node; 740 1.64 kent struct auich_softc *sc; 741 1.64 kent 742 1.64 kent node = *rnode; 743 1.64 kent sc = rnode->sysctl_data; 744 1.91 jmcneill if (node.sysctl_num == sc->sc_ac97_clock_mib) { 745 1.91 jmcneill tmp = sc->sc_ac97_clock; 746 1.91 jmcneill node.sysctl_data = &tmp; 747 1.91 jmcneill error = sysctl_lookup(SYSCTLFN_CALL(&node)); 748 1.91 jmcneill if (error || newp == NULL) 749 1.91 jmcneill return error; 750 1.64 kent 751 1.64 kent if (tmp < 48000 || tmp > 96000) 752 1.64 kent return EINVAL; 753 1.139 jmcneill mutex_enter(&sc->sc_lock); 754 1.64 kent sc->sc_ac97_clock = tmp; 755 1.139 jmcneill mutex_exit(&sc->sc_lock); 756 1.64 kent } 757 1.64 kent 758 1.64 kent return 0; 759 1.42 mycroft } 760 1.42 mycroft 761 1.81 kent static void 762 1.127 xtraeme auich_finish_attach(device_t self) 763 1.42 mycroft { 764 1.127 xtraeme struct auich_softc *sc = device_private(self); 765 1.42 mycroft 766 1.139 jmcneill mutex_enter(&sc->sc_lock); 767 1.75 kent if (!AC97_IS_FIXED_RATE(sc->codec_if)) 768 1.42 mycroft auich_calibrate(sc); 769 1.139 jmcneill mutex_exit(&sc->sc_lock); 770 1.42 mycroft 771 1.127 xtraeme sc->sc_audiodev = audio_attach_mi(&auich_hw_if, sc, sc->sc_dev); 772 1.102 jmcneill 773 1.102 jmcneill return; 774 1.1 thorpej } 775 1.1 thorpej 776 1.15 kent #define ICH_CODECIO_INTERVAL 10 777 1.81 kent static int 778 1.85 kent auich_read_codec(void *v, uint8_t reg, uint16_t *val) 779 1.1 thorpej { 780 1.85 kent struct auich_softc *sc; 781 1.1 thorpej int i; 782 1.15 kent uint32_t status; 783 1.1 thorpej 784 1.85 kent sc = v; 785 1.1 thorpej /* wait for an access semaphore */ 786 1.15 kent for (i = ICH_SEMATIMO / ICH_CODECIO_INTERVAL; i-- && 787 1.91 jmcneill bus_space_read_1(sc->iot, sc->aud_ioh, 788 1.91 jmcneill ICH_CAS + sc->sc_modem_offset) & 1; 789 1.15 kent DELAY(ICH_CODECIO_INTERVAL)); 790 1.1 thorpej 791 1.148 christos /* 792 1.148 christos * Be permissive in first attempt. If previous instances of 793 1.148 christos * this routine were interrupted precisely at this point (after 794 1.148 christos * access is granted by CAS but before a command is sent), 795 1.148 christos * they could have left hardware in an inconsistent state where 796 1.148 christos * a command is expected and therefore semaphore wait would hit 797 1.148 christos * the timeout. 798 1.148 christos */ 799 1.148 christos if (!sc->sc_cas_been_used && i <= 0) 800 1.148 christos i = 1; 801 1.148 christos sc->sc_cas_been_used = 1; 802 1.148 christos 803 1.1 thorpej if (i > 0) { 804 1.94 jmcneill *val = bus_space_read_2(sc->iot, sc->mix_ioh, 805 1.94 jmcneill reg + (sc->sc_codecnum * ICH_CODEC_OFFSET)); 806 1.1 thorpej DPRINTF(ICH_DEBUG_CODECIO, 807 1.146 christos (sc->sc_dev, "%s(%x, %x)\n", __func__, reg, *val)); 808 1.91 jmcneill status = bus_space_read_4(sc->iot, sc->aud_ioh, 809 1.91 jmcneill ICH_GSTS + sc->sc_modem_offset); 810 1.15 kent if (status & ICH_RCS) { 811 1.91 jmcneill bus_space_write_4(sc->iot, sc->aud_ioh, 812 1.91 jmcneill ICH_GSTS + sc->sc_modem_offset, 813 1.15 kent status & ~(ICH_SRI|ICH_PRI|ICH_GSCI)); 814 1.15 kent *val = 0xffff; 815 1.77 cube DPRINTF(ICH_DEBUG_CODECIO, 816 1.146 christos (sc->sc_dev, "%s: read_codec error\n", __func__)); 817 1.95 jmcneill if (reg == AC97_REG_GPIO_STATUS) 818 1.95 jmcneill auich_clear_cas(sc); 819 1.77 cube return -1; 820 1.15 kent } 821 1.95 jmcneill if (reg == AC97_REG_GPIO_STATUS) 822 1.95 jmcneill auich_clear_cas(sc); 823 1.1 thorpej return 0; 824 1.1 thorpej } else { 825 1.127 xtraeme aprint_normal_dev(sc->sc_dev, "read_codec timeout\n"); 826 1.95 jmcneill if (reg == AC97_REG_GPIO_STATUS) 827 1.95 jmcneill auich_clear_cas(sc); 828 1.1 thorpej return -1; 829 1.1 thorpej } 830 1.1 thorpej } 831 1.1 thorpej 832 1.81 kent static int 833 1.85 kent auich_write_codec(void *v, uint8_t reg, uint16_t val) 834 1.1 thorpej { 835 1.85 kent struct auich_softc *sc; 836 1.1 thorpej int i; 837 1.1 thorpej 838 1.85 kent sc = v; 839 1.146 christos DPRINTF(ICH_DEBUG_CODECIO, (sc->sc_dev, "%s(%x, %x)\n", 840 1.146 christos __func__, reg, val)); 841 1.1 thorpej /* wait for an access semaphore */ 842 1.15 kent for (i = ICH_SEMATIMO / ICH_CODECIO_INTERVAL; i-- && 843 1.91 jmcneill bus_space_read_1(sc->iot, sc->aud_ioh, 844 1.91 jmcneill ICH_CAS + sc->sc_modem_offset) & 1; 845 1.15 kent DELAY(ICH_CODECIO_INTERVAL)); 846 1.1 thorpej 847 1.148 christos /* Be permissive in first attempt (see comments in auich_read_codec) */ 848 1.148 christos if (!sc->sc_cas_been_used && i <= 0) 849 1.148 christos i = 1; 850 1.148 christos sc->sc_cas_been_used = 1; 851 1.148 christos 852 1.1 thorpej if (i > 0) { 853 1.94 jmcneill bus_space_write_2(sc->iot, sc->mix_ioh, 854 1.94 jmcneill reg + (sc->sc_codecnum * ICH_CODEC_OFFSET), val); 855 1.1 thorpej return 0; 856 1.1 thorpej } else { 857 1.127 xtraeme aprint_normal_dev(sc->sc_dev, "write_codec timeout\n"); 858 1.1 thorpej return -1; 859 1.1 thorpej } 860 1.1 thorpej } 861 1.1 thorpej 862 1.81 kent static int 863 1.1 thorpej auich_attach_codec(void *v, struct ac97_codec_if *cif) 864 1.1 thorpej { 865 1.85 kent struct auich_softc *sc; 866 1.1 thorpej 867 1.85 kent sc = v; 868 1.1 thorpej sc->codec_if = cif; 869 1.91 jmcneill 870 1.1 thorpej return 0; 871 1.1 thorpej } 872 1.1 thorpej 873 1.81 kent static int 874 1.1 thorpej auich_reset_codec(void *v) 875 1.1 thorpej { 876 1.85 kent struct auich_softc *sc; 877 1.15 kent int i; 878 1.47 kent uint32_t control, status; 879 1.1 thorpej 880 1.85 kent sc = v; 881 1.91 jmcneill control = bus_space_read_4(sc->iot, sc->aud_ioh, 882 1.91 jmcneill ICH_GCTRL + sc->sc_modem_offset); 883 1.95 jmcneill if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) { 884 1.130 sborrill control &= ~(ICH_ACLSO | sc->sc_pcm246_mask); 885 1.95 jmcneill } else { 886 1.92 jmcneill control &= ~ICH_ACLSO; 887 1.95 jmcneill control |= ICH_GIE; 888 1.95 jmcneill } 889 1.18 kent control |= (control & ICH_CRESET) ? ICH_WRESET : ICH_CRESET; 890 1.91 jmcneill bus_space_write_4(sc->iot, sc->aud_ioh, 891 1.91 jmcneill ICH_GCTRL + sc->sc_modem_offset, control); 892 1.15 kent 893 1.47 kent for (i = 500000; i >= 0; i--) { 894 1.91 jmcneill status = bus_space_read_4(sc->iot, sc->aud_ioh, 895 1.91 jmcneill ICH_GSTS + sc->sc_modem_offset); 896 1.49 kent if (status & (ICH_PCR | ICH_SCR | ICH_S2CR)) 897 1.47 kent break; 898 1.47 kent DELAY(1); 899 1.47 kent } 900 1.47 kent if (i <= 0) { 901 1.127 xtraeme aprint_error_dev(sc->sc_dev, "auich_reset_codec: time out\n"); 902 1.62 kent return ETIMEDOUT; 903 1.62 kent } 904 1.104 rpaulo #ifdef AUICH_DEBUG 905 1.62 kent if (status & ICH_SCR) 906 1.146 christos aprint_normal_dev(sc->sc_dev, "The 2nd codec is ready.\n"); 907 1.62 kent if (status & ICH_S2CR) 908 1.146 christos aprint_normal_dev(sc->sc_dev, "The 3rd codec is ready.\n"); 909 1.57 soren #endif 910 1.62 kent return 0; 911 1.1 thorpej } 912 1.1 thorpej 913 1.105 christos static enum ac97_host_flags 914 1.105 christos auich_flags_codec(void *v) 915 1.105 christos { 916 1.105 christos struct auich_softc *sc = v; 917 1.105 christos return sc->sc_codecflags; 918 1.105 christos } 919 1.105 christos 920 1.109 kent static void 921 1.116 thorpej auich_spdif_event(void *addr, bool flag) 922 1.109 kent { 923 1.109 kent struct auich_softc *sc; 924 1.109 kent 925 1.109 kent sc = addr; 926 1.109 kent sc->sc_spdif = flag; 927 1.109 kent } 928 1.109 kent 929 1.109 kent static int 930 1.115 christos auich_open(void *addr, int flags) 931 1.109 kent { 932 1.109 kent struct auich_softc *sc; 933 1.109 kent 934 1.109 kent sc = (struct auich_softc *)addr; 935 1.109 kent sc->codec_if->vtbl->lock(sc->codec_if); 936 1.109 kent return 0; 937 1.109 kent } 938 1.109 kent 939 1.109 kent static void 940 1.109 kent auich_close(void *addr) 941 1.109 kent { 942 1.109 kent struct auich_softc *sc; 943 1.109 kent 944 1.109 kent sc = (struct auich_softc *)addr; 945 1.109 kent sc->codec_if->vtbl->unlock(sc->codec_if); 946 1.109 kent } 947 1.109 kent 948 1.81 kent static int 949 1.155 isaki auich_query_format(void *v, struct audio_format_query *afp) 950 1.1 thorpej { 951 1.80 kent struct auich_softc *sc; 952 1.6 enami 953 1.80 kent sc = (struct auich_softc *)v; 954 1.155 isaki if (sc->sc_spdif) { 955 1.155 isaki return audio_query_format(auich_spdif_formats, 956 1.155 isaki AUICH_SPDIF_NFORMATS, afp); 957 1.155 isaki } else { 958 1.156 christos return audio_query_format(sc->sc_audio_formats, 959 1.155 isaki AUICH_AUDIO_NFORMATS, afp); 960 1.155 isaki } 961 1.1 thorpej } 962 1.1 thorpej 963 1.81 kent static int 964 1.31 kent auich_set_rate(struct auich_softc *sc, int mode, u_long srate) 965 1.17 augustss { 966 1.41 kent int ret; 967 1.84 kent u_int ratetmp; 968 1.18 kent 969 1.64 kent sc->codec_if->vtbl->set_clock(sc->codec_if, sc->sc_ac97_clock); 970 1.31 kent ratetmp = srate; 971 1.41 kent if (mode == AUMODE_RECORD) 972 1.41 kent return sc->codec_if->vtbl->set_rate(sc->codec_if, 973 1.41 kent AC97_REG_PCM_LR_ADC_RATE, &ratetmp); 974 1.41 kent ret = sc->codec_if->vtbl->set_rate(sc->codec_if, 975 1.41 kent AC97_REG_PCM_FRONT_DAC_RATE, &ratetmp); 976 1.41 kent if (ret) 977 1.41 kent return ret; 978 1.41 kent ratetmp = srate; 979 1.41 kent ret = sc->codec_if->vtbl->set_rate(sc->codec_if, 980 1.41 kent AC97_REG_PCM_SURR_DAC_RATE, &ratetmp); 981 1.41 kent if (ret) 982 1.41 kent return ret; 983 1.41 kent ratetmp = srate; 984 1.41 kent ret = sc->codec_if->vtbl->set_rate(sc->codec_if, 985 1.41 kent AC97_REG_PCM_LFE_DAC_RATE, &ratetmp); 986 1.41 kent return ret; 987 1.17 augustss } 988 1.17 augustss 989 1.81 kent static int 990 1.155 isaki auich_set_format(void *v, int setmode, 991 1.155 isaki const audio_params_t *play, const audio_params_t *rec, 992 1.155 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 993 1.1 thorpej { 994 1.85 kent struct auich_softc *sc; 995 1.155 isaki const audio_params_t *p; 996 1.80 kent int mode, index; 997 1.84 kent uint32_t control; 998 1.1 thorpej 999 1.85 kent sc = v; 1000 1.1 thorpej for (mode = AUMODE_RECORD; mode != -1; 1001 1.1 thorpej mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 1002 1.1 thorpej if ((setmode & mode) == 0) 1003 1.1 thorpej continue; 1004 1.1 thorpej 1005 1.1 thorpej p = mode == AUMODE_PLAY ? play : rec; 1006 1.1 thorpej 1007 1.94 jmcneill if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) { 1008 1.123 kent if (!sc->sc_spdif) 1009 1.155 isaki index = audio_indexof_format( 1010 1.155 isaki sc->sc_audio_formats, AUICH_AUDIO_NFORMATS, 1011 1.155 isaki mode, p); 1012 1.109 kent else 1013 1.155 isaki index = audio_indexof_format( 1014 1.155 isaki auich_spdif_formats, AUICH_SPDIF_NFORMATS, 1015 1.155 isaki mode, p); 1016 1.91 jmcneill } else { 1017 1.155 isaki index = audio_indexof_format(sc->sc_modem_formats, 1018 1.155 isaki AUICH_MODEM_NFORMATS, mode, p); 1019 1.91 jmcneill } 1020 1.155 isaki 1021 1.84 kent /* p represents HW encoding */ 1022 1.94 jmcneill if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) { 1023 1.91 jmcneill if (sc->sc_audio_formats[index].frequency_type != 1 1024 1.91 jmcneill && auich_set_rate(sc, mode, p->sample_rate)) 1025 1.91 jmcneill return EINVAL; 1026 1.91 jmcneill } else { 1027 1.91 jmcneill if (sc->sc_modem_formats[index].frequency_type != 1 1028 1.91 jmcneill && auich_set_rate(sc, mode, p->sample_rate)) 1029 1.91 jmcneill return EINVAL; 1030 1.92 jmcneill auich_write_codec(sc, AC97_REG_LINE1_RATE, 1031 1.92 jmcneill p->sample_rate); 1032 1.92 jmcneill auich_write_codec(sc, AC97_REG_LINE1_LEVEL, 0); 1033 1.91 jmcneill } 1034 1.94 jmcneill if (mode == AUMODE_PLAY && 1035 1.94 jmcneill sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) { 1036 1.91 jmcneill control = bus_space_read_4(sc->iot, sc->aud_ioh, 1037 1.91 jmcneill ICH_GCTRL + sc->sc_modem_offset); 1038 1.154 isaki control &= ~sc->sc_pcm246_mask; 1039 1.84 kent if (p->channels == 4) { 1040 1.130 sborrill control |= sc->sc_pcm4; 1041 1.84 kent } else if (p->channels == 6) { 1042 1.130 sborrill control |= sc->sc_pcm6; 1043 1.41 kent } 1044 1.91 jmcneill bus_space_write_4(sc->iot, sc->aud_ioh, 1045 1.91 jmcneill ICH_GCTRL + sc->sc_modem_offset, control); 1046 1.18 kent } 1047 1.1 thorpej } 1048 1.1 thorpej 1049 1.85 kent return 0; 1050 1.1 thorpej } 1051 1.1 thorpej 1052 1.90 mycroft static void 1053 1.90 mycroft auich_halt_pipe(struct auich_softc *sc, int pipe) 1054 1.90 mycroft { 1055 1.90 mycroft int i; 1056 1.90 mycroft uint32_t status; 1057 1.90 mycroft 1058 1.90 mycroft bus_space_write_1(sc->iot, sc->aud_ioh, pipe + ICH_CTRL, 0); 1059 1.90 mycroft for (i = 0; i < 100; i++) { 1060 1.90 mycroft status = bus_space_read_4(sc->iot, sc->aud_ioh, pipe + ICH_STS); 1061 1.90 mycroft if (status & ICH_DCH) 1062 1.90 mycroft break; 1063 1.90 mycroft DELAY(1); 1064 1.90 mycroft } 1065 1.90 mycroft bus_space_write_1(sc->iot, sc->aud_ioh, pipe + ICH_CTRL, ICH_RR); 1066 1.90 mycroft 1067 1.99 rpaulo #if AUICH_DEBUG 1068 1.90 mycroft if (i > 0) 1069 1.146 christos aprint_normal_dev(sc->sc_dev, "%s: halt took %d cycles\n", 1070 1.146 christos __func__, i); 1071 1.90 mycroft #endif 1072 1.90 mycroft } 1073 1.90 mycroft 1074 1.81 kent static int 1075 1.1 thorpej auich_halt_output(void *v) 1076 1.1 thorpej { 1077 1.85 kent struct auich_softc *sc; 1078 1.1 thorpej 1079 1.85 kent sc = v; 1080 1.146 christos DPRINTF(ICH_DEBUG_DMA, (sc->sc_dev, "%s\n", __func__)); 1081 1.1 thorpej 1082 1.90 mycroft auich_halt_pipe(sc, ICH_PCMO); 1083 1.73 mycroft sc->pcmo.intr = NULL; 1084 1.1 thorpej 1085 1.85 kent return 0; 1086 1.1 thorpej } 1087 1.1 thorpej 1088 1.81 kent static int 1089 1.1 thorpej auich_halt_input(void *v) 1090 1.1 thorpej { 1091 1.85 kent struct auich_softc *sc; 1092 1.1 thorpej 1093 1.85 kent sc = v; 1094 1.146 christos DPRINTF(ICH_DEBUG_DMA, (sc->sc_dev, "%s\n", __func__)); 1095 1.1 thorpej 1096 1.90 mycroft auich_halt_pipe(sc, ICH_PCMI); 1097 1.73 mycroft sc->pcmi.intr = NULL; 1098 1.1 thorpej 1099 1.85 kent return 0; 1100 1.1 thorpej } 1101 1.1 thorpej 1102 1.81 kent static int 1103 1.1 thorpej auich_getdev(void *v, struct audio_device *adp) 1104 1.1 thorpej { 1105 1.85 kent struct auich_softc *sc; 1106 1.1 thorpej 1107 1.85 kent sc = v; 1108 1.1 thorpej *adp = sc->sc_audev; 1109 1.85 kent return 0; 1110 1.1 thorpej } 1111 1.1 thorpej 1112 1.81 kent static int 1113 1.1 thorpej auich_set_port(void *v, mixer_ctrl_t *cp) 1114 1.1 thorpej { 1115 1.85 kent struct auich_softc *sc; 1116 1.1 thorpej 1117 1.85 kent sc = v; 1118 1.85 kent return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp); 1119 1.1 thorpej } 1120 1.1 thorpej 1121 1.81 kent static int 1122 1.1 thorpej auich_get_port(void *v, mixer_ctrl_t *cp) 1123 1.1 thorpej { 1124 1.85 kent struct auich_softc *sc; 1125 1.1 thorpej 1126 1.85 kent sc = v; 1127 1.85 kent return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp); 1128 1.1 thorpej } 1129 1.1 thorpej 1130 1.81 kent static int 1131 1.1 thorpej auich_query_devinfo(void *v, mixer_devinfo_t *dp) 1132 1.1 thorpej { 1133 1.85 kent struct auich_softc *sc; 1134 1.1 thorpej 1135 1.85 kent sc = v; 1136 1.85 kent return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp); 1137 1.1 thorpej } 1138 1.1 thorpej 1139 1.81 kent static void * 1140 1.139 jmcneill auich_allocm(void *v, int direction, size_t size) 1141 1.1 thorpej { 1142 1.85 kent struct auich_softc *sc; 1143 1.1 thorpej struct auich_dma *p; 1144 1.1 thorpej int error; 1145 1.1 thorpej 1146 1.1 thorpej if (size > (ICH_DMALIST_MAX * ICH_DMASEG_MAX)) 1147 1.85 kent return NULL; 1148 1.1 thorpej 1149 1.139 jmcneill p = kmem_alloc(sizeof(*p), KM_SLEEP); 1150 1.1 thorpej 1151 1.85 kent sc = v; 1152 1.1 thorpej error = auich_allocmem(sc, size, 0, p); 1153 1.1 thorpej if (error) { 1154 1.139 jmcneill kmem_free(p, sizeof(*p)); 1155 1.85 kent return NULL; 1156 1.1 thorpej } 1157 1.1 thorpej 1158 1.1 thorpej p->next = sc->sc_dmas; 1159 1.1 thorpej sc->sc_dmas = p; 1160 1.1 thorpej 1161 1.85 kent return KERNADDR(p); 1162 1.1 thorpej } 1163 1.1 thorpej 1164 1.81 kent static void 1165 1.139 jmcneill auich_freem(void *v, void *ptr, size_t size) 1166 1.1 thorpej { 1167 1.85 kent struct auich_softc *sc; 1168 1.1 thorpej struct auich_dma *p, **pp; 1169 1.1 thorpej 1170 1.85 kent sc = v; 1171 1.1 thorpej for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) { 1172 1.1 thorpej if (KERNADDR(p) == ptr) { 1173 1.1 thorpej auich_freemem(sc, p); 1174 1.1 thorpej *pp = p->next; 1175 1.139 jmcneill kmem_free(p, sizeof(*p)); 1176 1.1 thorpej return; 1177 1.1 thorpej } 1178 1.1 thorpej } 1179 1.1 thorpej } 1180 1.1 thorpej 1181 1.81 kent static size_t 1182 1.115 christos auich_round_buffersize(void *v, int direction, size_t size) 1183 1.1 thorpej { 1184 1.1 thorpej 1185 1.1 thorpej if (size > (ICH_DMALIST_MAX * ICH_DMASEG_MAX)) 1186 1.1 thorpej size = ICH_DMALIST_MAX * ICH_DMASEG_MAX; 1187 1.1 thorpej 1188 1.1 thorpej return size; 1189 1.1 thorpej } 1190 1.1 thorpej 1191 1.81 kent static int 1192 1.1 thorpej auich_get_props(void *v) 1193 1.1 thorpej { 1194 1.1 thorpej 1195 1.157 isaki return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE | 1196 1.157 isaki AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1197 1.1 thorpej } 1198 1.1 thorpej 1199 1.81 kent static int 1200 1.1 thorpej auich_intr(void *v) 1201 1.1 thorpej { 1202 1.85 kent struct auich_softc *sc; 1203 1.85 kent int ret, gsts; 1204 1.33 kent #ifdef DIAGNOSTIC 1205 1.33 kent int csts; 1206 1.33 kent #endif 1207 1.33 kent 1208 1.85 kent sc = v; 1209 1.120 jmcneill 1210 1.127 xtraeme if (!device_has_power(sc->sc_dev)) 1211 1.120 jmcneill return (0); 1212 1.120 jmcneill 1213 1.139 jmcneill mutex_spin_enter(&sc->sc_intr_lock); 1214 1.139 jmcneill 1215 1.85 kent ret = 0; 1216 1.33 kent #ifdef DIAGNOSTIC 1217 1.33 kent csts = pci_conf_read(sc->sc_pc, sc->sc_pt, PCI_COMMAND_STATUS_REG); 1218 1.33 kent if (csts & PCI_STATUS_MASTER_ABORT) { 1219 1.146 christos aprint_error_dev(sc->sc_dev, "%s: PCI master abort\n", 1220 1.146 christos __func__); 1221 1.33 kent } 1222 1.33 kent #endif 1223 1.33 kent 1224 1.91 jmcneill gsts = bus_space_read_4(sc->iot, sc->aud_ioh, 1225 1.91 jmcneill ICH_GSTS + sc->sc_modem_offset); 1226 1.146 christos DPRINTF(ICH_DEBUG_INTR, (sc->sc_dev, "%s: gsts=0x%x\n", 1227 1.146 christos __func__, gsts)); 1228 1.1 thorpej 1229 1.94 jmcneill if ((sc->sc_codectype == AC97_CODEC_TYPE_AUDIO && gsts & ICH_POINT) || 1230 1.94 jmcneill (sc->sc_codectype == AC97_CODEC_TYPE_MODEM && gsts & ICH_MOINT)) { 1231 1.73 mycroft int sts; 1232 1.73 mycroft 1233 1.61 soren sts = bus_space_read_2(sc->iot, sc->aud_ioh, 1234 1.61 soren ICH_PCMO + sc->sc_sts_reg); 1235 1.146 christos DPRINTF(ICH_DEBUG_INTR, 1236 1.146 christos (sc->sc_dev, "%s: osts=0x%x\n", __func__, sts)); 1237 1.1 thorpej 1238 1.73 mycroft if (sts & ICH_FIFOE) 1239 1.146 christos aprint_error_dev(sc->sc_dev, "%s: fifo underrun\n", 1240 1.146 christos __func__); 1241 1.1 thorpej 1242 1.90 mycroft if (sts & ICH_BCIS) 1243 1.90 mycroft auich_intr_pipe(sc, ICH_PCMO, &sc->pcmo); 1244 1.1 thorpej 1245 1.1 thorpej /* int ack */ 1246 1.61 soren bus_space_write_2(sc->iot, sc->aud_ioh, ICH_PCMO + 1247 1.73 mycroft sc->sc_sts_reg, sts & (ICH_BCIS | ICH_FIFOE)); 1248 1.94 jmcneill if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) 1249 1.91 jmcneill bus_space_write_4(sc->iot, sc->aud_ioh, 1250 1.91 jmcneill ICH_GSTS + sc->sc_modem_offset, ICH_POINT); 1251 1.91 jmcneill else 1252 1.91 jmcneill bus_space_write_4(sc->iot, sc->aud_ioh, 1253 1.91 jmcneill ICH_GSTS + sc->sc_modem_offset, ICH_MOINT); 1254 1.1 thorpej ret++; 1255 1.1 thorpej } 1256 1.1 thorpej 1257 1.94 jmcneill if ((sc->sc_codectype == AC97_CODEC_TYPE_AUDIO && gsts & ICH_PIINT) || 1258 1.94 jmcneill (sc->sc_codectype == AC97_CODEC_TYPE_MODEM && gsts & ICH_MIINT)) { 1259 1.73 mycroft int sts; 1260 1.73 mycroft 1261 1.61 soren sts = bus_space_read_2(sc->iot, sc->aud_ioh, 1262 1.61 soren ICH_PCMI + sc->sc_sts_reg); 1263 1.61 soren DPRINTF(ICH_DEBUG_INTR, 1264 1.146 christos (sc->sc_dev, "%s: ists=0x%x\n", __func__, sts)); 1265 1.1 thorpej 1266 1.73 mycroft if (sts & ICH_FIFOE) 1267 1.146 christos aprint_error_dev(sc->sc_dev, "%s: fifo overrun\n", 1268 1.146 christos __func__); 1269 1.1 thorpej 1270 1.90 mycroft if (sts & ICH_BCIS) 1271 1.90 mycroft auich_intr_pipe(sc, ICH_PCMI, &sc->pcmi); 1272 1.1 thorpej 1273 1.1 thorpej /* int ack */ 1274 1.61 soren bus_space_write_2(sc->iot, sc->aud_ioh, ICH_PCMI + 1275 1.73 mycroft sc->sc_sts_reg, sts & (ICH_BCIS | ICH_FIFOE)); 1276 1.94 jmcneill if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO) 1277 1.91 jmcneill bus_space_write_4(sc->iot, sc->aud_ioh, 1278 1.91 jmcneill ICH_GSTS + sc->sc_modem_offset, ICH_PIINT); 1279 1.91 jmcneill else 1280 1.91 jmcneill bus_space_write_4(sc->iot, sc->aud_ioh, 1281 1.91 jmcneill ICH_GSTS + sc->sc_modem_offset, ICH_MIINT); 1282 1.1 thorpej ret++; 1283 1.1 thorpej } 1284 1.1 thorpej 1285 1.94 jmcneill if (sc->sc_codectype == AC97_CODEC_TYPE_AUDIO && gsts & ICH_MINT) { 1286 1.73 mycroft int sts; 1287 1.73 mycroft 1288 1.61 soren sts = bus_space_read_2(sc->iot, sc->aud_ioh, 1289 1.61 soren ICH_MICI + sc->sc_sts_reg); 1290 1.61 soren DPRINTF(ICH_DEBUG_INTR, 1291 1.146 christos (sc->sc_dev, "%s: ists=0x%x\n", __func__, sts)); 1292 1.73 mycroft 1293 1.1 thorpej if (sts & ICH_FIFOE) 1294 1.146 christos aprint_error_dev(sc->sc_dev, "%s: fifo overrun\n", 1295 1.146 christos __func__); 1296 1.1 thorpej 1297 1.90 mycroft if (sts & ICH_BCIS) 1298 1.90 mycroft auich_intr_pipe(sc, ICH_MICI, &sc->mici); 1299 1.1 thorpej 1300 1.90 mycroft /* int ack */ 1301 1.90 mycroft bus_space_write_2(sc->iot, sc->aud_ioh, ICH_MICI + 1302 1.90 mycroft sc->sc_sts_reg, sts & (ICH_BCIS | ICH_FIFOE)); 1303 1.91 jmcneill bus_space_write_4(sc->iot, sc->aud_ioh, 1304 1.91 jmcneill ICH_GSTS + sc->sc_modem_offset, ICH_MINT); 1305 1.90 mycroft ret++; 1306 1.1 thorpej } 1307 1.1 thorpej 1308 1.95 jmcneill #ifdef AUICH_MODEM_DEBUG 1309 1.95 jmcneill if (sc->sc_codectype == AC97_CODEC_TYPE_MODEM && gsts & ICH_GSCI) { 1310 1.146 christos aprint_normal_dev(sc->sc_dev, "gsts=0x%x\n", gsts); 1311 1.95 jmcneill /* int ack */ 1312 1.95 jmcneill bus_space_write_4(sc->iot, sc->aud_ioh, 1313 1.95 jmcneill ICH_GSTS + sc->sc_modem_offset, ICH_GSCI); 1314 1.95 jmcneill ret++; 1315 1.95 jmcneill } 1316 1.95 jmcneill #endif 1317 1.95 jmcneill 1318 1.139 jmcneill mutex_spin_exit(&sc->sc_intr_lock); 1319 1.139 jmcneill 1320 1.1 thorpej return ret; 1321 1.1 thorpej } 1322 1.1 thorpej 1323 1.90 mycroft static void 1324 1.90 mycroft auich_trigger_pipe(struct auich_softc *sc, int pipe, struct auich_ring *ring) 1325 1.90 mycroft { 1326 1.90 mycroft int blksize, qptr; 1327 1.90 mycroft struct auich_dmalist *q; 1328 1.90 mycroft 1329 1.90 mycroft blksize = ring->blksize; 1330 1.90 mycroft 1331 1.90 mycroft for (qptr = 0; qptr < ICH_DMALIST_MAX; qptr++) { 1332 1.90 mycroft q = &ring->dmalist[qptr]; 1333 1.90 mycroft q->base = ring->p; 1334 1.90 mycroft q->len = (blksize >> sc->sc_sample_shift) | ICH_DMAF_IOC; 1335 1.90 mycroft 1336 1.90 mycroft ring->p += blksize; 1337 1.90 mycroft if (ring->p >= ring->end) 1338 1.90 mycroft ring->p = ring->start; 1339 1.90 mycroft } 1340 1.90 mycroft ring->qptr = 0; 1341 1.90 mycroft 1342 1.90 mycroft bus_space_write_1(sc->iot, sc->aud_ioh, pipe + ICH_LVI, 1343 1.90 mycroft (qptr - 1) & ICH_LVI_MASK); 1344 1.90 mycroft bus_space_write_1(sc->iot, sc->aud_ioh, pipe + ICH_CTRL, 1345 1.90 mycroft ICH_IOCE | ICH_FEIE | ICH_RPBM); 1346 1.90 mycroft } 1347 1.90 mycroft 1348 1.90 mycroft static void 1349 1.90 mycroft auich_intr_pipe(struct auich_softc *sc, int pipe, struct auich_ring *ring) 1350 1.90 mycroft { 1351 1.90 mycroft int blksize, qptr, nqptr; 1352 1.90 mycroft struct auich_dmalist *q; 1353 1.90 mycroft 1354 1.90 mycroft blksize = ring->blksize; 1355 1.90 mycroft qptr = ring->qptr; 1356 1.90 mycroft nqptr = bus_space_read_1(sc->iot, sc->aud_ioh, pipe + ICH_CIV); 1357 1.90 mycroft 1358 1.90 mycroft while (qptr != nqptr) { 1359 1.90 mycroft q = &ring->dmalist[qptr]; 1360 1.90 mycroft q->base = ring->p; 1361 1.90 mycroft q->len = (blksize >> sc->sc_sample_shift) | ICH_DMAF_IOC; 1362 1.90 mycroft 1363 1.90 mycroft DPRINTF(ICH_DEBUG_INTR, 1364 1.146 christos (sc->sc_dev, "%s: %p, %p = %x @ 0x%x\n", __func__, 1365 1.90 mycroft &ring->dmalist[qptr], q, q->len, q->base)); 1366 1.90 mycroft 1367 1.90 mycroft ring->p += blksize; 1368 1.90 mycroft if (ring->p >= ring->end) 1369 1.90 mycroft ring->p = ring->start; 1370 1.90 mycroft 1371 1.90 mycroft qptr = (qptr + 1) & ICH_LVI_MASK; 1372 1.90 mycroft if (ring->intr) 1373 1.90 mycroft ring->intr(ring->arg); 1374 1.90 mycroft } 1375 1.90 mycroft ring->qptr = qptr; 1376 1.90 mycroft 1377 1.90 mycroft bus_space_write_1(sc->iot, sc->aud_ioh, pipe + ICH_LVI, 1378 1.90 mycroft (qptr - 1) & ICH_LVI_MASK); 1379 1.90 mycroft } 1380 1.90 mycroft 1381 1.81 kent static int 1382 1.1 thorpej auich_trigger_output(void *v, void *start, void *end, int blksize, 1383 1.115 christos void (*intr)(void *), void *arg, const audio_params_t *param) 1384 1.1 thorpej { 1385 1.85 kent struct auich_softc *sc; 1386 1.1 thorpej struct auich_dma *p; 1387 1.1 thorpej size_t size; 1388 1.1 thorpej 1389 1.146 christos sc = v; 1390 1.1 thorpej DPRINTF(ICH_DEBUG_DMA, 1391 1.146 christos (sc->sc_dev, "%s(%p, %p, %d, %p, %p, %p)\n", __func__, 1392 1.1 thorpej start, end, blksize, intr, arg, param)); 1393 1.1 thorpej 1394 1.1 thorpej for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) 1395 1.85 kent continue; 1396 1.1 thorpej if (!p) { 1397 1.146 christos aprint_error_dev(sc->sc_dev, "%s: bad addr %p\n", __func__, 1398 1.146 christos start); 1399 1.85 kent return EINVAL; 1400 1.1 thorpej } 1401 1.1 thorpej 1402 1.117 christos size = (size_t)((char *)end - (char *)start); 1403 1.1 thorpej 1404 1.90 mycroft sc->pcmo.intr = intr; 1405 1.90 mycroft sc->pcmo.arg = arg; 1406 1.73 mycroft sc->pcmo.start = DMAADDR(p); 1407 1.73 mycroft sc->pcmo.p = sc->pcmo.start; 1408 1.73 mycroft sc->pcmo.end = sc->pcmo.start + size; 1409 1.73 mycroft sc->pcmo.blksize = blksize; 1410 1.1 thorpej 1411 1.1 thorpej bus_space_write_4(sc->iot, sc->aud_ioh, ICH_PCMO + ICH_BDBAR, 1412 1.1 thorpej sc->sc_cddma + ICH_PCMO_OFF(0)); 1413 1.90 mycroft auich_trigger_pipe(sc, ICH_PCMO, &sc->pcmo); 1414 1.1 thorpej 1415 1.85 kent return 0; 1416 1.1 thorpej } 1417 1.1 thorpej 1418 1.81 kent static int 1419 1.84 kent auich_trigger_input(void *v, void *start, void *end, int blksize, 1420 1.115 christos void (*intr)(void *), void *arg, const audio_params_t *param) 1421 1.1 thorpej { 1422 1.85 kent struct auich_softc *sc; 1423 1.1 thorpej struct auich_dma *p; 1424 1.1 thorpej size_t size; 1425 1.1 thorpej 1426 1.146 christos sc = v; 1427 1.1 thorpej DPRINTF(ICH_DEBUG_DMA, 1428 1.146 christos (sc->sc_dev, "%s(%p, %p, %d, %p, %p, %p)\n", __func__, 1429 1.1 thorpej start, end, blksize, intr, arg, param)); 1430 1.1 thorpej 1431 1.1 thorpej for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) 1432 1.85 kent continue; 1433 1.1 thorpej if (!p) { 1434 1.146 christos aprint_error_dev(sc->sc_dev, "%s: bad addr %p\n", __func__, 1435 1.146 christos start); 1436 1.85 kent return EINVAL; 1437 1.1 thorpej } 1438 1.1 thorpej 1439 1.117 christos size = (size_t)((char *)end - (char *)start); 1440 1.1 thorpej 1441 1.90 mycroft sc->pcmi.intr = intr; 1442 1.90 mycroft sc->pcmi.arg = arg; 1443 1.73 mycroft sc->pcmi.start = DMAADDR(p); 1444 1.73 mycroft sc->pcmi.p = sc->pcmi.start; 1445 1.73 mycroft sc->pcmi.end = sc->pcmi.start + size; 1446 1.73 mycroft sc->pcmi.blksize = blksize; 1447 1.1 thorpej 1448 1.1 thorpej bus_space_write_4(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_BDBAR, 1449 1.1 thorpej sc->sc_cddma + ICH_PCMI_OFF(0)); 1450 1.90 mycroft auich_trigger_pipe(sc, ICH_PCMI, &sc->pcmi); 1451 1.1 thorpej 1452 1.85 kent return 0; 1453 1.1 thorpej } 1454 1.1 thorpej 1455 1.81 kent static int 1456 1.1 thorpej auich_allocmem(struct auich_softc *sc, size_t size, size_t align, 1457 1.1 thorpej struct auich_dma *p) 1458 1.1 thorpej { 1459 1.1 thorpej int error; 1460 1.1 thorpej 1461 1.1 thorpej p->size = size; 1462 1.1 thorpej error = bus_dmamem_alloc(sc->dmat, p->size, align, 0, 1463 1.1 thorpej p->segs, sizeof(p->segs)/sizeof(p->segs[0]), 1464 1.139 jmcneill &p->nsegs, BUS_DMA_WAITOK); 1465 1.1 thorpej if (error) 1466 1.85 kent return error; 1467 1.1 thorpej 1468 1.1 thorpej error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size, 1469 1.139 jmcneill &p->addr, BUS_DMA_WAITOK|sc->sc_dmamap_flags); 1470 1.1 thorpej if (error) 1471 1.1 thorpej goto free; 1472 1.1 thorpej 1473 1.1 thorpej error = bus_dmamap_create(sc->dmat, p->size, 1, p->size, 1474 1.139 jmcneill 0, BUS_DMA_WAITOK, &p->map); 1475 1.1 thorpej if (error) 1476 1.1 thorpej goto unmap; 1477 1.1 thorpej 1478 1.1 thorpej error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, NULL, 1479 1.139 jmcneill BUS_DMA_WAITOK); 1480 1.1 thorpej if (error) 1481 1.1 thorpej goto destroy; 1482 1.85 kent return 0; 1483 1.1 thorpej 1484 1.1 thorpej destroy: 1485 1.1 thorpej bus_dmamap_destroy(sc->dmat, p->map); 1486 1.1 thorpej unmap: 1487 1.1 thorpej bus_dmamem_unmap(sc->dmat, p->addr, p->size); 1488 1.1 thorpej free: 1489 1.1 thorpej bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 1490 1.85 kent return error; 1491 1.1 thorpej } 1492 1.1 thorpej 1493 1.81 kent static int 1494 1.1 thorpej auich_freemem(struct auich_softc *sc, struct auich_dma *p) 1495 1.1 thorpej { 1496 1.1 thorpej 1497 1.1 thorpej bus_dmamap_unload(sc->dmat, p->map); 1498 1.1 thorpej bus_dmamap_destroy(sc->dmat, p->map); 1499 1.1 thorpej bus_dmamem_unmap(sc->dmat, p->addr, p->size); 1500 1.1 thorpej bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 1501 1.85 kent return 0; 1502 1.1 thorpej } 1503 1.1 thorpej 1504 1.81 kent static int 1505 1.1 thorpej auich_alloc_cdata(struct auich_softc *sc) 1506 1.1 thorpej { 1507 1.1 thorpej bus_dma_segment_t seg; 1508 1.1 thorpej int error, rseg; 1509 1.1 thorpej 1510 1.1 thorpej /* 1511 1.1 thorpej * Allocate the control data structure, and create and load the 1512 1.1 thorpej * DMA map for it. 1513 1.1 thorpej */ 1514 1.1 thorpej if ((error = bus_dmamem_alloc(sc->dmat, 1515 1.1 thorpej sizeof(struct auich_cdata), 1516 1.1 thorpej PAGE_SIZE, 0, &seg, 1, &rseg, 0)) != 0) { 1517 1.127 xtraeme aprint_error_dev(sc->sc_dev, "unable to allocate control data, error = %d\n", error); 1518 1.1 thorpej goto fail_0; 1519 1.1 thorpej } 1520 1.1 thorpej 1521 1.1 thorpej if ((error = bus_dmamem_map(sc->dmat, &seg, rseg, 1522 1.1 thorpej sizeof(struct auich_cdata), 1523 1.117 christos (void **) &sc->sc_cdata, 1524 1.34 kent sc->sc_dmamap_flags)) != 0) { 1525 1.127 xtraeme aprint_error_dev(sc->sc_dev, "unable to map control data, error = %d\n", error); 1526 1.1 thorpej goto fail_1; 1527 1.1 thorpej } 1528 1.1 thorpej 1529 1.1 thorpej if ((error = bus_dmamap_create(sc->dmat, sizeof(struct auich_cdata), 1, 1530 1.1 thorpej sizeof(struct auich_cdata), 0, 0, 1531 1.1 thorpej &sc->sc_cddmamap)) != 0) { 1532 1.127 xtraeme aprint_error_dev(sc->sc_dev, "unable to create control data DMA map, " 1533 1.125 cegger "error = %d\n", error); 1534 1.1 thorpej goto fail_2; 1535 1.1 thorpej } 1536 1.1 thorpej 1537 1.1 thorpej if ((error = bus_dmamap_load(sc->dmat, sc->sc_cddmamap, 1538 1.1 thorpej sc->sc_cdata, sizeof(struct auich_cdata), 1539 1.1 thorpej NULL, 0)) != 0) { 1540 1.127 xtraeme aprint_error_dev(sc->sc_dev, "unable tp load control data DMA map, " 1541 1.125 cegger "error = %d\n", error); 1542 1.1 thorpej goto fail_3; 1543 1.1 thorpej } 1544 1.1 thorpej 1545 1.73 mycroft sc->pcmo.dmalist = sc->sc_cdata->ic_dmalist_pcmo; 1546 1.73 mycroft sc->pcmi.dmalist = sc->sc_cdata->ic_dmalist_pcmi; 1547 1.73 mycroft sc->mici.dmalist = sc->sc_cdata->ic_dmalist_mici; 1548 1.73 mycroft 1549 1.85 kent return 0; 1550 1.1 thorpej 1551 1.1 thorpej fail_3: 1552 1.1 thorpej bus_dmamap_destroy(sc->dmat, sc->sc_cddmamap); 1553 1.1 thorpej fail_2: 1554 1.117 christos bus_dmamem_unmap(sc->dmat, (void *) sc->sc_cdata, 1555 1.1 thorpej sizeof(struct auich_cdata)); 1556 1.1 thorpej fail_1: 1557 1.1 thorpej bus_dmamem_free(sc->dmat, &seg, rseg); 1558 1.1 thorpej fail_0: 1559 1.85 kent return error; 1560 1.9 augustss } 1561 1.9 augustss 1562 1.120 jmcneill static bool 1563 1.137 dyoung auich_resume(device_t dv, const pmf_qual_t *qual) 1564 1.9 augustss { 1565 1.120 jmcneill struct auich_softc *sc = device_private(dv); 1566 1.121 jmcneill pcireg_t v; 1567 1.121 jmcneill 1568 1.139 jmcneill mutex_enter(&sc->sc_lock); 1569 1.139 jmcneill mutex_spin_enter(&sc->sc_intr_lock); 1570 1.139 jmcneill 1571 1.133 jakllsch if (sc->sc_iose) { 1572 1.122 jmcneill v = pci_conf_read(sc->sc_pc, sc->sc_pt, ICH_CFG); 1573 1.122 jmcneill pci_conf_write(sc->sc_pc, sc->sc_pt, ICH_CFG, 1574 1.121 jmcneill v | ICH_CFG_IOSE); 1575 1.121 jmcneill } 1576 1.9 augustss 1577 1.120 jmcneill auich_reset_codec(sc); 1578 1.139 jmcneill mutex_spin_exit(&sc->sc_intr_lock); 1579 1.120 jmcneill DELAY(1000); 1580 1.120 jmcneill (sc->codec_if->vtbl->restore_ports)(sc->codec_if); 1581 1.139 jmcneill mutex_exit(&sc->sc_lock); 1582 1.121 jmcneill 1583 1.120 jmcneill return true; 1584 1.18 kent } 1585 1.18 kent 1586 1.61 soren /* 1587 1.61 soren * Calibrate card (some boards are overclocked and need scaling) 1588 1.61 soren */ 1589 1.81 kent static void 1590 1.42 mycroft auich_calibrate(struct auich_softc *sc) 1591 1.18 kent { 1592 1.18 kent struct timeval t1, t2; 1593 1.53 kent uint8_t ociv, nciv; 1594 1.53 kent uint64_t wait_us; 1595 1.53 kent uint32_t actual_48k_rate, bytes, ac97rate; 1596 1.18 kent void *temp_buffer; 1597 1.18 kent struct auich_dma *p; 1598 1.84 kent u_int rate; 1599 1.18 kent 1600 1.18 kent /* 1601 1.18 kent * Grab audio from input for fixed interval and compare how 1602 1.18 kent * much we actually get with what we expect. Interval needs 1603 1.18 kent * to be sufficiently short that no interrupts are 1604 1.18 kent * generated. 1605 1.18 kent */ 1606 1.18 kent 1607 1.54 mycroft /* Force the codec to a known state first. */ 1608 1.54 mycroft sc->codec_if->vtbl->set_clock(sc->codec_if, 48000); 1609 1.76 cube rate = sc->sc_ac97_clock = 48000; 1610 1.54 mycroft sc->codec_if->vtbl->set_rate(sc->codec_if, AC97_REG_PCM_LR_ADC_RATE, 1611 1.54 mycroft &rate); 1612 1.54 mycroft 1613 1.18 kent /* Setup a buffer */ 1614 1.53 kent bytes = 64000; 1615 1.139 jmcneill temp_buffer = auich_allocm(sc, AUMODE_RECORD, bytes); 1616 1.54 mycroft 1617 1.18 kent for (p = sc->sc_dmas; p && KERNADDR(p) != temp_buffer; p = p->next) 1618 1.85 kent continue; 1619 1.18 kent if (p == NULL) { 1620 1.146 christos aprint_error_dev(sc->sc_dev, "%s: bad address %p\n", 1621 1.146 christos __func__, temp_buffer); 1622 1.29 kent return; 1623 1.18 kent } 1624 1.73 mycroft sc->pcmi.dmalist[0].base = DMAADDR(p); 1625 1.73 mycroft sc->pcmi.dmalist[0].len = (bytes >> sc->sc_sample_shift); 1626 1.18 kent 1627 1.18 kent /* 1628 1.18 kent * our data format is stereo, 16 bit so each sample is 4 bytes. 1629 1.18 kent * assuming we get 48000 samples per second, we get 192000 bytes/sec. 1630 1.18 kent * we're going to start recording with interrupts disabled and measure 1631 1.18 kent * the time taken for one block to complete. we know the block size, 1632 1.18 kent * we know the time in microseconds, we calculate the sample rate: 1633 1.18 kent * 1634 1.18 kent * actual_rate [bps] = bytes / (time [s] * 4) 1635 1.18 kent * actual_rate [bps] = (bytes * 1000000) / (time [us] * 4) 1636 1.18 kent * actual_rate [Hz] = (bytes * 250000) / time [us] 1637 1.18 kent */ 1638 1.18 kent 1639 1.18 kent /* prepare */ 1640 1.18 kent ociv = bus_space_read_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CIV); 1641 1.18 kent bus_space_write_4(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_BDBAR, 1642 1.18 kent sc->sc_cddma + ICH_PCMI_OFF(0)); 1643 1.18 kent bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_LVI, 1644 1.18 kent (0 - 1) & ICH_LVI_MASK); 1645 1.18 kent 1646 1.18 kent /* start */ 1647 1.139 jmcneill kpreempt_disable(); 1648 1.18 kent microtime(&t1); 1649 1.18 kent bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, ICH_RPBM); 1650 1.18 kent 1651 1.18 kent /* wait */ 1652 1.51 mycroft nciv = ociv; 1653 1.42 mycroft do { 1654 1.18 kent microtime(&t2); 1655 1.18 kent if (t2.tv_sec - t1.tv_sec > 1) 1656 1.18 kent break; 1657 1.18 kent nciv = bus_space_read_1(sc->iot, sc->aud_ioh, 1658 1.18 kent ICH_PCMI + ICH_CIV); 1659 1.42 mycroft } while (nciv == ociv); 1660 1.53 kent microtime(&t2); 1661 1.18 kent 1662 1.18 kent /* stop */ 1663 1.18 kent bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, 0); 1664 1.139 jmcneill kpreempt_enable(); 1665 1.18 kent 1666 1.18 kent /* reset */ 1667 1.18 kent DELAY(100); 1668 1.18 kent bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, ICH_RR); 1669 1.18 kent 1670 1.18 kent /* turn time delta into us */ 1671 1.18 kent wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) + t2.tv_usec - t1.tv_usec; 1672 1.18 kent 1673 1.139 jmcneill auich_freem(sc, temp_buffer, bytes); 1674 1.18 kent 1675 1.18 kent if (nciv == ociv) { 1676 1.146 christos aprint_error_dev(sc->sc_dev, "ac97 link rate calibration " 1677 1.146 christos "timed out after %" PRIu64 " us\n", wait_us); 1678 1.29 kent return; 1679 1.18 kent } 1680 1.18 kent 1681 1.147 christos if (wait_us == 0) { 1682 1.147 christos /* Can happen with emulated hardware */ 1683 1.147 christos aprint_error_dev(sc->sc_dev, "abnormal zero delay during " 1684 1.147 christos "calibration\n"); 1685 1.147 christos return; 1686 1.147 christos } 1687 1.147 christos 1688 1.144 tls rnd_add_data(NULL, &wait_us, sizeof(wait_us), 1); 1689 1.144 tls 1690 1.53 kent actual_48k_rate = (bytes * UINT64_C(250000)) / wait_us; 1691 1.18 kent 1692 1.53 kent if (actual_48k_rate < 50000) 1693 1.29 kent ac97rate = 48000; 1694 1.29 kent else 1695 1.53 kent ac97rate = ((actual_48k_rate + 500) / 1000) * 1000; 1696 1.18 kent 1697 1.136 njoly aprint_verbose_dev(sc->sc_dev, "measured ac97 link rate at %d Hz", 1698 1.136 njoly actual_48k_rate); 1699 1.29 kent if (ac97rate != actual_48k_rate) 1700 1.136 njoly aprint_verbose(", will use %d Hz", ac97rate); 1701 1.136 njoly aprint_verbose("\n"); 1702 1.18 kent 1703 1.64 kent sc->sc_ac97_clock = ac97rate; 1704 1.1 thorpej } 1705 1.95 jmcneill 1706 1.95 jmcneill static void 1707 1.95 jmcneill auich_clear_cas(struct auich_softc *sc) 1708 1.95 jmcneill { 1709 1.95 jmcneill /* Clear the codec access semaphore */ 1710 1.95 jmcneill (void)bus_space_read_2(sc->iot, sc->mix_ioh, 1711 1.95 jmcneill AC97_REG_RESET * (sc->sc_codecnum * ICH_CODEC_OFFSET)); 1712 1.95 jmcneill 1713 1.95 jmcneill return; 1714 1.95 jmcneill } 1715 1.139 jmcneill 1716 1.139 jmcneill static void 1717 1.139 jmcneill auich_get_locks(void *addr, kmutex_t **intr, kmutex_t **thread) 1718 1.139 jmcneill { 1719 1.139 jmcneill struct auich_softc *sc; 1720 1.139 jmcneill 1721 1.139 jmcneill sc = addr; 1722 1.139 jmcneill *intr = &sc->sc_intr_lock; 1723 1.139 jmcneill *thread = &sc->sc_lock; 1724 1.139 jmcneill } 1725