Deleted Added
sdiff udiff text old ( 67652 ) new ( 70134 )
full compact
1/*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * Copyright Luigi Rizzo, 1997,1998
4 * Copyright by Hannu Savolainen 1994, 1995
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

--- 11 unchanged lines hidden (view full) ---

20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/dev/sound/isa/ad1816.c 70134 2000-12-18 01:36:41Z cg $
29 */
30
31#include <dev/sound/pcm/sound.h>
32#include <dev/sound/isa/ad1816.h>
33
34#include "mixer_if.h"
35
36struct ad1816_info;
37
38struct ad1816_chinfo {
39 struct ad1816_info *parent;
40 pcm_channel *channel;
41 snd_dbuf *buffer;
42 int dir;
43};

--- 17 unchanged lines hidden (view full) ---

61static int ad1816_probe(device_t dev);
62static int ad1816_attach(device_t dev);
63
64/* IO primitives */
65static int ad1816_wait_init(struct ad1816_info *ad1816, int x);
66static u_short ad1816_read(struct ad1816_info *ad1816, u_int reg);
67static void ad1816_write(struct ad1816_info *ad1816, u_int reg, u_short data);
68
69static devclass_t pcm_devclass;
70
71static u_int32_t ad1816_fmt[] = {
72 AFMT_U8,
73 AFMT_STEREO | AFMT_U8,
74 AFMT_S16_LE,
75 AFMT_STEREO | AFMT_S16_LE,
76 AFMT_MU_LAW,
77 AFMT_STEREO | AFMT_MU_LAW,
78 AFMT_A_LAW,
79 AFMT_STEREO | AFMT_A_LAW,
80 0
81};
82
83static pcmchan_caps ad1816_caps = {4000, 55200, ad1816_fmt, 0};
84
85#define AD1816_MUTE 31 /* value for mute */
86
87static int
88port_rd(struct resource *port, int off)
89{
90 if (port)
91 return bus_space_read_1(rman_get_bustag(port),
92 rman_get_bushandle(port),

--- 95 unchanged lines hidden (view full) ---

188 flags = spltty();
189 if (ad1816_wait_init(ad1816, 100) == -1) return;
190 io_wr(ad1816, AD1816_ALE, (reg & AD1816_ALEMASK));
191 io_wr(ad1816, AD1816_LOW, (data & 0x000000ff));
192 io_wr(ad1816, AD1816_HIGH, (data & 0x0000ff00) >> 8);
193 splx(flags);
194}
195
196/* -------------------------------------------------------------------- */
197
198static int
199ad1816mix_init(snd_mixer *m)
200{
201 mix_setdevs(m, AD1816_MIXER_DEVICES);
202 mix_setrecdevs(m, AD1816_REC_DEVICES);
203 return 0;
204}
205

--- 81 unchanged lines hidden (view full) ---

287 src = SOUND_MASK_MIC;
288 }
289
290 dev |= dev << 8;
291 ad1816_write(ad1816, 20, (ad1816_read(ad1816, 20) & ~0x7070) | dev);
292 return src;
293}
294
295static kobj_method_t ad1816mixer_methods[] = {
296 KOBJMETHOD(mixer_init, ad1816mix_init),
297 KOBJMETHOD(mixer_set, ad1816mix_set),
298 KOBJMETHOD(mixer_setrecsrc, ad1816mix_setrecsrc),
299 { 0, 0 }
300};
301MIXER_DECLARE(ad1816mixer);
302
303/* -------------------------------------------------------------------- */
304/* channel interface */
305static void *
306ad1816chan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
307{
308 struct ad1816_info *ad1816 = devinfo;
309 struct ad1816_chinfo *ch = (dir == PCMDIR_PLAY)? &ad1816->pch : &ad1816->rch;
310
311 ch->parent = ad1816;
312 ch->channel = c;
313 ch->buffer = b;
314 ch->buffer->bufsize = DSP_BUFFSIZE;
315 if (chn_allocbuf(ch->buffer, ad1816->parent_dmat) == -1) return NULL;
316 return ch;
317}
318
319static int
320ad1816chan_setdir(kobj_t obj, void *data, int dir)
321{
322 struct ad1816_chinfo *ch = data;
323 struct ad1816_info *ad1816 = ch->parent;
324
325 ch->buffer->chan = rman_get_start((dir == PCMDIR_PLAY)?
326 ad1816->drq1 : ad1816->drq2);
327 ch->dir = dir;
328 return 0;
329}
330
331static int
332ad1816chan_setformat(kobj_t obj, void *data, u_int32_t format)
333{
334 struct ad1816_chinfo *ch = data;
335 struct ad1816_info *ad1816 = ch->parent;
336
337 int fmt = AD1816_U8, reg;
338 if (ch->dir == PCMDIR_PLAY) {
339 reg = AD1816_PLAY;
340 ad1816_write(ad1816, 8, 0x0000); /* reset base and current counter */

--- 25 unchanged lines hidden (view full) ---

366 break;
367 }
368 if (format & AFMT_STEREO) fmt |= AD1816_STEREO;
369 io_wr(ad1816, reg, fmt);
370 return format;
371}
372
373static int
374ad1816chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
375{
376 struct ad1816_chinfo *ch = data;
377 struct ad1816_info *ad1816 = ch->parent;
378
379 RANGE(speed, 4000, 55200);
380 ad1816_write(ad1816, (ch->dir == PCMDIR_PLAY)? 2 : 3, speed);
381 return speed;
382}
383
384static int
385ad1816chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
386{
387 return blocksize;
388}
389
390static int
391ad1816chan_trigger(kobj_t obj, void *data, int go)
392{
393 struct ad1816_chinfo *ch = data;
394 struct ad1816_info *ad1816 = ch->parent;
395 int wr, reg;
396
397 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
398 return 0;
399

--- 33 unchanged lines hidden (view full) ---

433 ad1816_write(ad1816, wr? 9 : 11, 0); /* reset cur cnt */
434 }
435 break;
436 }
437 return 0;
438}
439
440static int
441ad1816chan_getptr(kobj_t obj, void *data)
442{
443 struct ad1816_chinfo *ch = data;
444 return buf_isadmaptr(ch->buffer);
445}
446
447static pcmchan_caps *
448ad1816chan_getcaps(kobj_t obj, void *data)
449{
450 return &ad1816_caps;
451}
452
453static kobj_method_t ad1816chan_methods[] = {
454 KOBJMETHOD(channel_init, ad1816chan_init),
455 KOBJMETHOD(channel_setdir, ad1816chan_setdir),
456 KOBJMETHOD(channel_setformat, ad1816chan_setformat),
457 KOBJMETHOD(channel_setspeed, ad1816chan_setspeed),
458 KOBJMETHOD(channel_setblocksize, ad1816chan_setblocksize),
459 KOBJMETHOD(channel_trigger, ad1816chan_trigger),
460 KOBJMETHOD(channel_getptr, ad1816chan_getptr),
461 KOBJMETHOD(channel_getcaps, ad1816chan_getcaps),
462 { 0, 0 }
463};
464CHANNEL_DECLARE(ad1816chan);
465
466/* -------------------------------------------------------------------- */
467
468static void
469ad1816_release_resources(struct ad1816_info *ad1816, device_t dev)
470{
471 if (ad1816->irq) {
472 if (ad1816->ih)
473 bus_teardown_intr(dev, ad1816->irq, ad1816->ih);
474 bus_release_resource(dev, SYS_RES_IRQ, ad1816->irq_rid,
475 ad1816->irq);

--- 102 unchanged lines hidden (view full) ---

578
579 ad1816->io_rid = 2;
580 ad1816->irq_rid = 0;
581 ad1816->drq1_rid = 0;
582 ad1816->drq2_rid = 1;
583
584 if (!ad1816_alloc_resources(ad1816, dev)) goto no;
585 ad1816_init(ad1816, dev);
586 if (mixer_init(dev, &ad1816mixer_class, ad1816)) goto no;
587
588 bus_setup_intr(dev, ad1816->irq, INTR_TYPE_TTY, ad1816_intr, ad1816, &ad1816->ih);
589 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
590 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
591 /*highaddr*/BUS_SPACE_MAXADDR,
592 /*filter*/NULL, /*filterarg*/NULL,
593 /*maxsize*/DSP_BUFFSIZE, /*nsegments*/1,
594 /*maxsegz*/0x3ffff,
595 /*flags*/0, &ad1816->parent_dmat) != 0) {

--- 4 unchanged lines hidden (view full) ---

600 rman_get_start(ad1816->io_base),
601 rman_get_start(ad1816->irq),
602 rman_get_start(ad1816->drq1));
603 if (ad1816->drq2) snprintf(status + strlen(status),
604 SND_STATUSLEN - strlen(status), ":%ld",
605 rman_get_start(ad1816->drq2));
606
607 if (pcm_register(dev, ad1816, 1, 1)) goto no;
608 pcm_addchan(dev, PCMDIR_REC, &ad1816chan_class, ad1816);
609 pcm_addchan(dev, PCMDIR_PLAY, &ad1816chan_class, ad1816);
610 pcm_setstatus(dev, status);
611
612 return 0;
613no:
614 ad1816_release_resources(ad1816, dev);
615 return ENXIO;
616
617}

--- 36 unchanged lines hidden ---