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 --- |