1 /* $OpenBSD: cs4281.c,v 1.16 2003/10/07 14:11:04 fgsch Exp $ */
2 /* $Tera: cs4281.c,v 1.18 2000/12/27 14:24:45 tacha Exp $ */
3
4 /*
5 * Copyright (c) 2000 Tatoku Ogaito. 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 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Tatoku Ogaito
18 * for the NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Cirrus Logic CS4281 driver.
36 * Data sheets can be found
37 * http://www.cirrus.com/pubs/4281.pdf?DocumentID=30
38 * ftp://ftp.alsa-project.org/pub/manuals/cirrus/cs4281tm.pdf
39 *
40 * TODO:
41 * 1: midi and FM support
42 */
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/malloc.h>
48 #include <sys/fcntl.h>
49 #include <sys/device.h>
50
51 #include <dev/pci/pcidevs.h>
52 #include <dev/pci/pcivar.h>
53 #include <dev/pci/cs4281reg.h>
54
55 #include <sys/audioio.h>
56 #include <dev/audio_if.h>
57 #include <dev/midi_if.h>
58 #include <dev/mulaw.h>
59 #include <dev/auconv.h>
60
61 #include <dev/ic/ac97.h>
62
63 #include <machine/bus.h>
64
65 #define CSCC_PCI_BA0 0x10
66 #define CSCC_PCI_BA1 0x14
67
68 struct cs4281_dma {
69 bus_dmamap_t map;
70 caddr_t addr; /* real dma buffer */
71 caddr_t dum; /* dummy buffer for audio driver */
72 bus_dma_segment_t segs[1];
73 int nsegs;
74 size_t size;
75 struct cs4281_dma *next;
76 };
77 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
78 #define BUFADDR(p) ((void *)((p)->dum))
79 #define KERNADDR(p) ((void *)((p)->addr))
80
81 /*
82 * Software state
83 */
84 struct cs4281_softc {
85 struct device sc_dev;
86
87 pci_intr_handle_t *sc_ih;
88
89 /* I/O (BA0) */
90 bus_space_tag_t ba0t;
91 bus_space_handle_t ba0h;
92
93 /* BA1 */
94 bus_space_tag_t ba1t;
95 bus_space_handle_t ba1h;
96
97 /* DMA */
98 bus_dma_tag_t sc_dmatag;
99 struct cs4281_dma *sc_dmas;
100 size_t dma_size;
101 size_t dma_align;
102
103 int hw_blocksize;
104
105 /* playback */
106 void (*sc_pintr)(void *); /* dma completion intr handler */
107 void *sc_parg; /* arg for sc_intr() */
108 char *sc_ps, *sc_pe, *sc_pn;
109 int sc_pcount;
110 int sc_pi;
111 struct cs4281_dma *sc_pdma;
112 char *sc_pbuf;
113 int (*halt_output)(void *);
114 #ifdef DIAGNOSTIC
115 char sc_prun;
116 #endif
117
118 /* capturing */
119 void (*sc_rintr)(void *); /* dma completion intr handler */
120 void *sc_rarg; /* arg for sc_intr() */
121 char *sc_rs, *sc_re, *sc_rn;
122 int sc_rcount;
123 int sc_ri;
124 struct cs4281_dma *sc_rdma;
125 char *sc_rbuf;
126 int sc_rparam; /* record format */
127 int (*halt_input)(void *);
128 #ifdef DIAGNOSTIC
129 char sc_rrun;
130 #endif
131
132 #if NMIDI > 0
133 void (*sc_iintr)(void *, int); /* midi input ready handler */
134 void (*sc_ointr)(void *); /* midi output ready handler */
135 void *sc_arg;
136 #endif
137
138 /* AC97 CODEC */
139 struct ac97_codec_if *codec_if;
140 struct ac97_host_if host_if;
141
142 /* Power Management */
143 char sc_suspend;
144 void *sc_powerhook; /* Power hook */
145 u_int16_t ac97_reg[CS4281_SAVE_REG_MAX + 1]; /* Save ac97 registers */
146 };
147
148 #define BA0READ4(sc, r) bus_space_read_4((sc)->ba0t, (sc)->ba0h, (r))
149 #define BA0WRITE4(sc, r, x) bus_space_write_4((sc)->ba0t, (sc)->ba0h, (r), (x))
150
151 #if defined(ENABLE_SECONDARY_CODEC)
152 #define MAX_CHANNELS (4)
153 #define MAX_FIFO_SIZE 32 /* 128/4 channels */
154 #else
155 #define MAX_CHANNELS (2)
156 #define MAX_FIFO_SIZE 64 /* 128/2 channels */
157 #endif
158
159 int cs4281_match(struct device *, void *, void *);
160 void cs4281_attach(struct device *, struct device *, void *);
161 int cs4281_intr(void *);
162 int cs4281_query_encoding(void *, struct audio_encoding *);
163 int cs4281_set_params(void *, int, int, struct audio_params *,
164 struct audio_params *);
165 int cs4281_halt_output(void *);
166 int cs4281_halt_input(void *);
167 int cs4281_getdev(void *, struct audio_device *);
168 int cs4281_trigger_output(void *, void *, void *, int, void (*)(void *),
169 void *, struct audio_params *);
170 int cs4281_trigger_input(void *, void *, void *, int, void (*)(void *),
171 void *, struct audio_params *);
172 u_int8_t cs4281_sr2regval(int);
173 void cs4281_set_dac_rate(struct cs4281_softc *, int);
174 void cs4281_set_adc_rate(struct cs4281_softc *, int);
175 int cs4281_init(struct cs4281_softc *);
176
177 int cs4281_open(void *, int);
178 void cs4281_close(void *);
179 int cs4281_round_blocksize(void *, int);
180 int cs4281_get_props(void *);
181 int cs4281_attach_codec(void *, struct ac97_codec_if *);
182 int cs4281_read_codec(void *, u_int8_t , u_int16_t *);
183 int cs4281_write_codec(void *, u_int8_t, u_int16_t);
184 void cs4281_reset_codec(void *);
185
186 void cs4281_power(int, void *);
187
188 int cs4281_mixer_set_port(void *, mixer_ctrl_t *);
189 int cs4281_mixer_get_port(void *, mixer_ctrl_t *);
190 int cs4281_query_devinfo(void *, mixer_devinfo_t *);
191 void *cs4281_malloc(void *, int, size_t, int, int);
192 size_t cs4281_round_buffersize(void *, int, size_t);
193 void cs4281_free(void *, void *, int);
194 paddr_t cs4281_mappage(void *, void *, off_t, int);
195
196 int cs4281_allocmem(struct cs4281_softc *, size_t, int, int,
197 struct cs4281_dma *);
198 int cs4281_src_wait(struct cs4281_softc *);
199
200 #if defined(CS4281_DEBUG)
201 #undef DPRINTF
202 #undef DPRINTFN
203 #define DPRINTF(x) if (cs4281_debug) printf x
204 #define DPRINTFN(n,x) if (cs4281_debug>(n)) printf x
205 int cs4281_debug = 5;
206 #else
207 #define DPRINTF(x)
208 #define DPRINTFN(n,x)
209 #endif
210
211 struct audio_hw_if cs4281_hw_if = {
212 cs4281_open,
213 cs4281_close,
214 NULL,
215 cs4281_query_encoding,
216 cs4281_set_params,
217 cs4281_round_blocksize,
218 NULL,
219 NULL,
220 NULL,
221 NULL,
222 NULL,
223 cs4281_halt_output,
224 cs4281_halt_input,
225 NULL,
226 cs4281_getdev,
227 NULL,
228 cs4281_mixer_set_port,
229 cs4281_mixer_get_port,
230 cs4281_query_devinfo,
231 cs4281_malloc,
232 cs4281_free,
233 cs4281_round_buffersize,
234 NULL, /* cs4281_mappage, */
235 cs4281_get_props,
236 cs4281_trigger_output,
237 cs4281_trigger_input,
238 };
239
240 #if NMIDI > 0
241 /* Midi Interface */
242 void cs4281_midi_close(void *);
243 void cs4281_midi_getinfo(void *, struct midi_info *);
244 int cs4281_midi_open(void *, int, void (*)(void *, int),
245 void (*)(void *), void *);
246 int cs4281_midi_output(void *, int);
247
248 struct midi_hw_if cs4281_midi_hw_if = {
249 cs4281_midi_open,
250 cs4281_midi_close,
251 cs4281_midi_output,
252 cs4281_midi_getinfo,
253 0,
254 };
255 #endif
256
257 struct cfattach clct_ca = {
258 sizeof(struct cs4281_softc), cs4281_match, cs4281_attach
259 };
260
261 struct cfdriver clct_cd = {
262 NULL, "clct", DV_DULL
263 };
264
265 struct audio_device cs4281_device = {
266 "CS4281",
267 "",
268 "cs4281"
269 };
270
271
272 int
cs4281_match(parent,match,aux)273 cs4281_match(parent, match, aux)
274 struct device *parent;
275 void *match;
276 void *aux;
277 {
278 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
279
280 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS ||
281 PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_CIRRUS_CS4281)
282 return (0);
283
284 return (1);
285 }
286
287 void
cs4281_attach(parent,self,aux)288 cs4281_attach(parent, self, aux)
289 struct device *parent;
290 struct device *self;
291 void *aux;
292 {
293 struct cs4281_softc *sc = (struct cs4281_softc *)self;
294 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
295 pci_chipset_tag_t pc = pa->pa_pc;
296 char const *intrstr;
297 pci_intr_handle_t ih;
298 pcireg_t csr;
299 int pci_pwrmgmt_cap_reg, pci_pwrmgmt_csr_reg;
300
301 /* Map I/O register */
302 if (pci_mapreg_map(pa, CSCC_PCI_BA0,
303 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba0t,
304 &sc->ba0h, NULL, NULL, 0)) {
305 printf("%s: can't map BA0 space\n", sc->sc_dev.dv_xname);
306 return;
307 }
308 if (pci_mapreg_map(pa, CSCC_PCI_BA1,
309 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba1t,
310 &sc->ba1h, NULL, NULL, 0)) {
311 printf("%s: can't map BA1 space\n", sc->sc_dev.dv_xname);
312 return;
313 }
314
315 sc->sc_dmatag = pa->pa_dmat;
316
317 /*
318 * Set Power State D0.
319 * Without doing this, 0xffffffff is read from all registers after
320 * using Windows and rebooting into OpenBSD.
321 * On my IBM ThinkPad X20, it is set to D3 after using Windows2000.
322 */
323 if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
324 &pci_pwrmgmt_cap_reg, 0)) {
325 pcireg_t reg;
326
327 pci_pwrmgmt_csr_reg = pci_pwrmgmt_cap_reg + PCI_PMCSR;
328 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, pci_pwrmgmt_csr_reg);
329 if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) {
330 pci_conf_write(pc, pa->pa_tag, pci_pwrmgmt_csr_reg,
331 (reg & ~PCI_PMCSR_STATE_MASK) |
332 PCI_PMCSR_STATE_D0);
333 }
334 }
335
336 /* Enable the device (set bus master flag) */
337 csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
338 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
339 csr | PCI_COMMAND_MASTER_ENABLE);
340
341 /* Map and establish the interrupt. */
342 if (pci_intr_map(pa, &ih)) {
343 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
344 return;
345 }
346 intrstr = pci_intr_string(pc, ih);
347
348 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, cs4281_intr, sc,
349 sc->sc_dev.dv_xname);
350 if (sc->sc_ih == NULL) {
351 printf("%s: couldn't establish interrupt",sc->sc_dev.dv_xname);
352 if (intrstr != NULL)
353 printf(" at %s", intrstr);
354 printf("\n");
355 return;
356 }
357 printf(" %s\n", intrstr);
358
359 /*
360 * Sound System start-up
361 */
362 if (cs4281_init(sc) != 0)
363 return;
364
365 sc->halt_input = cs4281_halt_input;
366 sc->halt_output = cs4281_halt_output;
367
368 sc->dma_size = CS4281_BUFFER_SIZE / MAX_CHANNELS;
369 sc->dma_align = 0x10;
370 sc->hw_blocksize = sc->dma_size / 2;
371
372 /* AC 97 attachment */
373 sc->host_if.arg = sc;
374 sc->host_if.attach = cs4281_attach_codec;
375 sc->host_if.read = cs4281_read_codec;
376 sc->host_if.write = cs4281_write_codec;
377 sc->host_if.reset = cs4281_reset_codec;
378 if (ac97_attach(&sc->host_if) != 0) {
379 printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname);
380 return;
381 }
382 audio_attach_mi(&cs4281_hw_if, sc, &sc->sc_dev);
383
384 #if NMIDI > 0
385 midi_attach_mi(&cs4281_midi_hw_if, sc, &sc->sc_dev);
386 #endif
387
388 sc->sc_suspend = PWR_RESUME;
389 sc->sc_powerhook = powerhook_establish(cs4281_power, sc);
390 }
391
392
393 int
cs4281_intr(p)394 cs4281_intr(p)
395 void *p;
396 {
397 struct cs4281_softc *sc = p;
398 u_int32_t intr, val;
399 char *empty_dma;
400
401 intr = BA0READ4(sc, CS4281_HISR);
402 if (!(intr & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) {
403 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
404 return (0);
405 }
406 DPRINTF(("cs4281_intr:"));
407
408 if (intr & HISR_DMA0)
409 val = BA0READ4(sc, CS4281_HDSR0); /* clear intr condition */
410 if (intr & HISR_DMA1)
411 val = BA0READ4(sc, CS4281_HDSR1); /* clear intr condition */
412 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
413
414 /* Playback Interrupt */
415 if (intr & HISR_DMA0) {
416 DPRINTF((" PB DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA0),
417 (int)BA0READ4(sc, CS4281_DCC0)));
418 if (sc->sc_pintr) {
419 if ((sc->sc_pi%sc->sc_pcount) == 0)
420 sc->sc_pintr(sc->sc_parg);
421 } else {
422 printf("unexpected play intr\n");
423 }
424 /* copy buffer */
425 ++sc->sc_pi;
426 empty_dma = sc->sc_pdma->addr;
427 if (sc->sc_pi&1)
428 empty_dma += sc->hw_blocksize;
429 memcpy(empty_dma, sc->sc_pn, sc->hw_blocksize);
430 sc->sc_pn += sc->hw_blocksize;
431 if (sc->sc_pn >= sc->sc_pe)
432 sc->sc_pn = sc->sc_ps;
433 }
434 if (intr & HISR_DMA1) {
435 val = BA0READ4(sc, CS4281_HDSR1);
436 /* copy from dma */
437 DPRINTF((" CP DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA1),
438 (int)BA0READ4(sc, CS4281_DCC1)));
439 ++sc->sc_ri;
440 empty_dma = sc->sc_rdma->addr;
441 if ((sc->sc_ri & 1) == 0)
442 empty_dma += sc->hw_blocksize;
443 memcpy(sc->sc_rn, empty_dma, sc->hw_blocksize);
444 if (sc->sc_rn >= sc->sc_re)
445 sc->sc_rn = sc->sc_rs;
446 if (sc->sc_rintr) {
447 if ((sc->sc_ri % sc->sc_rcount) == 0)
448 sc->sc_rintr(sc->sc_rarg);
449 } else {
450 printf("unexpected record intr\n");
451 }
452 }
453 DPRINTF(("\n"));
454 return (1);
455 }
456
457 int
cs4281_query_encoding(addr,fp)458 cs4281_query_encoding(addr, fp)
459 void *addr;
460 struct audio_encoding *fp;
461 {
462 switch (fp->index) {
463 case 0:
464 strlcpy(fp->name, AudioEulinear, sizeof fp->name);
465 fp->encoding = AUDIO_ENCODING_ULINEAR;
466 fp->precision = 8;
467 fp->flags = 0;
468 break;
469 case 1:
470 strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
471 fp->encoding = AUDIO_ENCODING_ULAW;
472 fp->precision = 8;
473 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
474 break;
475 case 2:
476 strlcpy(fp->name, AudioEalaw, sizeof fp->name);
477 fp->encoding = AUDIO_ENCODING_ALAW;
478 fp->precision = 8;
479 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
480 break;
481 case 3:
482 strlcpy(fp->name, AudioEslinear, sizeof fp->name);
483 fp->encoding = AUDIO_ENCODING_SLINEAR;
484 fp->precision = 8;
485 fp->flags = 0;
486 break;
487 case 4:
488 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
489 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
490 fp->precision = 16;
491 fp->flags = 0;
492 break;
493 case 5:
494 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
495 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
496 fp->precision = 16;
497 fp->flags = 0;
498 break;
499 case 6:
500 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
501 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
502 fp->precision = 16;
503 fp->flags = 0;
504 break;
505 case 7:
506 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
507 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
508 fp->precision = 16;
509 fp->flags = 0;
510 break;
511 default:
512 return EINVAL;
513 }
514 return (0);
515 }
516
517 int
cs4281_set_params(addr,setmode,usemode,play,rec)518 cs4281_set_params(addr, setmode, usemode, play, rec)
519 void *addr;
520 int setmode, usemode;
521 struct audio_params *play, *rec;
522 {
523 struct cs4281_softc *sc = addr;
524 struct audio_params *p;
525 int mode;
526
527 for (mode = AUMODE_RECORD; mode != -1;
528 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
529 if ((setmode & mode) == 0)
530 continue;
531
532 p = mode == AUMODE_PLAY ? play : rec;
533
534 if (p == play) {
535 DPRINTFN(5,("play: samp=%ld precision=%d channels=%d\n",
536 p->sample_rate, p->precision, p->channels));
537 if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
538 (p->precision != 8 && p->precision != 16) ||
539 (p->channels != 1 && p->channels != 2)) {
540 return (EINVAL);
541 }
542 } else {
543 DPRINTFN(5,("rec: samp=%ld precision=%d channels=%d\n",
544 p->sample_rate, p->precision, p->channels));
545 if (p->sample_rate < 6023 || p->sample_rate > 48000 ||
546 (p->precision != 8 && p->precision != 16) ||
547 (p->channels != 1 && p->channels != 2)) {
548 return (EINVAL);
549 }
550 }
551 p->factor = 1;
552 p->sw_code = 0;
553
554 switch (p->encoding) {
555 case AUDIO_ENCODING_SLINEAR_BE:
556 break;
557 case AUDIO_ENCODING_SLINEAR_LE:
558 break;
559 case AUDIO_ENCODING_ULINEAR_BE:
560 break;
561 case AUDIO_ENCODING_ULINEAR_LE:
562 break;
563 case AUDIO_ENCODING_ULAW:
564 if (mode == AUMODE_PLAY) {
565 p->sw_code = mulaw_to_slinear8;
566 } else {
567 p->sw_code = slinear8_to_mulaw;
568 }
569 break;
570 case AUDIO_ENCODING_ALAW:
571 if (mode == AUMODE_PLAY) {
572 p->sw_code = alaw_to_slinear8;
573 } else {
574 p->sw_code = slinear8_to_alaw;
575 }
576 break;
577 default:
578 return (EINVAL);
579 }
580 }
581
582 /* set sample rate */
583 cs4281_set_dac_rate(sc, play->sample_rate);
584 cs4281_set_adc_rate(sc, rec->sample_rate);
585 return (0);
586 }
587
588 int
cs4281_halt_output(addr)589 cs4281_halt_output(addr)
590 void *addr;
591 {
592 struct cs4281_softc *sc = addr;
593
594 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
595 #ifdef DIAGNOSTIC
596 sc->sc_prun = 0;
597 #endif
598 return (0);
599 }
600
601 int
cs4281_halt_input(addr)602 cs4281_halt_input(addr)
603 void *addr;
604 {
605 struct cs4281_softc *sc = addr;
606
607 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
608 #ifdef DIAGNOSTIC
609 sc->sc_rrun = 0;
610 #endif
611 return (0);
612 }
613
614 /* trivial */
615 int
cs4281_getdev(addr,retp)616 cs4281_getdev(addr, retp)
617 void *addr;
618 struct audio_device *retp;
619 {
620 *retp = cs4281_device;
621 return (0);
622 }
623
624
625 int
cs4281_trigger_output(addr,start,end,blksize,intr,arg,param)626 cs4281_trigger_output(addr, start, end, blksize, intr, arg, param)
627 void *addr;
628 void *start, *end;
629 int blksize;
630 void (*intr)(void *);
631 void *arg;
632 struct audio_params *param;
633 {
634 struct cs4281_softc *sc = addr;
635 u_int32_t fmt=0;
636 struct cs4281_dma *p;
637 int dma_count;
638
639 #ifdef DIAGNOSTIC
640 if (sc->sc_prun)
641 printf("cs4281_trigger_output: already running\n");
642 sc->sc_prun = 1;
643 #endif
644
645 DPRINTF(("cs4281_trigger_output: sc=%p start=%p end=%p "
646 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
647 sc->sc_pintr = intr;
648 sc->sc_parg = arg;
649
650 /* stop playback DMA */
651 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK);
652
653 DPRINTF(("param: precision=%d factor=%d channels=%d encoding=%d\n",
654 param->precision, param->factor, param->channels,
655 param->encoding));
656 for (p = sc->sc_dmas; p != NULL && BUFADDR(p) != start; p = p->next)
657 ;
658 if (p == NULL) {
659 printf("cs4281_trigger_output: bad addr %p\n", start);
660 return (EINVAL);
661 }
662
663 sc->sc_pcount = blksize / sc->hw_blocksize;
664 sc->sc_ps = (char *)start;
665 sc->sc_pe = (char *)end;
666 sc->sc_pdma = p;
667 sc->sc_pbuf = KERNADDR(p);
668 sc->sc_pi = 0;
669 sc->sc_pn = sc->sc_ps;
670 if (blksize >= sc->dma_size) {
671 sc->sc_pn = sc->sc_ps + sc->dma_size;
672 memcpy(sc->sc_pbuf, start, sc->dma_size);
673 ++sc->sc_pi;
674 } else {
675 sc->sc_pn = sc->sc_ps + sc->hw_blocksize;
676 memcpy(sc->sc_pbuf, start, sc->hw_blocksize);
677 }
678
679 dma_count = sc->dma_size;
680 if (param->precision * param->factor != 8)
681 dma_count /= 2; /* 16 bit */
682 if (param->channels > 1)
683 dma_count /= 2; /* Stereo */
684
685 DPRINTF(("cs4281_trigger_output: DMAADDR(p)=0x%x count=%d\n",
686 (int)DMAADDR(p), dma_count));
687 BA0WRITE4(sc, CS4281_DBA0, DMAADDR(p));
688 BA0WRITE4(sc, CS4281_DBC0, dma_count-1);
689
690 /* set playback format */
691 fmt = BA0READ4(sc, CS4281_DMR0) & ~DMRn_FMTMSK;
692 if (param->precision * param->factor == 8)
693 fmt |= DMRn_SIZE8;
694 if (param->channels == 1)
695 fmt |= DMRn_MONO;
696 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
697 param->encoding == AUDIO_ENCODING_SLINEAR_BE)
698 fmt |= DMRn_BEND;
699 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
700 param->encoding == AUDIO_ENCODING_ULINEAR_LE)
701 fmt |= DMRn_USIGN;
702 BA0WRITE4(sc, CS4281_DMR0, fmt);
703
704 /* set sample rate */
705 cs4281_set_dac_rate(sc, param->sample_rate);
706
707 /* start DMA */
708 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) & ~DCRn_MSK);
709 /* Enable interrupts */
710 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
711
712 BA0WRITE4(sc, CS4281_PPRVC, 7);
713 BA0WRITE4(sc, CS4281_PPLVC, 7);
714
715 DPRINTF(("HICR =0x%08x(expected 0x00000001)\n", BA0READ4(sc, CS4281_HICR)));
716 DPRINTF(("HIMR =0x%08x(expected 0x00f0fc3f)\n", BA0READ4(sc, CS4281_HIMR)));
717 DPRINTF(("DMR0 =0x%08x(expected 0x2???0018)\n", BA0READ4(sc, CS4281_DMR0)));
718 DPRINTF(("DCR0 =0x%08x(expected 0x00030000)\n", BA0READ4(sc, CS4281_DCR0)));
719 DPRINTF(("FCR0 =0x%08x(expected 0x81000f00)\n", BA0READ4(sc, CS4281_FCR0)));
720 DPRINTF(("DACSR=0x%08x(expected 1 for 44kHz 5 for 8kHz)\n",
721 BA0READ4(sc, CS4281_DACSR)));
722 DPRINTF(("SRCSA=0x%08x(expected 0x0b0a0100)\n", BA0READ4(sc, CS4281_SRCSA)));
723 DPRINTF(("SSPM&SSPM_PSRCEN =0x%08x(expected 0x00000010)\n",
724 BA0READ4(sc, CS4281_SSPM) & SSPM_PSRCEN));
725
726 return (0);
727 }
728
729 int
cs4281_trigger_input(addr,start,end,blksize,intr,arg,param)730 cs4281_trigger_input(addr, start, end, blksize, intr, arg, param)
731 void *addr;
732 void *start, *end;
733 int blksize;
734 void (*intr)(void *);
735 void *arg;
736 struct audio_params *param;
737 {
738 struct cs4281_softc *sc = addr;
739 struct cs4281_dma *p;
740 u_int32_t fmt=0;
741 int dma_count;
742
743 printf("cs4281_trigger_input: not implemented yet\n");
744 #ifdef DIAGNOSTIC
745 if (sc->sc_rrun)
746 printf("cs4281_trigger_input: already running\n");
747 sc->sc_rrun = 1;
748 #endif
749 DPRINTF(("cs4281_trigger_input: sc=%p start=%p end=%p "
750 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
751 sc->sc_rintr = intr;
752 sc->sc_rarg = arg;
753
754 /* stop recording DMA */
755 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK);
756
757 for (p = sc->sc_dmas; p && BUFADDR(p) != start; p = p->next)
758 ;
759 if (!p) {
760 printf("cs4281_trigger_input: bad addr %p\n", start);
761 return (EINVAL);
762 }
763
764 sc->sc_rcount = blksize / sc->hw_blocksize;
765 sc->sc_rs = (char *)start;
766 sc->sc_re = (char *)end;
767 sc->sc_rdma = p;
768 sc->sc_rbuf = KERNADDR(p);
769 sc->sc_ri = 0;
770 sc->sc_rn = sc->sc_rs;
771
772 dma_count = sc->dma_size;
773 if (param->precision * param->factor == 8)
774 dma_count /= 2;
775 if (param->channels > 1)
776 dma_count /= 2;
777
778 DPRINTF(("cs4281_trigger_input: DMAADDR(p)=0x%x count=%d\n",
779 (int)DMAADDR(p), dma_count));
780 BA0WRITE4(sc, CS4281_DBA1, DMAADDR(p));
781 BA0WRITE4(sc, CS4281_DBC1, dma_count-1);
782
783 /* set recording format */
784 fmt = BA0READ4(sc, CS4281_DMR1) & ~DMRn_FMTMSK;
785 if (param->precision * param->factor == 8)
786 fmt |= DMRn_SIZE8;
787 if (param->channels == 1)
788 fmt |= DMRn_MONO;
789 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
790 param->encoding == AUDIO_ENCODING_SLINEAR_BE)
791 fmt |= DMRn_BEND;
792 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE ||
793 param->encoding == AUDIO_ENCODING_ULINEAR_LE)
794 fmt |= DMRn_USIGN;
795 BA0WRITE4(sc, CS4281_DMR1, fmt);
796
797 /* set sample rate */
798 cs4281_set_adc_rate(sc, param->sample_rate);
799
800 /* Start DMA */
801 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) & ~DCRn_MSK);
802 /* Enable interrupts */
803 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM);
804
805 DPRINTF(("HICR=0x%08x\n", BA0READ4(sc, CS4281_HICR)));
806 DPRINTF(("HIMR=0x%08x\n", BA0READ4(sc, CS4281_HIMR)));
807 DPRINTF(("DMR1=0x%08x\n", BA0READ4(sc, CS4281_DMR1)));
808 DPRINTF(("DCR1=0x%08x\n", BA0READ4(sc, CS4281_DCR1)));
809
810 return (0);
811 }
812
813 /* convert sample rate to register value */
814 u_int8_t
cs4281_sr2regval(rate)815 cs4281_sr2regval(rate)
816 int rate;
817 {
818 u_int8_t retval;
819
820 /* We don't have to change here. but anyway ... */
821 if (rate > 48000)
822 rate = 48000;
823 if (rate < 6023)
824 rate = 6023;
825
826 switch (rate) {
827 case 8000:
828 retval = 5;
829 break;
830 case 11025:
831 retval = 4;
832 break;
833 case 16000:
834 retval = 3;
835 break;
836 case 22050:
837 retval = 2;
838 break;
839 case 44100:
840 retval = 1;
841 break;
842 case 48000:
843 retval = 0;
844 break;
845 default:
846 retval = 1536000/rate; /* == 24576000/(rate*16) */
847 }
848 return (retval);
849 }
850
851
852 void
cs4281_set_dac_rate(sc,rate)853 cs4281_set_dac_rate(sc, rate)
854 struct cs4281_softc *sc;
855 int rate;
856 {
857 BA0WRITE4(sc, CS4281_DACSR, cs4281_sr2regval(rate));
858 }
859
860 void
cs4281_set_adc_rate(sc,rate)861 cs4281_set_adc_rate(sc, rate)
862 struct cs4281_softc *sc;
863 int rate;
864 {
865 BA0WRITE4(sc, CS4281_ADCSR, cs4281_sr2regval(rate));
866 }
867
868 int
cs4281_init(sc)869 cs4281_init(sc)
870 struct cs4281_softc *sc;
871 {
872 int n;
873 u_int16_t data;
874 u_int32_t dat32;
875
876 /* set "Configuration Write Protect" register to
877 * 0x4281 to allow to write */
878 BA0WRITE4(sc, CS4281_CWPR, 0x4281);
879
880 /*
881 * Unset "Full Power-Down bit of Extended PCI Power Management
882 * Control" register to release the reset state.
883 */
884 dat32 = BA0READ4(sc, CS4281_EPPMC);
885 if (dat32 & EPPMC_FPDN)
886 BA0WRITE4(sc, CS4281_EPPMC, dat32 & ~EPPMC_FPDN);
887
888 /* Start PLL out in known state */
889 BA0WRITE4(sc, CS4281_CLKCR1, 0);
890 /* Start serial ports out in known state */
891 BA0WRITE4(sc, CS4281_SERMC, 0);
892
893 /* Reset codec */
894 BA0WRITE4(sc, CS4281_ACCTL, 0);
895 delay(50); /* delay 50us */
896
897 BA0WRITE4(sc, CS4281_SPMC, 0);
898 delay(100); /* delay 100us */
899 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
900 #if defined(ENABLE_SECONDARY_CODEC)
901 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
902 BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
903 #endif
904 delay(50000); /* XXX: delay 50ms */
905
906 /* Turn on Sound System clocks based on ABITCLK */
907 BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_DLLP);
908 delay(50000); /* XXX: delay 50ms */
909 BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_SWCE | CLKCR1_DLLP);
910
911 /* Set enables for sections that are needed in the SSPM registers */
912 BA0WRITE4(sc, CS4281_SSPM,
913 SSPM_MIXEN | /* Mixer */
914 SSPM_CSRCEN | /* Capture SRC */
915 SSPM_PSRCEN | /* Playback SRC */
916 SSPM_JSEN | /* Joystick */
917 SSPM_ACLEN | /* AC LINK */
918 SSPM_FMEN /* FM */
919 );
920
921 /* Wait for clock stabilization */
922 n = 0;
923 while ((BA0READ4(sc, CS4281_CLKCR1)& (CLKCR1_DLLRDY | CLKCR1_CLKON))
924 != (CLKCR1_DLLRDY | CLKCR1_CLKON)) {
925 delay(100);
926 if (++n > 1000)
927 return (-1);
928 }
929
930 /* Enable ASYNC generation */
931 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN);
932
933 /* Wait for Codec ready. Linux driver wait 50ms here */
934 n = 0;
935 while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) {
936 delay(100);
937 if (++n > 1000)
938 return (-1);
939 }
940
941 #if defined(ENABLE_SECONDARY_CODEC)
942 /* secondary codec ready*/
943 n = 0;
944 while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
945 delay(100);
946 if (++n > 1000)
947 return (-1);
948 }
949 #endif
950
951 /* Set the serial timing configuration */
952 /* XXX: undocumented but the Linux driver do this */
953 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
954
955 /* Wait for Codec ready signal */
956 n = 0;
957 do {
958 delay(1000);
959 if (++n > 1000) {
960 printf("%s: Timeout waiting for Codec ready\n",
961 sc->sc_dev.dv_xname);
962 return -1;
963 }
964 dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY;
965 } while (dat32 == 0);
966
967 /* Enable Valid Frame output on ASDOUT */
968 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
969
970 /* Wait until Codec Calibration is finished. Codec register 26h */
971 n = 0;
972 do {
973 delay(1);
974 if (++n > 1000) {
975 printf("%s: Timeout waiting for Codec calibration\n",
976 sc->sc_dev.dv_xname);
977 return -1;
978 }
979 cs4281_read_codec(sc, AC97_REG_POWER, &data);
980 } while ((data & 0x0f) != 0x0f);
981
982 /* Set the serial timing configuration again */
983 /* XXX: undocumented but the Linux driver do this */
984 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
985
986 /* Wait until we've sampled input slots 3 & 4 as valid */
987 n = 0;
988 do {
989 delay(1000);
990 if (++n > 1000) {
991 printf("%s: Timeout waiting for sampled input slots as valid\n",
992 sc->sc_dev.dv_xname);
993 return -1;
994 }
995 dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4);
996 } while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
997
998 /* Start digital data transfer of audio data to the codec */
999 BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
1000
1001 cs4281_write_codec(sc, AC97_REG_HEADPHONE_VOLUME, 0);
1002 cs4281_write_codec(sc, AC97_REG_MASTER_VOLUME, 0);
1003
1004 /* Power on the DAC */
1005 cs4281_read_codec(sc, AC97_REG_POWER, &data);
1006 cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfdff);
1007
1008 /* Wait until we sample a DAC ready state.
1009 * Not documented, but Linux driver does.
1010 */
1011 for (n = 0; n < 32; ++n) {
1012 delay(1000);
1013 cs4281_read_codec(sc, AC97_REG_POWER, &data);
1014 if (data & 0x02)
1015 break;
1016 }
1017
1018 /* Power on the ADC */
1019 cs4281_read_codec(sc, AC97_REG_POWER, &data);
1020 cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfeff);
1021
1022 /* Wait until we sample ADC ready state.
1023 * Not documented, but Linux driver does.
1024 */
1025 for (n = 0; n < 32; ++n) {
1026 delay(1000);
1027 cs4281_read_codec(sc, AC97_REG_POWER, &data);
1028 if (data & 0x01)
1029 break;
1030 }
1031
1032 #if 0
1033 /* Initialize SSCR register features */
1034 /* XXX: hardware volume setting */
1035 BA0WRITE4(sc, CS4281_SSCR, ~SSCR_HVC); /* disable HW volume setting */
1036 #endif
1037
1038 /* disable Sound Blaster Pro emulation */
1039 /* XXX:
1040 * Cannot set since the documents does not describe which bit is
1041 * correspond to SSCR_SB. Since the reset value of SSCR is 0,
1042 * we can ignore it.*/
1043 #if 0
1044 BA0WRITE4(sc, CS4281_SSCR, SSCR_SB);
1045 #endif
1046
1047 /* map AC97 PCM playback to DMA Channel 0 */
1048 /* Reset FEN bit to setup first */
1049 BA0WRITE4(sc, CS4281_FCR0, (BA0READ4(sc,CS4281_FCR0) & ~FCRn_FEN));
1050 /*
1051 *| RS[4:0]/| |
1052 *| LS[4:0] | AC97 | Slot Function
1053 *|---------+--------+--------------------
1054 *| 0 | 3 | Left PCM Playback
1055 *| 1 | 4 | Right PCM Playback
1056 *| 2 | 5 | Phone Line 1 DAC
1057 *| 3 | 6 | Center PCM Playback
1058 *....
1059 * quoted from Table 29(p109)
1060 */
1061 dat32 = 0x01 << 24 | /* RS[4:0] = 1 see above */
1062 0x00 << 16 | /* LS[4:0] = 0 see above */
1063 0x0f << 8 | /* SZ[6:0] = 15 size of buffer */
1064 0x00 << 0 ; /* OF[6:0] = 0 offset */
1065 BA0WRITE4(sc, CS4281_FCR0, dat32);
1066 BA0WRITE4(sc, CS4281_FCR0, dat32 | FCRn_FEN);
1067
1068 /* map AC97 PCM record to DMA Channel 1 */
1069 /* Reset FEN bit to setup first */
1070 BA0WRITE4(sc, CS4281_FCR1, (BA0READ4(sc,CS4281_FCR1) & ~FCRn_FEN));
1071 /*
1072 *| RS[4:0]/|
1073 *| LS[4:0] | AC97 | Slot Function
1074 *|---------+------+-------------------
1075 *| 10 | 3 | Left PCM Record
1076 *| 11 | 4 | Right PCM Record
1077 *| 12 | 5 | Phone Line 1 ADC
1078 *| 13 | 6 | Mic ADC
1079 *....
1080 * quoted from Table 30(p109)
1081 */
1082 dat32 = 0x0b << 24 | /* RS[4:0] = 11 See above */
1083 0x0a << 16 | /* LS[4:0] = 10 See above */
1084 0x0f << 8 | /* SZ[6:0] = 15 Size of buffer */
1085 0x10 << 0 ; /* OF[6:0] = 16 offset */
1086
1087 /* XXX: I cannot understand why FCRn_PSH is needed here. */
1088 BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_PSH);
1089 BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_FEN);
1090
1091 #if 0
1092 /* Disable DMA Channel 2, 3 */
1093 BA0WRITE4(sc, CS4281_FCR2, (BA0READ4(sc,CS4281_FCR2) & ~FCRn_FEN));
1094 BA0WRITE4(sc, CS4281_FCR3, (BA0READ4(sc,CS4281_FCR3) & ~FCRn_FEN));
1095 #endif
1096
1097 /* Set the SRC Slot Assignment accordingly */
1098 /*| PLSS[4:0]/
1099 *| PRSS[4:0] | AC97 | Slot Function
1100 *|-----------+------+----------------
1101 *| 0 | 3 | Left PCM Playback
1102 *| 1 | 4 | Right PCM Playback
1103 *| 2 | 5 | phone line 1 DAC
1104 *| 3 | 6 | Center PCM Playback
1105 *| 4 | 7 | Left Surround PCM Playback
1106 *| 5 | 8 | Right Surround PCM Playback
1107 *......
1108 *
1109 *| CLSS[4:0]/
1110 *| CRSS[4:0] | AC97 | Codec |Slot Function
1111 *|-----------+------+-------+-----------------
1112 *| 10 | 3 |Primary| Left PCM Record
1113 *| 11 | 4 |Primary| Right PCM Record
1114 *| 12 | 5 |Primary| Phone Line 1 ADC
1115 *| 13 | 6 |Primary| Mic ADC
1116 *|.....
1117 *| 20 | 3 | Sec. | Left PCM Record
1118 *| 21 | 4 | Sec. | Right PCM Record
1119 *| 22 | 5 | Sec. | Phone Line 1 ADC
1120 *| 23 | 6 | Sec. | Mic ADC
1121 */
1122 dat32 = 0x0b << 24 | /* CRSS[4:0] Right PCM Record(primary) */
1123 0x0a << 16 | /* CLSS[4:0] Left PCM Record(primary) */
1124 0x01 << 8 | /* PRSS[4:0] Right PCM Playback */
1125 0x00 << 0; /* PLSS[4:0] Left PCM Playback */
1126 BA0WRITE4(sc, CS4281_SRCSA, dat32);
1127
1128 /* Set interrupt to occurred at Half and Full terminal
1129 * count interrupt enable for DMA channel 0 and 1.
1130 * To keep DMA stop, set MSK.
1131 */
1132 dat32 = DCRn_HTCIE | DCRn_TCIE | DCRn_MSK;
1133 BA0WRITE4(sc, CS4281_DCR0, dat32);
1134 BA0WRITE4(sc, CS4281_DCR1, dat32);
1135
1136 /* Set Auto-Initialize Contorl enable */
1137 BA0WRITE4(sc, CS4281_DMR0,
1138 DMRn_DMA | DMRn_AUTO | DMRn_TR_READ);
1139 BA0WRITE4(sc, CS4281_DMR1,
1140 DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE);
1141
1142 /* Clear DMA Mask in HIMR */
1143 dat32 = BA0READ4(sc, CS4281_HIMR) & 0xfffbfcff;
1144 BA0WRITE4(sc, CS4281_HIMR, dat32);
1145 return (0);
1146 }
1147
1148 void
cs4281_power(why,v)1149 cs4281_power(why, v)
1150 int why;
1151 void *v;
1152 {
1153 struct cs4281_softc *sc = (struct cs4281_softc *)v;
1154 int i;
1155
1156 DPRINTF(("%s: cs4281_power why=%d\n", sc->sc_dev.dv_xname, why));
1157 if (why != PWR_RESUME) {
1158 sc->sc_suspend = why;
1159
1160 cs4281_halt_output(sc);
1161 cs4281_halt_input(sc);
1162 /* Save AC97 registers */
1163 for (i = 1; i <= CS4281_SAVE_REG_MAX; i++) {
1164 if (i == 0x04) /* AC97_REG_MASTER_TONE */
1165 continue;
1166 cs4281_read_codec(sc, 2*i, &sc->ac97_reg[i>>1]);
1167 }
1168 /* should I powerdown here ? */
1169 cs4281_write_codec(sc, AC97_REG_POWER, CS4281_POWER_DOWN_ALL);
1170 } else {
1171 if (sc->sc_suspend == PWR_RESUME) {
1172 printf("cs4281_power: odd, resume without suspend.\n");
1173 sc->sc_suspend = why;
1174 return;
1175 }
1176 sc->sc_suspend = why;
1177 cs4281_init(sc);
1178 cs4281_reset_codec(sc);
1179
1180 /* restore ac97 registers */
1181 for (i = 1; i <= CS4281_SAVE_REG_MAX; i++) {
1182 if (i == 0x04) /* AC97_REG_MASTER_TONE */
1183 continue;
1184 cs4281_write_codec(sc, 2*i, sc->ac97_reg[i>>1]);
1185 }
1186 }
1187 }
1188
1189 void
cs4281_reset_codec(void * addr)1190 cs4281_reset_codec(void *addr)
1191 {
1192 struct cs4281_softc *sc;
1193 u_int16_t data;
1194 u_int32_t dat32;
1195 int n;
1196
1197 sc = addr;
1198
1199 DPRINTFN(3,("cs4281_reset_codec\n"));
1200
1201 /* Reset codec */
1202 BA0WRITE4(sc, CS4281_ACCTL, 0);
1203 delay(50); /* delay 50us */
1204
1205 BA0WRITE4(sc, CS4281_SPMC, 0);
1206 delay(100); /* delay 100us */
1207 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN);
1208 #if defined(ENABLE_SECONDARY_CODEC)
1209 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E);
1210 BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID);
1211 #endif
1212 delay(50000); /* XXX: delay 50ms */
1213
1214 /* Enable ASYNC generation */
1215 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN);
1216
1217 /* Wait for Codec ready. Linux driver wait 50ms here */
1218 n = 0;
1219 while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) {
1220 delay(100);
1221 if (++n > 1000) {
1222 printf("reset_codec: AC97 codec ready timeout\n");
1223 return;
1224 }
1225 }
1226 #if defined(ENABLE_SECONDARY_CODEC)
1227 /* secondary codec ready*/
1228 n = 0;
1229 while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) {
1230 delay(100);
1231 if (++n > 1000)
1232 return;
1233 }
1234 #endif
1235 /* Set the serial timing configuration */
1236 /* XXX: undocumented but the Linux driver do this */
1237 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
1238
1239 /* Wait for Codec ready signal */
1240 n = 0;
1241 do {
1242 delay(1000);
1243 if (++n > 1000) {
1244 printf("%s: Timeout waiting for Codec ready\n",
1245 sc->sc_dev.dv_xname);
1246 return;
1247 }
1248 dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY;
1249 } while (dat32 == 0);
1250
1251 /* Enable Valid Frame output on ASDOUT */
1252 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM);
1253
1254 /* Wait until Codec Calibration is finished. Codec register 26h */
1255 n = 0;
1256 do {
1257 delay(1);
1258 if (++n > 1000) {
1259 printf("%s: Timeout waiting for Codec calibration\n",
1260 sc->sc_dev.dv_xname);
1261 return ;
1262 }
1263 cs4281_read_codec(sc, AC97_REG_POWER, &data);
1264 } while ((data & 0x0f) != 0x0f);
1265
1266 /* Set the serial timing configuration again */
1267 /* XXX: undocumented but the Linux driver do this */
1268 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97);
1269
1270 /* Wait until we've sampled input slots 3 & 4 as valid */
1271 n = 0;
1272 do {
1273 delay(1000);
1274 if (++n > 1000) {
1275 printf("%s: Timeout waiting for sampled input slots as valid\n",
1276 sc->sc_dev.dv_xname);
1277 return;
1278 }
1279 dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ;
1280 } while (dat32 != (ACISV_ISV3 | ACISV_ISV4));
1281
1282 /* Start digital data transfer of audio data to the codec */
1283 BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4));
1284 }
1285
1286 int
cs4281_open(void * addr,int flags)1287 cs4281_open(void *addr, int flags)
1288 {
1289 return (0);
1290 }
1291
1292 void
cs4281_close(void * addr)1293 cs4281_close(void *addr)
1294 {
1295 struct cs4281_softc *sc;
1296
1297 sc = addr;
1298
1299 (*sc->halt_output)(sc);
1300 (*sc->halt_input)(sc);
1301
1302 sc->sc_pintr = 0;
1303 sc->sc_rintr = 0;
1304 }
1305
1306 int
cs4281_round_blocksize(void * addr,int blk)1307 cs4281_round_blocksize(void *addr, int blk)
1308 {
1309 struct cs4281_softc *sc;
1310 int retval;
1311
1312 DPRINTFN(5,("cs4281_round_blocksize blk=%d -> ", blk));
1313
1314 sc=addr;
1315 if (blk < sc->hw_blocksize)
1316 retval = sc->hw_blocksize;
1317 else
1318 retval = blk & -(sc->hw_blocksize);
1319
1320 DPRINTFN(5,("%d\n", retval));
1321
1322 return (retval);
1323 }
1324
1325 int
cs4281_mixer_set_port(void * addr,mixer_ctrl_t * cp)1326 cs4281_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1327 {
1328 struct cs4281_softc *sc;
1329 int val;
1330
1331 sc = addr;
1332 val = sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp);
1333 DPRINTFN(3,("mixer_set_port: val=%d\n", val));
1334 return (val);
1335 }
1336
1337 int
cs4281_mixer_get_port(void * addr,mixer_ctrl_t * cp)1338 cs4281_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1339 {
1340 struct cs4281_softc *sc;
1341
1342 sc = addr;
1343 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
1344 }
1345
1346
1347 int
cs4281_query_devinfo(void * addr,mixer_devinfo_t * dip)1348 cs4281_query_devinfo(void *addr, mixer_devinfo_t *dip)
1349 {
1350 struct cs4281_softc *sc;
1351
1352 sc = addr;
1353 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
1354 }
1355
1356 void *
cs4281_malloc(void * addr,int direction,size_t size,int pool,int flags)1357 cs4281_malloc(void *addr, int direction, size_t size, int pool, int flags)
1358 {
1359 struct cs4281_softc *sc;
1360 struct cs4281_dma *p;
1361 int error;
1362
1363 sc = addr;
1364
1365 p = malloc(sizeof(*p), pool, flags);
1366 if (!p)
1367 return (0);
1368
1369 error = cs4281_allocmem(sc, size, pool, flags, p);
1370
1371 if (error) {
1372 free(p, pool);
1373 return (0);
1374 }
1375
1376 p->next = sc->sc_dmas;
1377 sc->sc_dmas = p;
1378 return (BUFADDR(p));
1379 }
1380
1381
1382
1383 void
cs4281_free(void * addr,void * ptr,int pool)1384 cs4281_free(void *addr, void *ptr, int pool)
1385 {
1386 struct cs4281_softc *sc;
1387 struct cs4281_dma **pp, *p;
1388
1389 sc = addr;
1390 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
1391 if (BUFADDR(p) == ptr) {
1392 bus_dmamap_unload(sc->sc_dmatag, p->map);
1393 bus_dmamap_destroy(sc->sc_dmatag, p->map);
1394 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
1395 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
1396 free(p->dum, pool);
1397 *pp = p->next;
1398 free(p, pool);
1399 return;
1400 }
1401 }
1402 }
1403
1404 size_t
cs4281_round_buffersize(void * addr,int direction,size_t size)1405 cs4281_round_buffersize(void *addr, int direction, size_t size)
1406 {
1407 /* The real dma buffersize are 4KB for CS4280
1408 * and 64kB/MAX_CHANNELS for CS4281.
1409 * But they are too small for high quality audio,
1410 * let the upper layer(audio) use a larger buffer.
1411 * (originally suggested by Lennart Augustsson.)
1412 */
1413 return (size);
1414 }
1415
1416 paddr_t
cs4281_mappage(void * addr,void * mem,off_t off,int prot)1417 cs4281_mappage(void *addr, void *mem, off_t off, int prot)
1418 {
1419 struct cs4281_softc *sc;
1420 struct cs4281_dma *p;
1421
1422 sc = addr;
1423 if (off < 0)
1424 return -1;
1425
1426 for (p = sc->sc_dmas; p && BUFADDR(p) != mem; p = p->next)
1427 ;
1428
1429 if (!p) {
1430 DPRINTF(("cs4281_mappage: bad buffer address\n"));
1431 return (-1);
1432 }
1433
1434 return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, off, prot,
1435 BUS_DMA_WAITOK));
1436 }
1437
1438
1439 int
cs4281_get_props(void * addr)1440 cs4281_get_props(void *addr)
1441 {
1442 int retval;
1443
1444 retval = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1445 #ifdef MMAP_READY
1446 retval |= AUDIO_PROP_MMAP;
1447 #endif
1448 return (retval);
1449 }
1450
1451 /* AC97 */
1452 int
cs4281_attach_codec(void * addr,struct ac97_codec_if * codec_if)1453 cs4281_attach_codec(void *addr, struct ac97_codec_if *codec_if)
1454 {
1455 struct cs4281_softc *sc;
1456
1457 DPRINTF(("cs4281_attach_codec:\n"));
1458 sc = addr;
1459 sc->codec_if = codec_if;
1460 return (0);
1461 }
1462
1463
1464 int
cs4281_read_codec(void * addr,u_int8_t ac97_addr,u_int16_t * ac97_data)1465 cs4281_read_codec(void *addr, u_int8_t ac97_addr, u_int16_t *ac97_data)
1466 {
1467 struct cs4281_softc *sc;
1468 u_int32_t acctl;
1469 int n;
1470
1471 sc = addr;
1472
1473 DPRINTFN(5,("read_codec: add=0x%02x ", ac97_addr));
1474 /*
1475 * Make sure that there is not data sitting around from a preivous
1476 * uncompleted access.
1477 */
1478 BA0READ4(sc, CS4281_ACSDA);
1479
1480 /* Set up AC97 control registers. */
1481 BA0WRITE4(sc, CS4281_ACCAD, ac97_addr);
1482 BA0WRITE4(sc, CS4281_ACCDA, 0);
1483
1484 acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_CRW | ACCTL_DCV;
1485 BA0WRITE4(sc, CS4281_ACCTL, acctl);
1486
1487 if (cs4281_src_wait(sc) < 0) {
1488 printf("%s: AC97 read prob. (DCV!=0) for add=0x%0x\n",
1489 sc->sc_dev.dv_xname, ac97_addr);
1490 return 1;
1491 }
1492
1493 /* wait for valid status bit is active */
1494 n = 0;
1495 while ((BA0READ4(sc, CS4281_ACSTS) & ACSTS_VSTS) == 0) {
1496 delay(1);
1497 while (++n > 1000) {
1498 printf("%s: AC97 read fail (VSTS==0) for add=0x%0x\n",
1499 sc->sc_dev.dv_xname, ac97_addr);
1500 return 1;
1501 }
1502 }
1503 *ac97_data = BA0READ4(sc, CS4281_ACSDA);
1504 DPRINTFN(5,("data=0x%04x\n", *ac97_data));
1505 return (0);
1506 }
1507
1508 int
cs4281_write_codec(void * addr,u_int8_t ac97_addr,u_int16_t ac97_data)1509 cs4281_write_codec(void *addr, u_int8_t ac97_addr, u_int16_t ac97_data)
1510 {
1511 struct cs4281_softc *sc;
1512 u_int32_t acctl;
1513
1514 sc = addr;
1515
1516 DPRINTFN(5,("write_codec: add=0x%02x data=0x%04x\n", ac97_addr, ac97_data));
1517 BA0WRITE4(sc, CS4281_ACCAD, ac97_addr);
1518 BA0WRITE4(sc, CS4281_ACCDA, ac97_data);
1519
1520 acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_DCV;
1521 BA0WRITE4(sc, CS4281_ACCTL, acctl);
1522
1523 if (cs4281_src_wait(sc) < 0) {
1524 printf("%s: AC97 write fail (DCV!=0) for add=0x%02x data="
1525 "0x%04x\n", sc->sc_dev.dv_xname, ac97_addr, ac97_data);
1526 return (1);
1527 }
1528 return (0);
1529 }
1530
1531 int
cs4281_allocmem(struct cs4281_softc * sc,size_t size,int pool,int flags,struct cs4281_dma * p)1532 cs4281_allocmem(struct cs4281_softc *sc, size_t size, int pool, int flags,
1533 struct cs4281_dma *p)
1534 {
1535 int error;
1536 size_t align;
1537
1538 align = sc->dma_align;
1539 p->size = sc->dma_size;
1540 /* allocate memory for upper audio driver */
1541 p->dum = malloc(size, pool, flags);
1542 if (!p->dum)
1543 return (1);
1544 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
1545 p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
1546 &p->nsegs, BUS_DMA_NOWAIT);
1547 if (error) {
1548 printf("%s: unable to allocate dma. error=%d\n",
1549 sc->sc_dev.dv_xname, error);
1550 return (error);
1551 }
1552
1553 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
1554 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1555 if (error) {
1556 printf("%s: unable to map dma, error=%d\n",
1557 sc->sc_dev.dv_xname, error);
1558 goto free;
1559 }
1560
1561 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
1562 0, BUS_DMA_NOWAIT, &p->map);
1563 if (error) {
1564 printf("%s: unable to create dma map, error=%d\n",
1565 sc->sc_dev.dv_xname, error);
1566 goto unmap;
1567 }
1568
1569 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
1570 BUS_DMA_NOWAIT);
1571 if (error) {
1572 printf("%s: unable to load dma map, error=%d\n",
1573 sc->sc_dev.dv_xname, error);
1574 goto destroy;
1575 }
1576 return (0);
1577
1578 destroy:
1579 bus_dmamap_destroy(sc->sc_dmatag, p->map);
1580 unmap:
1581 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
1582 free:
1583 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
1584 return (error);
1585 }
1586
1587
1588 int
cs4281_src_wait(sc)1589 cs4281_src_wait(sc)
1590 struct cs4281_softc *sc;
1591 {
1592 int n;
1593
1594 n = 0;
1595 while ((BA0READ4(sc, CS4281_ACCTL) & ACCTL_DCV)) {
1596 delay(1000);
1597 while (++n > 1000)
1598 return (-1);
1599 }
1600 return (0);
1601 }
1602