ad1816.c (67652) | ad1816.c (70134) |
---|---|
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 * | 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 67652 2000-10-26 20:46:58Z cg $ | 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 | 29 */ 30 31#include <dev/sound/pcm/sound.h> 32#include <dev/sound/isa/ad1816.h> 33 |
34#include "mixer_if.h" 35 |
|
34struct ad1816_info; 35 36struct ad1816_chinfo { 37 struct ad1816_info *parent; 38 pcm_channel *channel; 39 snd_dbuf *buffer; 40 int dir; 41}; --- 17 unchanged lines hidden (view full) --- 59static int ad1816_probe(device_t dev); 60static int ad1816_attach(device_t dev); 61 62/* IO primitives */ 63static int ad1816_wait_init(struct ad1816_info *ad1816, int x); 64static u_short ad1816_read(struct ad1816_info *ad1816, u_int reg); 65static void ad1816_write(struct ad1816_info *ad1816, u_int reg, u_short data); 66 | 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 |
67static int ad1816mix_init(snd_mixer *m); 68static int ad1816mix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); 69static int ad1816mix_setrecsrc(snd_mixer *m, u_int32_t src); 70static snd_mixer ad1816_mixer = { 71 "ad1816 mixer", 72 ad1816mix_init, 73 NULL, 74 NULL, 75 ad1816mix_set, 76 ad1816mix_setrecsrc, 77}; 78 | |
79static devclass_t pcm_devclass; 80 | 69static devclass_t pcm_devclass; 70 |
81/* channel interface */ 82static void *ad1816chan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 83static int ad1816chan_setdir(void *data, int dir); 84static int ad1816chan_setformat(void *data, u_int32_t format); 85static int ad1816chan_setspeed(void *data, u_int32_t speed); 86static int ad1816chan_setblocksize(void *data, u_int32_t blocksize); 87static int ad1816chan_trigger(void *data, int go); 88static int ad1816chan_getptr(void *data); 89static pcmchan_caps *ad1816chan_getcaps(void *data); 90 | |
91static u_int32_t ad1816_fmt[] = { 92 AFMT_U8, 93 AFMT_STEREO | AFMT_U8, 94 AFMT_S16_LE, 95 AFMT_STEREO | AFMT_S16_LE, 96 AFMT_MU_LAW, 97 AFMT_STEREO | AFMT_MU_LAW, 98 AFMT_A_LAW, 99 AFMT_STEREO | AFMT_A_LAW, 100 0 101}; 102 103static pcmchan_caps ad1816_caps = {4000, 55200, ad1816_fmt, 0}; 104 | 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 |
105static pcm_channel ad1816_chantemplate = { 106 ad1816chan_init, 107 ad1816chan_setdir, 108 ad1816chan_setformat, 109 ad1816chan_setspeed, 110 ad1816chan_setblocksize, 111 ad1816chan_trigger, 112 ad1816chan_getptr, 113 ad1816chan_getcaps, 114 NULL, /* free */ 115 NULL, /* nop1 */ 116 NULL, /* nop2 */ 117 NULL, /* nop3 */ 118 NULL, /* nop4 */ 119 NULL, /* nop5 */ 120 NULL, /* nop6 */ 121 NULL, /* nop7 */ 122}; 123 | |
124#define AD1816_MUTE 31 /* value for mute */ 125 126static int 127port_rd(struct resource *port, int off) 128{ 129 if (port) 130 return bus_space_read_1(rman_get_bustag(port), 131 rman_get_bushandle(port), --- 95 unchanged lines hidden (view full) --- 227 flags = spltty(); 228 if (ad1816_wait_init(ad1816, 100) == -1) return; 229 io_wr(ad1816, AD1816_ALE, (reg & AD1816_ALEMASK)); 230 io_wr(ad1816, AD1816_LOW, (data & 0x000000ff)); 231 io_wr(ad1816, AD1816_HIGH, (data & 0x0000ff00) >> 8); 232 splx(flags); 233} 234 | 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 |
|
235static int 236ad1816mix_init(snd_mixer *m) 237{ 238 mix_setdevs(m, AD1816_MIXER_DEVICES); 239 mix_setrecdevs(m, AD1816_REC_DEVICES); 240 return 0; 241} 242 --- 81 unchanged lines hidden (view full) --- 324 src = SOUND_MASK_MIC; 325 } 326 327 dev |= dev << 8; 328 ad1816_write(ad1816, 20, (ad1816_read(ad1816, 20) & ~0x7070) | dev); 329 return src; 330} 331 | 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/* -------------------------------------------------------------------- */ |
|
332/* channel interface */ 333static void * | 304/* channel interface */ 305static void * |
334ad1816chan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) | 306ad1816chan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) |
335{ 336 struct ad1816_info *ad1816 = devinfo; 337 struct ad1816_chinfo *ch = (dir == PCMDIR_PLAY)? &ad1816->pch : &ad1816->rch; 338 339 ch->parent = ad1816; 340 ch->channel = c; 341 ch->buffer = b; 342 ch->buffer->bufsize = DSP_BUFFSIZE; 343 if (chn_allocbuf(ch->buffer, ad1816->parent_dmat) == -1) return NULL; 344 return ch; 345} 346 347static int | 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 |
348ad1816chan_setdir(void *data, int dir) | 320ad1816chan_setdir(kobj_t obj, void *data, int dir) |
349{ 350 struct ad1816_chinfo *ch = data; 351 struct ad1816_info *ad1816 = ch->parent; 352 353 ch->buffer->chan = rman_get_start((dir == PCMDIR_PLAY)? 354 ad1816->drq1 : ad1816->drq2); 355 ch->dir = dir; 356 return 0; 357} 358 359static int | 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 |
360ad1816chan_setformat(void *data, u_int32_t format) | 332ad1816chan_setformat(kobj_t obj, void *data, u_int32_t format) |
361{ 362 struct ad1816_chinfo *ch = data; 363 struct ad1816_info *ad1816 = ch->parent; 364 365 int fmt = AD1816_U8, reg; 366 if (ch->dir == PCMDIR_PLAY) { 367 reg = AD1816_PLAY; 368 ad1816_write(ad1816, 8, 0x0000); /* reset base and current counter */ --- 25 unchanged lines hidden (view full) --- 394 break; 395 } 396 if (format & AFMT_STEREO) fmt |= AD1816_STEREO; 397 io_wr(ad1816, reg, fmt); 398 return format; 399} 400 401static int | 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 |
402ad1816chan_setspeed(void *data, u_int32_t speed) | 374ad1816chan_setspeed(kobj_t obj, void *data, u_int32_t speed) |
403{ 404 struct ad1816_chinfo *ch = data; 405 struct ad1816_info *ad1816 = ch->parent; 406 407 RANGE(speed, 4000, 55200); 408 ad1816_write(ad1816, (ch->dir == PCMDIR_PLAY)? 2 : 3, speed); 409 return speed; 410} 411 412static int | 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 |
413ad1816chan_setblocksize(void *data, u_int32_t blocksize) | 385ad1816chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) |
414{ 415 return blocksize; 416} 417 418static int | 386{ 387 return blocksize; 388} 389 390static int |
419ad1816chan_trigger(void *data, int go) | 391ad1816chan_trigger(kobj_t obj, void *data, int go) |
420{ 421 struct ad1816_chinfo *ch = data; 422 struct ad1816_info *ad1816 = ch->parent; 423 int wr, reg; 424 425 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 426 return 0; 427 --- 33 unchanged lines hidden (view full) --- 461 ad1816_write(ad1816, wr? 9 : 11, 0); /* reset cur cnt */ 462 } 463 break; 464 } 465 return 0; 466} 467 468static int | 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 |
469ad1816chan_getptr(void *data) | 441ad1816chan_getptr(kobj_t obj, void *data) |
470{ 471 struct ad1816_chinfo *ch = data; 472 return buf_isadmaptr(ch->buffer); 473} 474 475static pcmchan_caps * | 442{ 443 struct ad1816_chinfo *ch = data; 444 return buf_isadmaptr(ch->buffer); 445} 446 447static pcmchan_caps * |
476ad1816chan_getcaps(void *data) | 448ad1816chan_getcaps(kobj_t obj, void *data) |
477{ 478 return &ad1816_caps; 479} 480 | 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 |
|
481static void 482ad1816_release_resources(struct ad1816_info *ad1816, device_t dev) 483{ 484 if (ad1816->irq) { 485 if (ad1816->ih) 486 bus_teardown_intr(dev, ad1816->irq, ad1816->ih); 487 bus_release_resource(dev, SYS_RES_IRQ, ad1816->irq_rid, 488 ad1816->irq); --- 102 unchanged lines hidden (view full) --- 591 592 ad1816->io_rid = 2; 593 ad1816->irq_rid = 0; 594 ad1816->drq1_rid = 0; 595 ad1816->drq2_rid = 1; 596 597 if (!ad1816_alloc_resources(ad1816, dev)) goto no; 598 ad1816_init(ad1816, dev); | 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); |
599 mixer_init(dev, &ad1816_mixer, ad1816); | 586 if (mixer_init(dev, &ad1816mixer_class, ad1816)) goto no; 587 |
600 bus_setup_intr(dev, ad1816->irq, INTR_TYPE_TTY, ad1816_intr, ad1816, &ad1816->ih); 601 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 602 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 603 /*highaddr*/BUS_SPACE_MAXADDR, 604 /*filter*/NULL, /*filterarg*/NULL, 605 /*maxsize*/DSP_BUFFSIZE, /*nsegments*/1, 606 /*maxsegz*/0x3ffff, 607 /*flags*/0, &ad1816->parent_dmat) != 0) { --- 4 unchanged lines hidden (view full) --- 612 rman_get_start(ad1816->io_base), 613 rman_get_start(ad1816->irq), 614 rman_get_start(ad1816->drq1)); 615 if (ad1816->drq2) snprintf(status + strlen(status), 616 SND_STATUSLEN - strlen(status), ":%ld", 617 rman_get_start(ad1816->drq2)); 618 619 if (pcm_register(dev, ad1816, 1, 1)) goto no; | 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; |
620 pcm_addchan(dev, PCMDIR_REC, &ad1816_chantemplate, ad1816); 621 pcm_addchan(dev, PCMDIR_PLAY, &ad1816_chantemplate, ad1816); | 608 pcm_addchan(dev, PCMDIR_REC, &ad1816chan_class, ad1816); 609 pcm_addchan(dev, PCMDIR_PLAY, &ad1816chan_class, ad1816); |
622 pcm_setstatus(dev, status); 623 624 return 0; 625no: 626 ad1816_release_resources(ad1816, dev); 627 return ENXIO; 628 629} --- 36 unchanged lines hidden --- | 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 --- |