Line data Source code
1 : /* $OpenBSD: auich.c,v 1.109 2018/09/14 08:45:46 miko Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2000,2001 Michael Shalayeff
5 : * All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 : * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20 : * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 : * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 : * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 : * THE POSSIBILITY OF SUCH DAMAGE.
27 : */
28 :
29 : /*
30 : * AC'97 audio found on Intel 810/815/820/440MX chipsets.
31 : * http://developer.intel.com/design/chipsets/datashts/290655.htm
32 : * http://developer.intel.com/design/chipsets/manuals/298028.htm
33 : * http://www.intel.com/design/chipsets/datashts/290714.htm
34 : * http://www.intel.com/design/chipsets/datashts/290744.htm
35 : */
36 :
37 : #include <sys/param.h>
38 : #include <sys/systm.h>
39 : #include <sys/malloc.h>
40 : #include <sys/device.h>
41 :
42 : #include <dev/pci/pcidevs.h>
43 : #include <dev/pci/pcivar.h>
44 :
45 : #include <sys/audioio.h>
46 : #include <dev/audio_if.h>
47 :
48 : #include <machine/bus.h>
49 :
50 : #include <dev/ic/ac97.h>
51 :
52 : /* 12.1.10 NAMBAR - native audio mixer base address register */
53 : #define AUICH_NAMBAR 0x10
54 : /* 12.1.11 NABMBAR - native audio bus mastering base address register */
55 : #define AUICH_NABMBAR 0x14
56 : #define AUICH_CFG 0x41
57 : #define AUICH_CFG_IOSE 0x01
58 : /* ICH4/ICH5/ICH6/ICH7 native audio mixer BAR */
59 : #define AUICH_MMBAR 0x18
60 : /* ICH4/ICH5/ICH6/ICH7 native bus mastering BAR */
61 : #define AUICH_MBBAR 0x1c
62 : #define AUICH_S2CR 0x10000000 /* tertiary codec ready */
63 :
64 : /* table 12-3. native audio bus master control registers */
65 : #define AUICH_BDBAR 0x00 /* 8-byte aligned address */
66 : #define AUICH_CIV 0x04 /* 5 bits current index value */
67 : #define AUICH_LVI 0x05 /* 5 bits last valid index value */
68 : #define AUICH_LVI_MASK 0x1f
69 : #define AUICH_STS 0x06 /* 16 bits status */
70 : #define AUICH_FIFOE 0x10 /* fifo error */
71 : #define AUICH_BCIS 0x08 /* r- buf cmplt int sts; wr ack */
72 : #define AUICH_LVBCI 0x04 /* r- last valid bci, wr ack */
73 : #define AUICH_CELV 0x02 /* current equals last valid */
74 : #define AUICH_DCH 0x01 /* dma halted */
75 : #define AUICH_ISTS_BITS "\020\01dch\02celv\03lvbci\04bcis\05fifoe"
76 : #define AUICH_PICB 0x08 /* 16 bits */
77 : #define AUICH_PIV 0x0a /* 5 bits prefetched index value */
78 : #define AUICH_CTRL 0x0b /* control */
79 : #define AUICH_IOCE 0x10 /* int on completion enable */
80 : #define AUICH_FEIE 0x08 /* fifo error int enable */
81 : #define AUICH_LVBIE 0x04 /* last valid buf int enable */
82 : #define AUICH_RR 0x02 /* 1 - reset regs */
83 : #define AUICH_RPBM 0x01 /* 1 - run, 0 - pause */
84 :
85 : #define AUICH_PCMI 0x00
86 : #define AUICH_PCMO 0x10
87 : #define AUICH_MICI 0x20
88 :
89 : #define AUICH_GCTRL 0x2c
90 : #define AUICH_SSM_78 0x40000000 /* S/PDIF slots 7 and 8 */
91 : #define AUICH_SSM_69 0x80000000 /* S/PDIF slots 6 and 9 */
92 : #define AUICH_SSM_1011 0xc0000000 /* S/PDIF slots 10 and 11 */
93 : #define AUICH_POM16 0x000000 /* PCM out precision 16bit */
94 : #define AUICH_POM20 0x400000 /* PCM out precision 20bit */
95 : #define AUICH_PCM246_MASK 0x300000
96 : #define AUICH_PCM2 0x000000 /* 2ch output */
97 : #define AUICH_PCM4 0x100000 /* 4ch output */
98 : #define AUICH_PCM6 0x200000 /* 6ch output */
99 : #define AUICH_SIS_PCM246_MASK 0x0000c0 /* SiS 7012 */
100 : #define AUICH_SIS_PCM2 0x000000 /* SiS 7012 2ch output */
101 : #define AUICH_SIS_PCM4 0x000040 /* SiS 7012 4ch output */
102 : #define AUICH_SIS_PCM6 0x000080 /* SiS 7012 6ch output */
103 : #define AUICH_S2RIE 0x40 /* int when tertiary codec resume */
104 : #define AUICH_SRIE 0x20 /* int when 2ndary codec resume */
105 : #define AUICH_PRIE 0x10 /* int when primary codec resume */
106 : #define AUICH_ACLSO 0x08 /* aclink shut off */
107 : #define AUICH_WRESET 0x04 /* warm reset */
108 : #define AUICH_CRESET 0x02 /* cold reset */
109 : #define AUICH_GIE 0x01 /* gpi int enable */
110 : #define AUICH_GSTS 0x30
111 : #define AUICH_MD3 0x20000 /* pwr-dn semaphore for modem */
112 : #define AUICH_AD3 0x10000 /* pwr-dn semaphore for audio */
113 : #define AUICH_RCS 0x08000 /* read completion status */
114 : #define AUICH_B3S12 0x04000 /* bit 3 of slot 12 */
115 : #define AUICH_B2S12 0x02000 /* bit 2 of slot 12 */
116 : #define AUICH_B1S12 0x01000 /* bit 1 of slot 12 */
117 : #define AUICH_SRI 0x00800 /* secondary resume int */
118 : #define AUICH_PRI 0x00400 /* primary resume int */
119 : #define AUICH_SCR 0x00200 /* secondary codec ready */
120 : #define AUICH_PCR 0x00100 /* primary codec ready */
121 : #define AUICH_MINT 0x00080 /* mic in int */
122 : #define AUICH_POINT 0x00040 /* pcm out int */
123 : #define AUICH_PIINT 0x00020 /* pcm in int */
124 : #define AUICH_MOINT 0x00004 /* modem out int */
125 : #define AUICH_MIINT 0x00002 /* modem in int */
126 : #define AUICH_GSCI 0x00001 /* gpi status change */
127 : #define AUICH_GSTS_BITS "\020\01gsci\02miict\03moint\06piint\07point\010mint\011pcr\012scr\013pri\014sri\015b1s12\016b2s12\017b3s12\020rcs\021ad3\022md3"
128 : #define AUICH_CAS 0x34 /* 1/8 bit */
129 : #define AUICH_SEMATIMO 1000 /* us */
130 : #define AUICH_RESETIMO 500000 /* us */
131 :
132 : #define ICH_SIS_NV_CTL 0x4c /* some SiS/NVIDIA register. From Linux */
133 : #define ICH_SIS_CTL_UNMUTE 0x01 /* un-mute the output */
134 :
135 : /*
136 : * There are 32 buffer descriptors. Each can reference up to 2^16 16-bit
137 : * samples.
138 : */
139 : #define AUICH_DMALIST_MAX 32
140 : #define AUICH_DMASEG_MAX (65536*2)
141 : struct auich_dmalist {
142 : u_int32_t base;
143 : u_int32_t len;
144 : #define AUICH_DMAF_IOC 0x80000000 /* 1-int on complete */
145 : #define AUICH_DMAF_BUP 0x40000000 /* 0-retrans last, 1-transmit 0 */
146 : };
147 :
148 : #define AUICH_FIXED_RATE 48000
149 :
150 : struct auich_dma {
151 : bus_dmamap_t map;
152 : caddr_t addr;
153 : bus_dma_segment_t segs[1];
154 : int nsegs;
155 : size_t size;
156 : };
157 :
158 : struct auich_cdata {
159 : struct auich_dmalist ic_dmalist_pcmo[AUICH_DMALIST_MAX];
160 : struct auich_dmalist ic_dmalist_pcmi[AUICH_DMALIST_MAX];
161 : struct auich_dmalist ic_dmalist_mici[AUICH_DMALIST_MAX];
162 : };
163 :
164 : #define AUICH_CDOFF(x) offsetof(struct auich_cdata, x)
165 : #define AUICH_PCMO_OFF(x) AUICH_CDOFF(ic_dmalist_pcmo[(x)])
166 : #define AUICH_PCMI_OFF(x) AUICH_CDOFF(ic_dmalist_pcmi[(x)])
167 : #define AUICH_MICI_OFF(x) AUICH_CDOFF(ic_dmalist_mici[(x)])
168 :
169 : struct auich_softc {
170 : struct device sc_dev;
171 : void *sc_ih;
172 :
173 : pcireg_t pci_id;
174 : bus_space_tag_t iot;
175 : bus_space_tag_t iot_mix;
176 : bus_space_handle_t mix_ioh;
177 : bus_space_handle_t aud_ioh;
178 : bus_dma_tag_t dmat;
179 :
180 : struct ac97_codec_if *codec_if;
181 : struct ac97_host_if host_if;
182 : int sc_spdif;
183 :
184 : /* dma scatter-gather buffer lists */
185 :
186 : bus_dmamap_t sc_cddmamap;
187 : #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr
188 :
189 : struct auich_cdata *sc_cdata;
190 :
191 : struct auich_ring {
192 : int qptr;
193 : struct auich_dmalist *dmalist;
194 :
195 : uint32_t start, p, end;
196 : int blksize;
197 :
198 : void (*intr)(void *);
199 : void *arg;
200 : int running;
201 : size_t size;
202 : uint32_t ap;
203 : } pcmo, pcmi, mici;
204 :
205 : struct auich_dma *sc_pdma; /* play */
206 : struct auich_dma *sc_rdma; /* record */
207 : struct auich_dma *sc_cdma; /* calibrate */
208 :
209 : #ifdef AUICH_DEBUG
210 : int pcmi_fifoe;
211 : int pcmo_fifoe;
212 : #endif
213 :
214 : int suspend;
215 : u_int16_t ext_ctrl;
216 : int sc_sample_size;
217 : int sc_sts_reg;
218 : int sc_dmamap_flags;
219 : int sc_ignore_codecready;
220 : int flags;
221 : int sc_ac97rate;
222 :
223 : /* multi-channel control bits */
224 : int sc_pcm246_mask;
225 : int sc_pcm2;
226 : int sc_pcm4;
227 : int sc_pcm6;
228 :
229 : u_int last_rrate;
230 : u_int last_prate;
231 : u_int last_pchan;
232 : };
233 :
234 : #ifdef AUICH_DEBUG
235 : #define DPRINTF(l,x) do { if (auich_debug & (l)) printf x; } while(0)
236 : int auich_debug = 0x0002;
237 : #define AUICH_DEBUG_CODECIO 0x0001
238 : #define AUICH_DEBUG_DMA 0x0002
239 : #define AUICH_DEBUG_INTR 0x0004
240 : #else
241 : #define DPRINTF(x,y) /* nothing */
242 : #endif
243 :
244 : struct cfdriver auich_cd = {
245 : NULL, "auich", DV_DULL
246 : };
247 :
248 : int auich_match(struct device *, void *, void *);
249 : void auich_attach(struct device *, struct device *, void *);
250 : int auich_intr(void *);
251 :
252 : int auich_activate(struct device *, int);
253 :
254 : struct cfattach auich_ca = {
255 : sizeof(struct auich_softc), auich_match, auich_attach,
256 : NULL, auich_activate
257 : };
258 :
259 : static const struct auich_devtype {
260 : int vendor;
261 : int product;
262 : int options;
263 : char name[8];
264 : } auich_devices[] = {
265 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6300ESB_ACA, 0, "ESB" },
266 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6321ESB_ACA, 0, "ESB2" },
267 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_ACA, 0, "ICH" },
268 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_ACA, 0, "ICH0" },
269 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_ACA, 0, "ICH2" },
270 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CA_ACA, 0, "ICH3" },
271 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_ACA, 0, "ICH4" },
272 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801EB_ACA, 0, "ICH5" },
273 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801FB_ACA, 0, "ICH6" },
274 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GB_ACA, 0, "ICH7" },
275 : { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_ACA, 0, "440MX" },
276 : { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7012_ACA, 0, "SiS7012" },
277 : { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_ACA, 0, "nForce" },
278 : { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_ACA, 0, "nForce2" },
279 : { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_ACA,
280 : 0, "nForce2" },
281 : { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_ACA, 0, "nForce3" },
282 : { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_250_ACA,
283 : 0, "nForce3" },
284 : { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_AC, 0, "nForce4" },
285 : { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_AC97, 0, "MCP04" },
286 : { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP51_ACA, 0, "MCP51" },
287 : { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC768_ACA, 0, "AMD768" },
288 : { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_8111_ACA, 0, "AMD8111" },
289 : };
290 :
291 : int auich_open(void *, int);
292 : void auich_close(void *);
293 : int auich_set_params(void *, int, int, struct audio_params *,
294 : struct audio_params *);
295 : int auich_round_blocksize(void *, int);
296 : void auich_halt_pipe(struct auich_softc *, int, struct auich_ring *);
297 : int auich_halt_output(void *);
298 : int auich_halt_input(void *);
299 : int auich_set_port(void *, mixer_ctrl_t *);
300 : int auich_get_port(void *, mixer_ctrl_t *);
301 : int auich_query_devinfo(void *, mixer_devinfo_t *);
302 : void *auich_allocm(void *, int, size_t, int, int);
303 : void auich_freem(void *, void *, int);
304 : size_t auich_round_buffersize(void *, int, size_t);
305 : int auich_get_props(void *);
306 : void auich_trigger_pipe(struct auich_softc *, int, struct auich_ring *);
307 : void auich_intr_pipe(struct auich_softc *, int, struct auich_ring *);
308 : int auich_trigger_output(void *, void *, void *, int, void (*)(void *),
309 : void *, struct audio_params *);
310 : int auich_trigger_input(void *, void *, void *, int, void (*)(void *),
311 : void *, struct audio_params *);
312 : int auich_alloc_cdata(struct auich_softc *);
313 : int auich_allocmem(struct auich_softc *, size_t, size_t, struct auich_dma *);
314 : int auich_freemem(struct auich_softc *, struct auich_dma *);
315 :
316 : void auich_resume(struct auich_softc *);
317 :
318 : struct audio_hw_if auich_hw_if = {
319 : auich_open,
320 : auich_close,
321 : auich_set_params,
322 : auich_round_blocksize,
323 : NULL, /* commit_setting */
324 : NULL, /* init_output */
325 : NULL, /* init_input */
326 : NULL, /* start_output */
327 : NULL, /* start_input */
328 : auich_halt_output,
329 : auich_halt_input,
330 : NULL, /* speaker_ctl */
331 : NULL, /* getfd */
332 : auich_set_port,
333 : auich_get_port,
334 : auich_query_devinfo,
335 : auich_allocm,
336 : auich_freem,
337 : auich_round_buffersize,
338 : auich_get_props,
339 : auich_trigger_output,
340 : auich_trigger_input
341 : };
342 :
343 : int auich_attach_codec(void *, struct ac97_codec_if *);
344 : int auich_read_codec(void *, u_int8_t, u_int16_t *);
345 : int auich_write_codec(void *, u_int8_t, u_int16_t);
346 : void auich_reset_codec(void *);
347 : enum ac97_host_flags auich_flags_codec(void *);
348 : unsigned int auich_calibrate(struct auich_softc *);
349 : void auich_spdif_event(void *, int);
350 :
351 : int
352 0 : auich_match(struct device *parent, void *match, void *aux)
353 : {
354 0 : struct pci_attach_args *pa = aux;
355 : int i;
356 :
357 0 : for (i = nitems(auich_devices); i--;)
358 0 : if (PCI_VENDOR(pa->pa_id) == auich_devices[i].vendor &&
359 0 : PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)
360 0 : return 1;
361 :
362 0 : return 0;
363 0 : }
364 :
365 : void
366 0 : auich_attach(struct device *parent, struct device *self, void *aux)
367 : {
368 0 : struct auich_softc *sc = (struct auich_softc *)self;
369 0 : struct pci_attach_args *pa = aux;
370 0 : pci_intr_handle_t ih;
371 0 : bus_size_t mix_size, aud_size;
372 : pcireg_t csr;
373 : const char *intrstr;
374 : u_int32_t status;
375 : int i;
376 :
377 0 : if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
378 0 : (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA ||
379 0 : PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801EB_ACA ||
380 0 : PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801FB_ACA ||
381 0 : PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801GB_ACA)) {
382 : /*
383 : * Use native mode for ICH4/ICH5/ICH6/ICH7
384 : */
385 0 : if (pci_mapreg_map(pa, AUICH_MMBAR, PCI_MAPREG_TYPE_MEM, 0,
386 0 : &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
387 0 : csr = pci_conf_read(pa->pa_pc, pa->pa_tag, AUICH_CFG);
388 0 : pci_conf_write(pa->pa_pc, pa->pa_tag, AUICH_CFG,
389 0 : csr | AUICH_CFG_IOSE);
390 0 : if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO,
391 : 0, &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
392 0 : printf(": can't map codec mem/io space\n");
393 0 : return;
394 : }
395 : }
396 :
397 0 : if (pci_mapreg_map(pa, AUICH_MBBAR, PCI_MAPREG_TYPE_MEM, 0,
398 0 : &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) {
399 0 : csr = pci_conf_read(pa->pa_pc, pa->pa_tag, AUICH_CFG);
400 0 : pci_conf_write(pa->pa_pc, pa->pa_tag, AUICH_CFG,
401 0 : csr | AUICH_CFG_IOSE);
402 0 : if (pci_mapreg_map(pa, AUICH_NABMBAR,
403 : PCI_MAPREG_TYPE_IO, 0, &sc->iot,
404 : &sc->aud_ioh, NULL, &aud_size, 0)) {
405 0 : printf(": can't map device mem/io space\n");
406 0 : bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
407 0 : return;
408 : }
409 : }
410 : } else {
411 0 : if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO,
412 0 : 0, &sc->iot_mix, &sc->mix_ioh, NULL, &mix_size, 0)) {
413 0 : printf(": can't map codec i/o space\n");
414 0 : return;
415 : }
416 :
417 0 : if (pci_mapreg_map(pa, AUICH_NABMBAR, PCI_MAPREG_TYPE_IO,
418 0 : 0, &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) {
419 0 : printf(": can't map device i/o space\n");
420 0 : bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
421 0 : return;
422 : }
423 : }
424 0 : sc->dmat = pa->pa_dmat;
425 0 : sc->pci_id = pa->pa_id;
426 :
427 0 : if (pci_intr_map(pa, &ih)) {
428 0 : printf(": can't map interrupt\n");
429 0 : bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
430 0 : bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
431 0 : return;
432 : }
433 0 : intrstr = pci_intr_string(pa->pa_pc, ih);
434 0 : sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO | IPL_MPSAFE,
435 0 : auich_intr, sc, sc->sc_dev.dv_xname);
436 0 : if (!sc->sc_ih) {
437 0 : printf(": can't establish interrupt");
438 0 : if (intrstr)
439 0 : printf(" at %s", intrstr);
440 0 : printf("\n");
441 0 : bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
442 0 : bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
443 0 : return;
444 : }
445 :
446 0 : for (i = nitems(auich_devices); i--;)
447 0 : if (PCI_PRODUCT(pa->pa_id) == auich_devices[i].product)
448 : break;
449 :
450 0 : printf(": %s, %s\n", intrstr, auich_devices[i].name);
451 :
452 : /* SiS 7012 needs special handling */
453 0 : if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SIS &&
454 0 : PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_7012_ACA) {
455 0 : sc->sc_sts_reg = AUICH_PICB;
456 0 : sc->sc_sample_size = 1;
457 0 : sc->sc_pcm246_mask = AUICH_SIS_PCM246_MASK;
458 0 : sc->sc_pcm2 = AUICH_SIS_PCM2;
459 0 : sc->sc_pcm4 = AUICH_SIS_PCM4;
460 0 : sc->sc_pcm6 = AUICH_SIS_PCM6;
461 : /* un-mute output */
462 0 : bus_space_write_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL,
463 : bus_space_read_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL) |
464 : ICH_SIS_CTL_UNMUTE);
465 0 : } else {
466 0 : sc->sc_sts_reg = AUICH_STS;
467 0 : sc->sc_sample_size = 2;
468 0 : sc->sc_pcm246_mask = AUICH_PCM246_MASK;
469 0 : sc->sc_pcm2 = AUICH_PCM2;
470 0 : sc->sc_pcm4 = AUICH_PCM4;
471 0 : sc->sc_pcm6 = AUICH_PCM6;
472 : }
473 :
474 : /* Workaround for a 440MX B-stepping erratum */
475 0 : sc->sc_dmamap_flags = BUS_DMA_COHERENT;
476 0 : if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
477 0 : PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82440MX_ACA) {
478 0 : sc->sc_dmamap_flags |= BUS_DMA_NOCACHE;
479 0 : printf("%s: DMA bug workaround enabled\n", sc->sc_dev.dv_xname);
480 0 : }
481 :
482 : /* Set up DMA lists. */
483 0 : sc->pcmo.qptr = sc->pcmi.qptr = sc->mici.qptr = 0;
484 0 : auich_alloc_cdata(sc);
485 :
486 : DPRINTF(AUICH_DEBUG_DMA, ("auich_attach: lists %p %p %p\n",
487 : sc->pcmo.dmalist, sc->pcmi.dmalist, sc->mici.dmalist));
488 :
489 : /* Reset codec and AC'97 */
490 0 : auich_reset_codec(sc);
491 0 : status = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS);
492 0 : if (!(status & AUICH_PCR)) { /* reset failure */
493 0 : if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
494 0 : (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA ||
495 0 : PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801EB_ACA ||
496 0 : PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801FB_ACA ||
497 0 : PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801GB_ACA)) {
498 : /* MSI 845G Max never return AUICH_PCR */
499 0 : sc->sc_ignore_codecready = 1;
500 : } else {
501 0 : printf("%s: reset failed!\n", sc->sc_dev.dv_xname);
502 0 : return;
503 : }
504 0 : }
505 :
506 0 : sc->host_if.arg = sc;
507 0 : sc->host_if.attach = auich_attach_codec;
508 0 : sc->host_if.read = auich_read_codec;
509 0 : sc->host_if.write = auich_write_codec;
510 0 : sc->host_if.reset = auich_reset_codec;
511 0 : sc->host_if.flags = auich_flags_codec;
512 0 : sc->host_if.spdif_event = auich_spdif_event;
513 0 : if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001)
514 0 : sc->flags = AC97_HOST_SWAPPED_CHANNELS;
515 :
516 0 : if (ac97_attach(&sc->host_if) != 0) {
517 0 : pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
518 0 : bus_space_unmap(sc->iot, sc->aud_ioh, aud_size);
519 0 : bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size);
520 0 : return;
521 : }
522 0 : sc->codec_if->vtbl->unlock(sc->codec_if);
523 :
524 0 : audio_attach_mi(&auich_hw_if, sc, &sc->sc_dev);
525 :
526 : /* Watch for power changes */
527 0 : sc->suspend = DVACT_RESUME;
528 :
529 0 : sc->sc_ac97rate = -1;
530 0 : }
531 :
532 : int
533 0 : auich_activate(struct device *self, int act)
534 : {
535 0 : struct auich_softc *sc = (struct auich_softc *)self;
536 :
537 0 : switch (act) {
538 : case DVACT_RESUME:
539 0 : auich_resume(sc);
540 0 : break;
541 : default:
542 : break;
543 : }
544 0 : return (config_activate_children(self, act));
545 : }
546 :
547 : int
548 0 : auich_read_codec(void *v, u_int8_t reg, u_int16_t *val)
549 : {
550 0 : struct auich_softc *sc = v;
551 : int i;
552 :
553 : /* wait for an access semaphore */
554 0 : for (i = AUICH_SEMATIMO; i-- &&
555 0 : bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));
556 :
557 0 : if (!sc->sc_ignore_codecready && i < 0) {
558 : DPRINTF(AUICH_DEBUG_CODECIO,
559 : ("%s: read_codec timeout\n", sc->sc_dev.dv_xname));
560 0 : return (-1);
561 : }
562 :
563 0 : *val = bus_space_read_2(sc->iot_mix, sc->mix_ioh, reg);
564 : DPRINTF(AUICH_DEBUG_CODECIO, ("%s: read_codec(%x, %x)\n",
565 : sc->sc_dev.dv_xname, reg, *val));
566 0 : return (0);
567 0 : }
568 :
569 : int
570 0 : auich_write_codec(void *v, u_int8_t reg, u_int16_t val)
571 : {
572 0 : struct auich_softc *sc = v;
573 : int i;
574 :
575 : /* wait for an access semaphore */
576 0 : for (i = AUICH_SEMATIMO; i-- &&
577 0 : bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_CAS) & 1; DELAY(1));
578 :
579 0 : if (sc->sc_ignore_codecready || i >= 0) {
580 : DPRINTF(AUICH_DEBUG_CODECIO, ("%s: write_codec(%x, %x)\n",
581 : sc->sc_dev.dv_xname, reg, val));
582 0 : bus_space_write_2(sc->iot_mix, sc->mix_ioh, reg, val);
583 0 : return (0);
584 : } else {
585 : DPRINTF(AUICH_DEBUG_CODECIO,
586 : ("%s: write_codec timeout\n", sc->sc_dev.dv_xname));
587 0 : return (-1);
588 : }
589 0 : }
590 :
591 : int
592 0 : auich_attach_codec(void *v, struct ac97_codec_if *cif)
593 : {
594 0 : struct auich_softc *sc = v;
595 :
596 0 : sc->codec_if = cif;
597 0 : return 0;
598 : }
599 :
600 : void
601 0 : auich_reset_codec(void *v)
602 : {
603 0 : struct auich_softc *sc = v;
604 : u_int32_t control;
605 : int i;
606 :
607 0 : control = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GCTRL);
608 0 : control &= ~(AUICH_ACLSO | sc->sc_pcm246_mask);
609 0 : control |= (control & AUICH_CRESET) ? AUICH_WRESET : AUICH_CRESET;
610 0 : bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, control);
611 :
612 0 : for (i = AUICH_RESETIMO; i-- &&
613 0 : !(bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS) & AUICH_PCR);
614 0 : DELAY(1));
615 :
616 : if (i < 0)
617 : DPRINTF(AUICH_DEBUG_CODECIO,
618 : ("%s: reset_codec timeout\n", sc->sc_dev.dv_xname));
619 0 : }
620 :
621 : enum ac97_host_flags
622 0 : auich_flags_codec(void *v)
623 : {
624 0 : struct auich_softc *sc = v;
625 :
626 0 : return (sc->flags);
627 : }
628 :
629 : void
630 0 : auich_spdif_event(void *v, int flag)
631 : {
632 0 : struct auich_softc *sc = v;
633 0 : sc->sc_spdif = flag;
634 0 : }
635 :
636 : int
637 0 : auich_open(void *v, int flags)
638 : {
639 0 : struct auich_softc *sc = v;
640 :
641 0 : if (sc->sc_ac97rate == -1)
642 0 : sc->sc_ac97rate = auich_calibrate(sc);
643 :
644 0 : sc->codec_if->vtbl->lock(sc->codec_if);
645 :
646 0 : return 0;
647 : }
648 :
649 : void
650 0 : auich_close(void *v)
651 : {
652 0 : struct auich_softc *sc = v;
653 :
654 0 : sc->codec_if->vtbl->unlock(sc->codec_if);
655 0 : }
656 :
657 : int
658 0 : auich_set_params(void *v, int setmode, int usemode,
659 : struct audio_params *play, struct audio_params *rec)
660 : {
661 0 : struct auich_softc *sc = v;
662 0 : struct ac97_codec_if *codec = sc->codec_if;
663 : int error;
664 : u_int orate;
665 : u_int adj_rate;
666 : u_int32_t control;
667 : u_int16_t ext_id;
668 :
669 0 : if (setmode & AUMODE_PLAY) {
670 : /* only 16-bit 48kHz slinear_le if s/pdif enabled */
671 0 : if (sc->sc_spdif) {
672 0 : play->sample_rate = 48000;
673 0 : play->precision = 16;
674 0 : play->encoding = AUDIO_ENCODING_SLINEAR_LE;
675 0 : }
676 : }
677 0 : if (setmode & AUMODE_PLAY) {
678 0 : play->precision = 16;
679 0 : switch(play->encoding) {
680 : case AUDIO_ENCODING_SLINEAR_LE:
681 0 : if (play->channels > 6)
682 0 : play->channels = 6;
683 0 : if (play->channels > 1)
684 0 : play->channels &= ~1;
685 0 : switch (play->channels) {
686 : case 1:
687 0 : play->channels = 2;
688 0 : break;
689 : case 2:
690 : break;
691 : case 4:
692 0 : ext_id = codec->vtbl->get_caps(codec);
693 0 : if (!(ext_id & AC97_EXT_AUDIO_SDAC))
694 0 : play->channels = 2;
695 : break;
696 : case 6:
697 0 : ext_id = codec->vtbl->get_caps(codec);
698 0 : if ((ext_id & AC97_BITS_6CH) !=
699 : AC97_BITS_6CH)
700 0 : play->channels = 2;
701 : break;
702 : default:
703 0 : return (EINVAL);
704 : }
705 : break;
706 : default:
707 0 : return (EINVAL);
708 : }
709 0 : play->bps = AUDIO_BPS(play->precision);
710 0 : play->msb = 1;
711 :
712 0 : orate = adj_rate = play->sample_rate;
713 0 : if (sc->sc_ac97rate != 0)
714 0 : adj_rate = orate * AUICH_FIXED_RATE / sc->sc_ac97rate;
715 :
716 0 : play->sample_rate = adj_rate;
717 0 : sc->last_prate = play->sample_rate;
718 :
719 0 : error = ac97_set_rate(sc->codec_if,
720 : AC97_REG_PCM_LFE_DAC_RATE, &play->sample_rate);
721 0 : if (error)
722 0 : return (error);
723 :
724 0 : play->sample_rate = adj_rate;
725 0 : error = ac97_set_rate(sc->codec_if,
726 : AC97_REG_PCM_SURR_DAC_RATE, &play->sample_rate);
727 0 : if (error)
728 0 : return (error);
729 :
730 0 : play->sample_rate = adj_rate;
731 0 : error = ac97_set_rate(sc->codec_if,
732 : AC97_REG_PCM_FRONT_DAC_RATE, &play->sample_rate);
733 0 : if (error)
734 0 : return (error);
735 :
736 0 : if (play->sample_rate == adj_rate)
737 0 : play->sample_rate = orate;
738 :
739 0 : control = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GCTRL);
740 0 : control &= ~(sc->sc_pcm246_mask);
741 0 : if (play->channels == 4)
742 0 : control |= sc->sc_pcm4;
743 0 : else if (play->channels == 6)
744 0 : control |= sc->sc_pcm6;
745 0 : bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, control);
746 :
747 0 : sc->last_pchan = play->channels;
748 0 : }
749 :
750 0 : if (setmode & AUMODE_RECORD) {
751 0 : rec->channels = 2;
752 0 : rec->precision = 16;
753 0 : rec->encoding = AUDIO_ENCODING_SLINEAR_LE;
754 0 : rec->bps = AUDIO_BPS(rec->precision);
755 0 : rec->msb = 1;
756 :
757 0 : orate = rec->sample_rate;
758 0 : if (sc->sc_ac97rate != 0)
759 0 : rec->sample_rate = orate * AUICH_FIXED_RATE /
760 : sc->sc_ac97rate;
761 0 : sc->last_rrate = rec->sample_rate;
762 0 : error = ac97_set_rate(sc->codec_if, AC97_REG_PCM_LR_ADC_RATE,
763 : &rec->sample_rate);
764 0 : if (error)
765 0 : return (error);
766 0 : rec->sample_rate = orate;
767 0 : }
768 :
769 0 : return (0);
770 0 : }
771 :
772 : int
773 0 : auich_round_blocksize(void *v, int blk)
774 : {
775 0 : return (blk + 0x3f) & ~0x3f;
776 : }
777 :
778 :
779 : void
780 0 : auich_halt_pipe(struct auich_softc *sc, int pipe, struct auich_ring *ring)
781 : {
782 : int i;
783 : uint32_t sts;
784 :
785 0 : bus_space_write_1(sc->iot, sc->aud_ioh, pipe + AUICH_CTRL, 0);
786 :
787 : /* wait for DMA halted and clear interrupt / event bits if needed */
788 0 : for (i = 0; i < 1000; i++) {
789 0 : sts = bus_space_read_2(sc->iot, sc->aud_ioh,
790 : pipe + sc->sc_sts_reg);
791 0 : if (sts & (AUICH_CELV | AUICH_LVBCI | AUICH_BCIS | AUICH_FIFOE))
792 0 : bus_space_write_2(sc->iot, sc->aud_ioh,
793 : pipe + sc->sc_sts_reg,
794 : AUICH_CELV | AUICH_LVBCI |
795 : AUICH_BCIS | AUICH_FIFOE);
796 0 : if (sts & AUICH_DCH)
797 : break;
798 0 : DELAY(100);
799 : }
800 0 : bus_space_write_1(sc->iot, sc->aud_ioh, pipe + AUICH_CTRL, AUICH_RR);
801 :
802 : if (i > 0)
803 : DPRINTF(AUICH_DEBUG_DMA,
804 : ("auich_halt_pipe: halt took %d cycles\n", i));
805 :
806 0 : ring->running = 0;
807 0 : }
808 :
809 :
810 : int
811 0 : auich_halt_output(void *v)
812 : {
813 0 : struct auich_softc *sc = v;
814 :
815 : DPRINTF(AUICH_DEBUG_DMA, ("%s: halt_output\n", sc->sc_dev.dv_xname));
816 :
817 0 : mtx_enter(&audio_lock);
818 0 : auich_halt_pipe(sc, AUICH_PCMO, &sc->pcmo);
819 :
820 0 : sc->pcmo.intr = NULL;
821 0 : mtx_leave(&audio_lock);
822 0 : return 0;
823 : }
824 :
825 : int
826 0 : auich_halt_input(void *v)
827 : {
828 0 : struct auich_softc *sc = v;
829 :
830 : DPRINTF(AUICH_DEBUG_DMA,
831 : ("%s: halt_input\n", sc->sc_dev.dv_xname));
832 :
833 : /* XXX halt both unless known otherwise */
834 0 : mtx_enter(&audio_lock);
835 0 : auich_halt_pipe(sc, AUICH_PCMI, &sc->pcmi);
836 0 : auich_halt_pipe(sc, AUICH_MICI, &sc->mici);
837 :
838 0 : sc->pcmi.intr = NULL;
839 0 : mtx_leave(&audio_lock);
840 0 : return 0;
841 : }
842 :
843 : int
844 0 : auich_set_port(void *v, mixer_ctrl_t *cp)
845 : {
846 0 : struct auich_softc *sc = v;
847 0 : return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
848 : }
849 :
850 : int
851 0 : auich_get_port(void *v, mixer_ctrl_t *cp)
852 : {
853 0 : struct auich_softc *sc = v;
854 0 : return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp);
855 : }
856 :
857 : int
858 0 : auich_query_devinfo(void *v, mixer_devinfo_t *dp)
859 : {
860 0 : struct auich_softc *sc = v;
861 0 : return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp);
862 : }
863 :
864 : void *
865 0 : auich_allocm(void *v, int direction, size_t size, int pool, int flags)
866 : {
867 0 : struct auich_softc *sc = v;
868 : struct auich_dma *p;
869 : int error;
870 :
871 : /* can only use 1 segment */
872 0 : if (size > AUICH_DMASEG_MAX) {
873 : DPRINTF(AUICH_DEBUG_DMA,
874 : ("%s: requested buffer size too large: %zd", \
875 : sc->sc_dev.dv_xname, size));
876 0 : return NULL;
877 : }
878 :
879 0 : p = malloc(sizeof(*p), pool, flags | M_ZERO);
880 0 : if (!p)
881 0 : return NULL;
882 :
883 0 : error = auich_allocmem(sc, size, PAGE_SIZE, p);
884 0 : if (error) {
885 0 : free(p, pool, 0);
886 0 : return NULL;
887 : }
888 :
889 0 : if (direction == AUMODE_PLAY)
890 0 : sc->sc_pdma = p;
891 0 : else if (direction == AUMODE_RECORD)
892 0 : sc->sc_rdma = p;
893 : else
894 0 : sc->sc_cdma = p;
895 :
896 0 : return p->addr;
897 0 : }
898 :
899 : void
900 0 : auich_freem(void *v, void *ptr, int pool)
901 : {
902 : struct auich_softc *sc;
903 : struct auich_dma *p;
904 :
905 0 : sc = v;
906 0 : if (sc->sc_pdma != NULL && sc->sc_pdma->addr == ptr)
907 0 : p = sc->sc_pdma;
908 0 : else if (sc->sc_rdma != NULL && sc->sc_rdma->addr == ptr)
909 0 : p = sc->sc_rdma;
910 0 : else if (sc->sc_cdma != NULL && sc->sc_cdma->addr == ptr)
911 : p = sc->sc_cdma;
912 : else
913 0 : return;
914 :
915 0 : auich_freemem(sc, p);
916 0 : free(p, pool, 0);
917 0 : }
918 :
919 : size_t
920 0 : auich_round_buffersize(void *v, int direction, size_t size)
921 : {
922 0 : if (size > AUICH_DMALIST_MAX * AUICH_DMASEG_MAX)
923 : size = AUICH_DMALIST_MAX * AUICH_DMASEG_MAX;
924 :
925 0 : return size;
926 : }
927 :
928 : int
929 0 : auich_get_props(void *v)
930 : {
931 0 : return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
932 : }
933 :
934 : int
935 0 : auich_intr(void *v)
936 : {
937 0 : struct auich_softc *sc = v;
938 : int ret = 0, sts, gsts;
939 :
940 0 : mtx_enter(&audio_lock);
941 0 : gsts = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS);
942 : DPRINTF(AUICH_DEBUG_INTR, ("auich_intr: gsts=%b\n", gsts, AUICH_GSTS_BITS));
943 :
944 0 : if (gsts & AUICH_POINT) {
945 0 : sts = bus_space_read_2(sc->iot, sc->aud_ioh,
946 : AUICH_PCMO + sc->sc_sts_reg);
947 : DPRINTF(AUICH_DEBUG_INTR,
948 : ("auich_intr: osts=%b\n", sts, AUICH_ISTS_BITS));
949 :
950 : #ifdef AUICH_DEBUG
951 : if (sts & AUICH_FIFOE) {
952 : printf("%s: in fifo underrun # %u civ=%u ctrl=0x%x sts=%b\n",
953 : sc->sc_dev.dv_xname, sc->pcmo_fifoe++,
954 : bus_space_read_1(sc->iot, sc->aud_ioh,
955 : AUICH_PCMO + AUICH_CIV),
956 : bus_space_read_1(sc->iot, sc->aud_ioh,
957 : AUICH_PCMO + AUICH_CTRL),
958 : bus_space_read_2(sc->iot, sc->aud_ioh,
959 : AUICH_PCMO + sc->sc_sts_reg),
960 : AUICH_ISTS_BITS);
961 : }
962 : #endif
963 :
964 0 : if (sts & AUICH_BCIS)
965 0 : auich_intr_pipe(sc, AUICH_PCMO, &sc->pcmo);
966 :
967 : /* int ack */
968 0 : bus_space_write_2(sc->iot, sc->aud_ioh,
969 : AUICH_PCMO + sc->sc_sts_reg, sts &
970 : (AUICH_BCIS | AUICH_FIFOE));
971 0 : bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_POINT);
972 : ret++;
973 0 : }
974 :
975 0 : if (gsts & AUICH_PIINT) {
976 0 : sts = bus_space_read_2(sc->iot, sc->aud_ioh,
977 : AUICH_PCMI + sc->sc_sts_reg);
978 : DPRINTF(AUICH_DEBUG_INTR,
979 : ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS));
980 :
981 : #ifdef AUICH_DEBUG
982 : if (sts & AUICH_FIFOE) {
983 : printf("%s: in fifo overrun # %u civ=%u ctrl=0x%x sts=%b\n",
984 : sc->sc_dev.dv_xname, sc->pcmi_fifoe++,
985 : bus_space_read_1(sc->iot, sc->aud_ioh,
986 : AUICH_PCMI + AUICH_CIV),
987 : bus_space_read_1(sc->iot, sc->aud_ioh,
988 : AUICH_PCMI + AUICH_CTRL),
989 : bus_space_read_2(sc->iot, sc->aud_ioh,
990 : AUICH_PCMI + sc->sc_sts_reg),
991 : AUICH_ISTS_BITS);
992 : }
993 : #endif
994 :
995 0 : if (sts & AUICH_BCIS)
996 0 : auich_intr_pipe(sc, AUICH_PCMI, &sc->pcmi);
997 :
998 : /* int ack */
999 0 : bus_space_write_2(sc->iot, sc->aud_ioh,
1000 : AUICH_PCMI + sc->sc_sts_reg, sts &
1001 : (AUICH_BCIS | AUICH_FIFOE));
1002 0 : bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_PIINT);
1003 0 : ret++;
1004 0 : }
1005 :
1006 0 : if (gsts & AUICH_MINT) {
1007 0 : sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1008 : AUICH_MICI + sc->sc_sts_reg);
1009 : DPRINTF(AUICH_DEBUG_INTR,
1010 : ("auich_intr: ists=%b\n", sts, AUICH_ISTS_BITS));
1011 : #ifdef AUICH_DEBUG
1012 : if (sts & AUICH_FIFOE) {
1013 : printf("%s: in fifo overrun civ=%u ctrl=0x%x sts=%b\n",
1014 : sc->sc_dev.dv_xname,
1015 : bus_space_read_1(sc->iot, sc->aud_ioh,
1016 : AUICH_MICI + AUICH_CIV),
1017 : bus_space_read_1(sc->iot, sc->aud_ioh,
1018 : AUICH_MICI + AUICH_CTRL),
1019 : bus_space_read_2(sc->iot, sc->aud_ioh,
1020 : AUICH_MICI + sc->sc_sts_reg),
1021 : AUICH_ISTS_BITS);
1022 : }
1023 : #endif
1024 0 : if (sts & AUICH_BCIS)
1025 0 : auich_intr_pipe(sc, AUICH_MICI, &sc->mici);
1026 :
1027 : /* int ack */
1028 0 : bus_space_write_2(sc->iot, sc->aud_ioh,
1029 : AUICH_MICI + sc->sc_sts_reg,
1030 : sts + (AUICH_BCIS | AUICH_FIFOE));
1031 :
1032 0 : bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_MINT);
1033 0 : ret++;
1034 0 : }
1035 0 : mtx_leave(&audio_lock);
1036 0 : return ret;
1037 : }
1038 :
1039 :
1040 : void
1041 0 : auich_trigger_pipe(struct auich_softc *sc, int pipe, struct auich_ring *ring)
1042 : {
1043 : int blksize, qptr, oqptr;
1044 : struct auich_dmalist *q;
1045 :
1046 0 : blksize = ring->blksize;
1047 0 : qptr = oqptr = bus_space_read_1(sc->iot, sc->aud_ioh, pipe + AUICH_CIV);
1048 :
1049 : /* XXX remove this when no one reports problems */
1050 0 : if(oqptr >= AUICH_DMALIST_MAX) {
1051 0 : printf("%s: Unexpected CIV: %d\n", sc->sc_dev.dv_xname, oqptr);
1052 : qptr = oqptr = 0;
1053 0 : }
1054 :
1055 0 : do {
1056 0 : q = &ring->dmalist[qptr];
1057 0 : q->base = ring->p;
1058 0 : q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC;
1059 :
1060 : DPRINTF(AUICH_DEBUG_INTR,
1061 : ("auich_trigger_pipe: %p, %p = %x @ 0x%x qptr=%d\n",
1062 : &ring->dmalist[qptr], q, q->len, q->base, qptr));
1063 :
1064 0 : ring->p += blksize;
1065 0 : if (ring->p >= ring->end)
1066 0 : ring->p = ring->start;
1067 :
1068 0 : qptr = (qptr + 1) & AUICH_LVI_MASK;
1069 0 : } while (qptr != oqptr);
1070 :
1071 0 : ring->qptr = qptr;
1072 :
1073 : DPRINTF(AUICH_DEBUG_DMA,
1074 : ("auich_trigger_pipe: qptr=%d\n", qptr));
1075 :
1076 0 : bus_space_write_1(sc->iot, sc->aud_ioh, pipe + AUICH_LVI,
1077 : (qptr - 1) & AUICH_LVI_MASK);
1078 0 : bus_space_write_1(sc->iot, sc->aud_ioh, pipe + AUICH_CTRL,
1079 : AUICH_IOCE | AUICH_FEIE | AUICH_RPBM);
1080 :
1081 0 : ring->running = 1;
1082 0 : }
1083 :
1084 : void
1085 0 : auich_intr_pipe(struct auich_softc *sc, int pipe, struct auich_ring *ring)
1086 : {
1087 : int blksize, qptr, nqptr;
1088 : struct auich_dmalist *q;
1089 :
1090 0 : blksize = ring->blksize;
1091 0 : qptr = ring->qptr;
1092 0 : nqptr = bus_space_read_1(sc->iot, sc->aud_ioh, pipe + AUICH_CIV);
1093 :
1094 0 : while (qptr != nqptr) {
1095 0 : q = &ring->dmalist[qptr];
1096 0 : q->base = ring->p;
1097 0 : q->len = (blksize / sc->sc_sample_size) | AUICH_DMAF_IOC;
1098 :
1099 : DPRINTF(AUICH_DEBUG_INTR,
1100 : ("auich_intr: %p, %p = %x @ 0x%x qptr=%d\n",
1101 : &ring->dmalist[qptr], q, q->len, q->base, qptr));
1102 :
1103 0 : ring->p += blksize;
1104 0 : if (ring->p >= ring->end)
1105 0 : ring->p = ring->start;
1106 :
1107 0 : qptr = (qptr + 1) & AUICH_LVI_MASK;
1108 0 : if (ring->intr)
1109 0 : ring->intr(ring->arg);
1110 : else
1111 0 : printf("auich_intr: got progress with intr==NULL\n");
1112 :
1113 0 : ring->ap += blksize;
1114 0 : if (ring->ap >= ring->size)
1115 0 : ring->ap = 0;
1116 : }
1117 0 : ring->qptr = qptr;
1118 :
1119 0 : bus_space_write_1(sc->iot, sc->aud_ioh, pipe + AUICH_LVI,
1120 : (qptr - 1) & AUICH_LVI_MASK);
1121 0 : }
1122 :
1123 :
1124 : int
1125 0 : auich_trigger_output(void *v, void *start, void *end, int blksize,
1126 : void (*intr)(void *), void *arg, struct audio_params *param)
1127 : {
1128 0 : struct auich_softc *sc = v;
1129 : struct auich_dma *p;
1130 : size_t size;
1131 : #ifdef AUICH_DEBUG
1132 : uint16_t sts;
1133 : sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1134 : AUICH_PCMO + sc->sc_sts_reg);
1135 : DPRINTF(AUICH_DEBUG_DMA,
1136 : ("auich_trigger_output(%p, %p, %d, %p, %p, %p) sts=%b\n",
1137 : start, end, blksize, intr, arg, param, sts, AUICH_ISTS_BITS));
1138 : #endif
1139 :
1140 0 : if (sc->sc_pdma->addr == start)
1141 : p = sc->sc_pdma;
1142 : else
1143 0 : return -1;
1144 :
1145 0 : size = (size_t)((caddr_t)end - (caddr_t)start);
1146 0 : sc->pcmo.size = size;
1147 0 : sc->pcmo.intr = intr;
1148 0 : sc->pcmo.arg = arg;
1149 :
1150 : /*
1151 : * The logic behind this is:
1152 : * setup one buffer to play, then LVI dump out the rest
1153 : * to the scatter-gather chain.
1154 : */
1155 0 : sc->pcmo.start = p->segs->ds_addr;
1156 0 : sc->pcmo.p = sc->pcmo.start;
1157 0 : sc->pcmo.end = sc->pcmo.start + size;
1158 0 : sc->pcmo.blksize = blksize;
1159 :
1160 0 : mtx_enter(&audio_lock);
1161 0 : bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMO + AUICH_BDBAR,
1162 : sc->sc_cddma + AUICH_PCMO_OFF(0));
1163 0 : auich_trigger_pipe(sc, AUICH_PCMO, &sc->pcmo);
1164 0 : mtx_leave(&audio_lock);
1165 0 : return 0;
1166 0 : }
1167 :
1168 : int
1169 0 : auich_trigger_input(void *v, void *start, void *end, int blksize,
1170 : void (*intr)(void *), void *arg, struct audio_params *param)
1171 : {
1172 0 : struct auich_softc *sc = v;
1173 : struct auich_dma *p;
1174 : size_t size;
1175 :
1176 : DPRINTF(AUICH_DEBUG_DMA,
1177 : ("auich_trigger_input(%p, %p, %d, %p, %p, %p) sts=%b\n",
1178 : start, end, blksize, intr, arg, param,
1179 : bus_space_read_2(sc->iot, sc->aud_ioh,
1180 : AUICH_PCMI + sc->sc_sts_reg),
1181 : AUICH_ISTS_BITS));
1182 :
1183 0 : if (sc->sc_rdma->addr == start)
1184 : p = sc->sc_rdma;
1185 : else
1186 0 : return -1;
1187 :
1188 0 : size = (size_t)((caddr_t)end - (caddr_t)start);
1189 0 : sc->pcmi.size = size;
1190 0 : sc->pcmi.intr = intr;
1191 0 : sc->pcmi.arg = arg;
1192 :
1193 : /*
1194 : * The logic behind this is:
1195 : * setup one buffer to play, then LVI dump out the rest
1196 : * to the scatter-gather chain.
1197 : */
1198 0 : sc->pcmi.start = p->segs->ds_addr;
1199 0 : sc->pcmi.p = sc->pcmi.start;
1200 0 : sc->pcmi.end = sc->pcmi.start + size;
1201 0 : sc->pcmi.blksize = blksize;
1202 0 : mtx_enter(&audio_lock);
1203 0 : bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR,
1204 : sc->sc_cddma + AUICH_PCMI_OFF(0));
1205 0 : auich_trigger_pipe(sc, AUICH_PCMI, &sc->pcmi);
1206 0 : mtx_leave(&audio_lock);
1207 0 : return 0;
1208 0 : }
1209 :
1210 :
1211 : int
1212 0 : auich_allocmem(struct auich_softc *sc, size_t size, size_t align,
1213 : struct auich_dma *p)
1214 : {
1215 : int error;
1216 :
1217 0 : p->size = size;
1218 0 : error = bus_dmamem_alloc(sc->dmat, p->size, align, 0, p->segs, 1,
1219 : &p->nsegs, BUS_DMA_NOWAIT);
1220 0 : if (error) {
1221 : DPRINTF(AUICH_DEBUG_DMA,
1222 : ("%s: bus_dmamem_alloc failed: error %d\n",
1223 : sc->sc_dev.dv_xname, error));
1224 0 : return error;
1225 : }
1226 :
1227 0 : error = bus_dmamem_map(sc->dmat, p->segs, 1, p->size, &p->addr,
1228 : BUS_DMA_NOWAIT | sc->sc_dmamap_flags);
1229 0 : if (error) {
1230 : DPRINTF(AUICH_DEBUG_DMA,
1231 : ("%s: bus_dmamem_map failed: error %d\n",
1232 : sc->sc_dev.dv_xname, error));
1233 : goto free;
1234 : }
1235 :
1236 0 : error = bus_dmamap_create(sc->dmat, p->size, 1, p->size, 0,
1237 : BUS_DMA_NOWAIT, &p->map);
1238 0 : if (error) {
1239 : DPRINTF(AUICH_DEBUG_DMA,
1240 : ("%s: bus_dmamap_create failed: error %d\n",
1241 : sc->sc_dev.dv_xname, error));
1242 : goto unmap;
1243 : }
1244 :
1245 0 : error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, NULL,
1246 : BUS_DMA_NOWAIT);
1247 0 : if (error) {
1248 : DPRINTF(AUICH_DEBUG_DMA,
1249 : ("%s: bus_dmamap_load failed: error %d\n",
1250 : sc->sc_dev.dv_xname, error));
1251 : goto destroy;
1252 : }
1253 0 : return 0;
1254 :
1255 : destroy:
1256 0 : bus_dmamap_destroy(sc->dmat, p->map);
1257 : unmap:
1258 0 : bus_dmamem_unmap(sc->dmat, p->addr, p->size);
1259 : free:
1260 0 : bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
1261 0 : return error;
1262 0 : }
1263 :
1264 :
1265 : int
1266 0 : auich_freemem(struct auich_softc *sc, struct auich_dma *p)
1267 : {
1268 0 : bus_dmamap_unload(sc->dmat, p->map);
1269 0 : bus_dmamap_destroy(sc->dmat, p->map);
1270 0 : bus_dmamem_unmap(sc->dmat, p->addr, p->size);
1271 0 : bus_dmamem_free(sc->dmat, p->segs, p->nsegs);
1272 0 : return 0;
1273 : }
1274 :
1275 :
1276 :
1277 : int
1278 0 : auich_alloc_cdata(struct auich_softc *sc)
1279 : {
1280 0 : bus_dma_segment_t seg;
1281 0 : int error, rseg;
1282 :
1283 : /*
1284 : * Allocate the control data structure, and create and load the
1285 : * DMA map for it.
1286 : */
1287 0 : if ((error = bus_dmamem_alloc(sc->dmat, sizeof(struct auich_cdata),
1288 0 : PAGE_SIZE, 0, &seg, 1, &rseg, 0)) != 0) {
1289 0 : printf("%s: unable to allocate control data, error = %d\n",
1290 0 : sc->sc_dev.dv_xname, error);
1291 0 : goto fail_0;
1292 : }
1293 :
1294 0 : if ((error = bus_dmamem_map(sc->dmat, &seg, 1,
1295 : sizeof(struct auich_cdata), (caddr_t *) &sc->sc_cdata,
1296 0 : sc->sc_dmamap_flags)) != 0) {
1297 0 : printf("%s: unable to map control data, error = %d\n",
1298 0 : sc->sc_dev.dv_xname, error);
1299 0 : goto fail_1;
1300 : }
1301 :
1302 0 : if ((error = bus_dmamap_create(sc->dmat, sizeof(struct auich_cdata), 1,
1303 0 : sizeof(struct auich_cdata), 0, 0, &sc->sc_cddmamap)) != 0) {
1304 0 : printf("%s: unable to create control data DMA map, "
1305 0 : "error = %d\n", sc->sc_dev.dv_xname, error);
1306 0 : goto fail_2;
1307 : }
1308 :
1309 0 : if ((error = bus_dmamap_load(sc->dmat, sc->sc_cddmamap, sc->sc_cdata,
1310 0 : sizeof(struct auich_cdata), NULL, 0)) != 0) {
1311 0 : printf("%s: unable tp load control data DMA map, "
1312 0 : "error = %d\n", sc->sc_dev.dv_xname, error);
1313 : goto fail_3;
1314 : }
1315 :
1316 0 : sc->pcmo.dmalist = sc->sc_cdata->ic_dmalist_pcmo;
1317 0 : sc->pcmi.dmalist = sc->sc_cdata->ic_dmalist_pcmi;
1318 0 : sc->mici.dmalist = sc->sc_cdata->ic_dmalist_mici;
1319 :
1320 0 : return 0;
1321 :
1322 : fail_3:
1323 0 : bus_dmamap_destroy(sc->dmat, sc->sc_cddmamap);
1324 : fail_2:
1325 0 : bus_dmamem_unmap(sc->dmat, (caddr_t) sc->sc_cdata,
1326 : sizeof(struct auich_cdata));
1327 : fail_1:
1328 0 : bus_dmamem_free(sc->dmat, &seg, rseg);
1329 : fail_0:
1330 0 : return error;
1331 0 : }
1332 :
1333 : void
1334 0 : auich_resume(struct auich_softc *sc)
1335 : {
1336 : /* SiS 7012 needs special handling */
1337 0 : if (PCI_VENDOR(sc->pci_id) == PCI_VENDOR_SIS &&
1338 0 : PCI_PRODUCT(sc->pci_id) == PCI_PRODUCT_SIS_7012_ACA) {
1339 : /* un-mute output */
1340 0 : bus_space_write_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL,
1341 : bus_space_read_4(sc->iot, sc->aud_ioh, ICH_SIS_NV_CTL) |
1342 : ICH_SIS_CTL_UNMUTE);
1343 0 : }
1344 :
1345 0 : ac97_resume(&sc->host_if, sc->codec_if);
1346 0 : }
1347 :
1348 : /* -------------------------------------------------------------------- */
1349 : /* Calibrate card (some boards are overclocked and need scaling) */
1350 :
1351 : unsigned int
1352 0 : auich_calibrate(struct auich_softc *sc)
1353 : {
1354 0 : struct timeval t1, t2;
1355 : u_int8_t civ, ociv;
1356 : uint16_t sts, osts;
1357 : u_int32_t wait_us, actual_48k_rate, bytes, ac97rate;
1358 : void *temp_buffer;
1359 : struct auich_dma *p;
1360 :
1361 : ac97rate = AUICH_FIXED_RATE;
1362 : /*
1363 : * Grab audio from input for fixed interval and compare how
1364 : * much we actually get with what we expect. Interval needs
1365 : * to be sufficiently short that no interrupts are
1366 : * generated.
1367 : * XXX: Is this true? We don't request any interrupts,
1368 : * so why should the chip issue any?
1369 : */
1370 :
1371 : /* Setup a buffer */
1372 : bytes = 16000;
1373 0 : temp_buffer = auich_allocm(sc, 0, bytes, M_DEVBUF, M_NOWAIT);
1374 0 : if (temp_buffer == NULL)
1375 0 : return (ac97rate);
1376 0 : if (sc->sc_cdma->addr == temp_buffer) {
1377 : p = sc->sc_cdma;
1378 : } else {
1379 0 : printf("auich_calibrate: bad address %p\n", temp_buffer);
1380 0 : return (ac97rate);
1381 : }
1382 :
1383 : /* get current CIV (usually 0 after reboot) */
1384 0 : ociv = civ = bus_space_read_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CIV);
1385 0 : sc->pcmi.dmalist[civ].base = p->map->dm_segs[0].ds_addr;
1386 0 : sc->pcmi.dmalist[civ].len = bytes / sc->sc_sample_size;
1387 :
1388 :
1389 : /*
1390 : * our data format is stereo, 16 bit so each sample is 4 bytes.
1391 : * assuming we get 48000 samples per second, we get 192000 bytes/sec.
1392 : * we're going to start recording with interrupts disabled and measure
1393 : * the time taken for one block to complete. we know the block size,
1394 : * we know the time in microseconds, we calculate the sample rate:
1395 : *
1396 : * actual_rate [bps] = bytes / (time [s] * 4)
1397 : * actual_rate [bps] = (bytes * 1000000) / (time [us] * 4)
1398 : * actual_rate [Hz] = (bytes * 250000) / time [us]
1399 : */
1400 :
1401 : /* prepare */
1402 0 : bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_BDBAR,
1403 : sc->sc_cddma + AUICH_PCMI_OFF(0));
1404 : /* we got only one valid sample, so set LVI to CIV
1405 : * otherwise we provoke a AUICH_FIFOE FIFO error
1406 : * which will confuse the chip later on. */
1407 0 : bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_LVI,
1408 : civ & AUICH_LVI_MASK);
1409 :
1410 : /* start, but don't request any interupts */
1411 0 : microuptime(&t1);
1412 0 : bus_space_write_1(sc->iot, sc->aud_ioh, AUICH_PCMI + AUICH_CTRL,
1413 : AUICH_RPBM);
1414 :
1415 : /* XXX remove this sometime */
1416 0 : osts = bus_space_read_2(sc->iot, sc->aud_ioh,
1417 : AUICH_PCMI + sc->sc_sts_reg);
1418 : /* wait */
1419 0 : while(1) {
1420 0 : microuptime(&t2);
1421 0 : sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1422 : AUICH_PCMI + sc->sc_sts_reg);
1423 0 : civ = bus_space_read_1(sc->iot, sc->aud_ioh,
1424 : AUICH_PCMI + AUICH_CIV);
1425 :
1426 : /* turn time delta into us */
1427 0 : wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) +
1428 0 : t2.tv_usec - t1.tv_usec;
1429 :
1430 : /* this should actually never happen because civ==lvi */
1431 0 : if ((civ & AUICH_LVI_MASK) != (ociv & AUICH_LVI_MASK)) {
1432 0 : printf("%s: ac97 CIV progressed after %d us sts=%b civ=%u\n",
1433 0 : sc->sc_dev.dv_xname, wait_us, sts,
1434 : AUICH_ISTS_BITS, civ);
1435 : ociv = civ;
1436 0 : }
1437 : /* normal completion */
1438 0 : if (sts & (AUICH_DCH | AUICH_CELV | AUICH_LVBCI))
1439 : break;
1440 : /*
1441 : * check for strange changes in STS -
1442 : * XXX remove it when everythings fine
1443 : */
1444 0 : if (sts != osts) {
1445 0 : printf("%s: ac97 sts changed after %d us sts=%b civ=%u\n",
1446 0 : sc->sc_dev.dv_xname, wait_us, sts,
1447 : AUICH_ISTS_BITS, civ);
1448 : osts = sts;
1449 0 : }
1450 : /*
1451 : * timeout: we expect 83333 us for 48k sampling rate,
1452 : * 600000 us will be enough even for 8k sampling rate
1453 : */
1454 0 : if (wait_us > 600000) {
1455 0 : printf("%s: ac97 link rate timed out %d us sts=%b civ=%u\n",
1456 0 : sc->sc_dev.dv_xname, wait_us, sts,
1457 : AUICH_ISTS_BITS, civ);
1458 : /* reset and clean up*/
1459 0 : auich_halt_pipe(sc, AUICH_PCMI, &sc->pcmi);
1460 0 : auich_halt_pipe(sc, AUICH_MICI, &sc->mici);
1461 0 : auich_freem(sc, temp_buffer, M_DEVBUF);
1462 : /* return default sample rate */
1463 0 : return (ac97rate);
1464 : }
1465 : }
1466 :
1467 : DPRINTF(AUICH_DEBUG_CODECIO,
1468 : ("%s: ac97 link rate calibration took %d us sts=%b civ=%u\n",
1469 : sc->sc_dev.dv_xname, wait_us, sts, AUICH_ISTS_BITS, civ));
1470 :
1471 : /* reset and clean up */
1472 0 : auich_halt_pipe(sc, AUICH_PCMI, &sc->pcmi);
1473 0 : auich_halt_pipe(sc, AUICH_MICI, &sc->mici);
1474 0 : auich_freem(sc, temp_buffer, M_DEVBUF);
1475 :
1476 : #ifdef AUICH_DEBUG
1477 : sts = bus_space_read_2(sc->iot, sc->aud_ioh,
1478 : AUICH_PCMI + sc->sc_sts_reg);
1479 : civ = bus_space_read_4(sc->iot, sc->aud_ioh,
1480 : AUICH_PCMI + AUICH_CIV);
1481 : printf("%s: after calibration and reset sts=%b civ=%u\n",
1482 : sc->sc_dev.dv_xname, sts, AUICH_ISTS_BITS, civ);
1483 : #endif
1484 :
1485 : /* now finally calculate measured samplerate */
1486 0 : actual_48k_rate = (bytes * 250000) / wait_us;
1487 :
1488 0 : if (actual_48k_rate <= 48500)
1489 0 : ac97rate = AUICH_FIXED_RATE;
1490 : else
1491 : ac97rate = actual_48k_rate;
1492 :
1493 : DPRINTF(AUICH_DEBUG_CODECIO, ("%s: measured ac97 link rate at %d Hz",
1494 : sc->sc_dev.dv_xname, actual_48k_rate));
1495 : if (ac97rate != actual_48k_rate)
1496 : DPRINTF(AUICH_DEBUG_CODECIO, (", will use %d Hz", ac97rate));
1497 : DPRINTF(AUICH_DEBUG_CODECIO, ("\n"));
1498 :
1499 0 : return (ac97rate);
1500 0 : }
|