ess.c (67652) | ess.c (70134) |
---|---|
1/* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * Copyright 1997,1998 Luigi Rizzo. 4 * 5 * Derived from files in the Voxware 3.5 distribution, 6 * Copyright by Hannu Savolainen 1994, under the same copyright 7 * conditions. 8 * All rights reserved. --- 14 unchanged lines hidden (view full) --- 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * | 1/* 2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 3 * Copyright 1997,1998 Luigi Rizzo. 4 * 5 * Derived from files in the Voxware 3.5 distribution, 6 * Copyright by Hannu Savolainen 1994, under the same copyright 7 * conditions. 8 * All rights reserved. --- 14 unchanged lines hidden (view full) --- 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * |
31 * $FreeBSD: head/sys/dev/sound/isa/ess.c 67652 2000-10-26 20:46:58Z cg $ | 31 * $FreeBSD: head/sys/dev/sound/isa/ess.c 70134 2000-12-18 01:36:41Z cg $ |
32 */ 33 34#include <dev/sound/pcm/sound.h> 35 36#include <dev/sound/isa/sb.h> 37#include <dev/sound/chip.h> 38 | 32 */ 33 34#include <dev/sound/pcm/sound.h> 35 36#include <dev/sound/isa/sb.h> 37#include <dev/sound/chip.h> 38 |
39#include "mixer_if.h" 40 |
|
39#define ESS_BUFFSIZE (4096) 40#define ABS(x) (((x) < 0)? -(x) : (x)) 41 42/* audio2 never generates irqs and sounds very noisy */ 43#undef ESS18XX_DUPLEX 44 45/* more accurate clocks and split audio1/audio2 rates */ 46#define ESS18XX_NEWSPEED 47 | 41#define ESS_BUFFSIZE (4096) 42#define ABS(x) (((x) < 0)? -(x) : (x)) 43 44/* audio2 never generates irqs and sounds very noisy */ 45#undef ESS18XX_DUPLEX 46 47/* more accurate clocks and split audio1/audio2 rates */ 48#define ESS18XX_NEWSPEED 49 |
48/* channel interface for ESS */ 49static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 50static int esschan_setformat(void *data, u_int32_t format); 51static int esschan_setspeed(void *data, u_int32_t speed); 52static int esschan_setblocksize(void *data, u_int32_t blocksize); 53static int esschan_trigger(void *data, int go); 54static int esschan_getptr(void *data); 55static pcmchan_caps *esschan_getcaps(void *data); 56 | |
57static u_int32_t ess_pfmt[] = { 58 AFMT_U8, 59 AFMT_STEREO | AFMT_U8, 60 AFMT_S8, 61 AFMT_STEREO | AFMT_S8, 62 AFMT_S16_LE, 63 AFMT_STEREO | AFMT_S16_LE, 64 AFMT_U16_LE, --- 12 unchanged lines hidden (view full) --- 77 AFMT_STEREO | AFMT_S16_LE, 78 AFMT_U16_LE, 79 AFMT_STEREO | AFMT_U16_LE, 80 0 81}; 82 83static pcmchan_caps ess_reccaps = {5000, 49000, ess_rfmt, 0}; 84 | 50static u_int32_t ess_pfmt[] = { 51 AFMT_U8, 52 AFMT_STEREO | AFMT_U8, 53 AFMT_S8, 54 AFMT_STEREO | AFMT_S8, 55 AFMT_S16_LE, 56 AFMT_STEREO | AFMT_S16_LE, 57 AFMT_U16_LE, --- 12 unchanged lines hidden (view full) --- 70 AFMT_STEREO | AFMT_S16_LE, 71 AFMT_U16_LE, 72 AFMT_STEREO | AFMT_U16_LE, 73 0 74}; 75 76static pcmchan_caps ess_reccaps = {5000, 49000, ess_rfmt, 0}; 77 |
85static pcm_channel ess_chantemplate = { 86 esschan_init, 87 NULL, /* setdir */ 88 esschan_setformat, 89 esschan_setspeed, 90 esschan_setblocksize, 91 esschan_trigger, 92 esschan_getptr, 93 esschan_getcaps, 94 NULL, /* free */ 95 NULL, /* nop1 */ 96 NULL, /* nop2 */ 97 NULL, /* nop3 */ 98 NULL, /* nop4 */ 99 NULL, /* nop5 */ 100 NULL, /* nop6 */ 101 NULL, /* nop7 */ 102}; 103 | |
104struct ess_info; 105 106struct ess_chinfo { 107 struct ess_info *parent; 108 pcm_channel *channel; 109 snd_dbuf *buffer; | 78struct ess_info; 79 80struct ess_chinfo { 81 struct ess_info *parent; 82 pcm_channel *channel; 83 snd_dbuf *buffer; |
110 int dir, hwch, stopping; | 84 int dir, hwch, stopping, run; |
111 u_int32_t fmt, spd; 112}; 113 114struct ess_info { 115 struct resource *io_base; /* I/O address for the board */ 116 struct resource *irq; 117 struct resource *drq1; 118 struct resource *drq2; --- 18 unchanged lines hidden (view full) --- 137static int ess_write(struct ess_info *sc, u_char reg, int val); 138static int ess_read(struct ess_info *sc, u_char reg); 139 140static void ess_intr(void *arg); 141static int ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len); 142static int ess_start(struct ess_chinfo *ch); 143static int ess_stop(struct ess_chinfo *ch); 144 | 85 u_int32_t fmt, spd; 86}; 87 88struct ess_info { 89 struct resource *io_base; /* I/O address for the board */ 90 struct resource *irq; 91 struct resource *drq1; 92 struct resource *drq2; --- 18 unchanged lines hidden (view full) --- 111static int ess_write(struct ess_info *sc, u_char reg, int val); 112static int ess_read(struct ess_info *sc, u_char reg); 113 114static void ess_intr(void *arg); 115static int ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len); 116static int ess_start(struct ess_chinfo *ch); 117static int ess_stop(struct ess_chinfo *ch); 118 |
145static int essmix_init(snd_mixer *m); 146static int essmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right); 147static int essmix_setrecsrc(snd_mixer *m, u_int32_t src); 148 149static snd_mixer ess_mixer = { 150 "ESS mixer", 151 essmix_init, 152 NULL, 153 NULL, 154 essmix_set, 155 essmix_setrecsrc, 156}; 157 | |
158static devclass_t pcm_devclass; 159 160/* 161 * Common code for the midi and pcm functions 162 * 163 * ess_cmd write a single byte to the CMD port. 164 * ess_cmd1 write a CMD + 1 byte arg 165 * ess_cmd2 write a CMD + 2 byte arg --- 206 unchanged lines hidden (view full) --- 372 isa_dma_acquire(rman_get_start(sc->drq2)); 373 isa_dmainit(rman_get_start(sc->drq2), ESS_BUFFSIZE); 374 } 375 376 return 0; 377 } else return ENXIO; 378} 379 | 119static devclass_t pcm_devclass; 120 121/* 122 * Common code for the midi and pcm functions 123 * 124 * ess_cmd write a single byte to the CMD port. 125 * ess_cmd1 write a CMD + 1 byte arg 126 * ess_cmd2 write a CMD + 2 byte arg --- 206 unchanged lines hidden (view full) --- 333 isa_dma_acquire(rman_get_start(sc->drq2)); 334 isa_dmainit(rman_get_start(sc->drq2), ESS_BUFFSIZE); 335 } 336 337 return 0; 338 } else return ENXIO; 339} 340 |
380static int 381ess_doattach(device_t dev, struct ess_info *sc) 382{ 383 char status[SND_STATUSLEN], buf[64]; 384 int ver; 385 386 if (ess_alloc_resources(sc, dev)) 387 goto no; 388 if (ess_reset_dsp(sc)) 389 goto no; 390 mixer_init(dev, &ess_mixer, sc); 391 392 sc->duplex = 0; 393 sc->newspeed = 0; 394 ver = (ess_getmixer(sc, 0x40) << 8) | ess_rd(sc, SB_MIX_DATA); 395 snprintf(buf, sizeof buf, "ESS %x DSP", ver); 396 device_set_desc_copy(dev, buf); 397 if (bootverbose) 398 device_printf(dev, "ESS%x detected", ver); 399 400 switch (ver) { 401 case 0x1869: 402 case 0x1879: 403#ifdef ESS18XX_DUPLEX 404 sc->duplex = sc->drq2? 1 : 0; 405#endif 406#ifdef ESS18XX_NEWSPEED 407 sc->newspeed = 1; 408#endif 409 break; 410 } 411 if (bootverbose) 412 printf("%s%s\n", sc->duplex? ", duplex" : "", 413 sc->newspeed? ", newspeed" : ""); 414 415 if (sc->newspeed) 416 ess_setmixer(sc, 0x71, 0x22); 417 418 bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, ess_intr, sc, &sc->ih); 419 if (!sc->duplex) 420 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); 421 422 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 423 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 424 /*highaddr*/BUS_SPACE_MAXADDR, 425 /*filter*/NULL, /*filterarg*/NULL, 426 /*maxsize*/ESS_BUFFSIZE, /*nsegments*/1, 427 /*maxsegz*/0x3ffff, 428 /*flags*/0, &sc->parent_dmat) != 0) { 429 device_printf(dev, "unable to create dma tag\n"); 430 goto no; 431 } 432 433 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld", 434 rman_get_start(sc->io_base), rman_get_start(sc->irq), 435 rman_get_start(sc->drq1)); 436 if (sc->drq2) 437 snprintf(status + strlen(status), SND_STATUSLEN - strlen(status), 438 ":%ld", rman_get_start(sc->drq2)); 439 440 if (pcm_register(dev, sc, 1, 1)) 441 goto no; 442 pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sc); 443 pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sc); 444 pcm_setstatus(dev, status); 445 446 return 0; 447 448no: 449 ess_release_resources(sc, dev); 450 return ENXIO; 451} 452 453static int 454ess_detach(device_t dev) 455{ 456 int r; 457 struct ess_info *sc; 458 459 r = pcm_unregister(dev); 460 if (r) 461 return r; 462 463 sc = pcm_getdevinfo(dev); 464 ess_release_resources(sc, dev); 465 return 0; 466} 467 | |
468static void 469ess_intr(void *arg) 470{ 471 struct ess_info *sc = (struct ess_info *)arg; 472 int src, pirq, rirq; 473 474 src = 0; 475 if (ess_getmixer(sc, 0x7a) & 0x80) 476 src |= 2; 477 if (ess_rd(sc, 0x0c) & 0x01) 478 src |= 1; 479 480 pirq = (src & sc->pch.hwch)? 1 : 0; 481 rirq = (src & sc->rch.hwch)? 1 : 0; 482 483 if (pirq) { | 341static void 342ess_intr(void *arg) 343{ 344 struct ess_info *sc = (struct ess_info *)arg; 345 int src, pirq, rirq; 346 347 src = 0; 348 if (ess_getmixer(sc, 0x7a) & 0x80) 349 src |= 2; 350 if (ess_rd(sc, 0x0c) & 0x01) 351 src |= 1; 352 353 pirq = (src & sc->pch.hwch)? 1 : 0; 354 rirq = (src & sc->rch.hwch)? 1 : 0; 355 356 if (pirq) { |
357 if (!sc->pch.run) 358 printf("ess: play intr while not running\n"); |
|
484 if (sc->pch.stopping) { | 359 if (sc->pch.stopping) { |
360 sc->pch.run = 0; |
|
485 buf_isadma(sc->pch.buffer, PCMTRIG_STOP); 486 sc->pch.stopping = 0; 487 if (sc->pch.hwch == 1) 488 ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01); 489 else 490 ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x03); 491 } 492 chn_intr(sc->pch.channel); 493 } 494 495 if (rirq) { | 361 buf_isadma(sc->pch.buffer, PCMTRIG_STOP); 362 sc->pch.stopping = 0; 363 if (sc->pch.hwch == 1) 364 ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01); 365 else 366 ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x03); 367 } 368 chn_intr(sc->pch.channel); 369 } 370 371 if (rirq) { |
372 if (!sc->rch.run) 373 printf("ess: record intr while not running\n"); |
|
496 if (sc->rch.stopping) { | 374 if (sc->rch.stopping) { |
375 sc->rch.run = 0; |
|
497 buf_isadma(sc->rch.buffer, PCMTRIG_STOP); 498 sc->rch.stopping = 0; 499 /* XXX: will this stop audio2? */ 500 ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01); 501 } 502 chn_intr(sc->rch.channel); 503 } 504 --- 147 unchanged lines hidden (view full) --- 652 ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x04); 653 else 654 ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x10); 655 if (play) 656 ess_cmd(sc, DSP_CMD_SPKOFF); 657 return 0; 658} 659 | 376 buf_isadma(sc->rch.buffer, PCMTRIG_STOP); 377 sc->rch.stopping = 0; 378 /* XXX: will this stop audio2? */ 379 ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01); 380 } 381 chn_intr(sc->rch.channel); 382 } 383 --- 147 unchanged lines hidden (view full) --- 531 ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x04); 532 else 533 ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x10); 534 if (play) 535 ess_cmd(sc, DSP_CMD_SPKOFF); 536 return 0; 537} 538 |
539/* -------------------------------------------------------------------- */ |
|
660/* channel interface for ESS18xx */ 661static void * | 540/* channel interface for ESS18xx */ 541static void * |
662esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) | 542esschan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) |
663{ 664 struct ess_info *sc = devinfo; 665 struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; 666 667 ch->parent = sc; 668 ch->channel = c; 669 ch->buffer = b; 670 ch->buffer->bufsize = ESS_BUFFSIZE; 671 if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1) 672 return NULL; 673 ch->dir = dir; 674 ch->hwch = 1; 675 if ((dir == PCMDIR_PLAY) && (sc->duplex)) 676 ch->hwch = 2; 677 ch->buffer->chan = rman_get_start((ch->hwch == 1)? sc->drq1 : sc->drq2); 678 return ch; 679} 680 681static int | 543{ 544 struct ess_info *sc = devinfo; 545 struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; 546 547 ch->parent = sc; 548 ch->channel = c; 549 ch->buffer = b; 550 ch->buffer->bufsize = ESS_BUFFSIZE; 551 if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1) 552 return NULL; 553 ch->dir = dir; 554 ch->hwch = 1; 555 if ((dir == PCMDIR_PLAY) && (sc->duplex)) 556 ch->hwch = 2; 557 ch->buffer->chan = rman_get_start((ch->hwch == 1)? sc->drq1 : sc->drq2); 558 return ch; 559} 560 561static int |
682esschan_setformat(void *data, u_int32_t format) | 562esschan_setformat(kobj_t obj, void *data, u_int32_t format) |
683{ 684 struct ess_chinfo *ch = data; 685 686 ch->fmt = format; 687 return 0; 688} 689 690static int | 563{ 564 struct ess_chinfo *ch = data; 565 566 ch->fmt = format; 567 return 0; 568} 569 570static int |
691esschan_setspeed(void *data, u_int32_t speed) | 571esschan_setspeed(kobj_t obj, void *data, u_int32_t speed) |
692{ 693 struct ess_chinfo *ch = data; 694 struct ess_info *sc = ch->parent; 695 696 ch->spd = speed; 697 if (sc->newspeed) 698 ess_calcspeed9(&ch->spd); 699 else 700 ess_calcspeed8(&ch->spd); 701 return ch->spd; 702} 703 704static int | 572{ 573 struct ess_chinfo *ch = data; 574 struct ess_info *sc = ch->parent; 575 576 ch->spd = speed; 577 if (sc->newspeed) 578 ess_calcspeed9(&ch->spd); 579 else 580 ess_calcspeed8(&ch->spd); 581 return ch->spd; 582} 583 584static int |
705esschan_setblocksize(void *data, u_int32_t blocksize) | 585esschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) |
706{ 707 return blocksize; 708} 709 710static int | 586{ 587 return blocksize; 588} 589 590static int |
711esschan_trigger(void *data, int go) | 591esschan_trigger(kobj_t obj, void *data, int go) |
712{ 713 struct ess_chinfo *ch = data; 714 715 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 716 return 0; 717 718 switch (go) { 719 case PCMTRIG_START: | 592{ 593 struct ess_chinfo *ch = data; 594 595 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) 596 return 0; 597 598 switch (go) { 599 case PCMTRIG_START: |
600 ch->run = 1; |
|
720 buf_isadma(ch->buffer, go); 721 ess_start(ch); 722 break; 723 724 case PCMTRIG_STOP: 725 case PCMTRIG_ABORT: 726 default: 727 ess_stop(ch); 728 break; 729 } 730 return 0; 731} 732 733static int | 601 buf_isadma(ch->buffer, go); 602 ess_start(ch); 603 break; 604 605 case PCMTRIG_STOP: 606 case PCMTRIG_ABORT: 607 default: 608 ess_stop(ch); 609 break; 610 } 611 return 0; 612} 613 614static int |
734esschan_getptr(void *data) | 615esschan_getptr(kobj_t obj, void *data) |
735{ 736 struct ess_chinfo *ch = data; 737 738 return buf_isadmaptr(ch->buffer); 739} 740 741static pcmchan_caps * | 616{ 617 struct ess_chinfo *ch = data; 618 619 return buf_isadmaptr(ch->buffer); 620} 621 622static pcmchan_caps * |
742esschan_getcaps(void *data) | 623esschan_getcaps(kobj_t obj, void *data) |
743{ 744 struct ess_chinfo *ch = data; 745 746 return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; 747} 748 | 624{ 625 struct ess_chinfo *ch = data; 626 627 return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps; 628} 629 |
630static kobj_method_t esschan_methods[] = { 631 KOBJMETHOD(channel_init, esschan_init), 632 KOBJMETHOD(channel_setformat, esschan_setformat), 633 KOBJMETHOD(channel_setspeed, esschan_setspeed), 634 KOBJMETHOD(channel_setblocksize, esschan_setblocksize), 635 KOBJMETHOD(channel_trigger, esschan_trigger), 636 KOBJMETHOD(channel_getptr, esschan_getptr), 637 KOBJMETHOD(channel_getcaps, esschan_getcaps), 638 { 0, 0 } 639}; 640CHANNEL_DECLARE(esschan); 641 |
|
749/************************************************************/ 750 751static int 752essmix_init(snd_mixer *m) 753{ 754 struct ess_info *sc = mix_getdevinfo(m); 755 756 mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE | --- 94 unchanged lines hidden (view full) --- 851 break; 852 } 853 854 ess_setmixer(sc, 0x1c, recdev); 855 856 return src; 857} 858 | 642/************************************************************/ 643 644static int 645essmix_init(snd_mixer *m) 646{ 647 struct ess_info *sc = mix_getdevinfo(m); 648 649 mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE | --- 94 unchanged lines hidden (view full) --- 744 break; 745 } 746 747 ess_setmixer(sc, 0x1c, recdev); 748 749 return src; 750} 751 |
752static kobj_method_t essmixer_methods[] = { 753 KOBJMETHOD(mixer_init, essmix_init), 754 KOBJMETHOD(mixer_set, essmix_set), 755 KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc), 756 { 0, 0 } 757}; 758MIXER_DECLARE(essmixer); 759 760/************************************************************/ 761 |
|
859static int 860ess_probe(device_t dev) 861{ 862 uintptr_t func, ver, r, f; 863 864 /* The parent device has already been probed. */ 865 r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func); 866 if (func != SCF_PCM) --- 8 unchanged lines hidden (view full) --- 875 876 return 0; 877} 878 879static int 880ess_attach(device_t dev) 881{ 882 struct ess_info *sc; | 762static int 763ess_probe(device_t dev) 764{ 765 uintptr_t func, ver, r, f; 766 767 /* The parent device has already been probed. */ 768 r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func); 769 if (func != SCF_PCM) --- 8 unchanged lines hidden (view full) --- 778 779 return 0; 780} 781 782static int 783ess_attach(device_t dev) 784{ 785 struct ess_info *sc; |
786 char status[SND_STATUSLEN], buf[64]; 787 int ver; |
|
883 884 sc = (struct ess_info *)malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); 885 if (!sc) 886 return ENXIO; 887 bzero(sc, sizeof *sc); 888 | 788 789 sc = (struct ess_info *)malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); 790 if (!sc) 791 return ENXIO; 792 bzero(sc, sizeof *sc); 793 |
889 return ess_doattach(dev, sc); | 794 if (ess_alloc_resources(sc, dev)) 795 goto no; 796 if (ess_reset_dsp(sc)) 797 goto no; 798 if (mixer_init(dev, &essmixer_class, sc)) 799 goto no; 800 801 sc->duplex = 0; 802 sc->newspeed = 0; 803 ver = (ess_getmixer(sc, 0x40) << 8) | ess_rd(sc, SB_MIX_DATA); 804 snprintf(buf, sizeof buf, "ESS %x DSP", ver); 805 device_set_desc_copy(dev, buf); 806 if (bootverbose) 807 device_printf(dev, "ESS%x detected", ver); 808 809 switch (ver) { 810 case 0x1869: 811 case 0x1879: 812#ifdef ESS18XX_DUPLEX 813 sc->duplex = sc->drq2? 1 : 0; 814#endif 815#ifdef ESS18XX_NEWSPEED 816 sc->newspeed = 1; 817#endif 818 break; 819 } 820 if (bootverbose) 821 printf("%s%s\n", sc->duplex? ", duplex" : "", 822 sc->newspeed? ", newspeed" : ""); 823 824 if (sc->newspeed) 825 ess_setmixer(sc, 0x71, 0x22); 826 827 bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, ess_intr, sc, &sc->ih); 828 if (!sc->duplex) 829 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); 830 831 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 832 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 833 /*highaddr*/BUS_SPACE_MAXADDR, 834 /*filter*/NULL, /*filterarg*/NULL, 835 /*maxsize*/ESS_BUFFSIZE, /*nsegments*/1, 836 /*maxsegz*/0x3ffff, 837 /*flags*/0, &sc->parent_dmat) != 0) { 838 device_printf(dev, "unable to create dma tag\n"); 839 goto no; 840 } 841 842 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld", 843 rman_get_start(sc->io_base), rman_get_start(sc->irq), 844 rman_get_start(sc->drq1)); 845 if (sc->drq2) 846 snprintf(status + strlen(status), SND_STATUSLEN - strlen(status), 847 ":%ld", rman_get_start(sc->drq2)); 848 849 if (pcm_register(dev, sc, 1, 1)) 850 goto no; 851 pcm_addchan(dev, PCMDIR_REC, &esschan_class, sc); 852 pcm_addchan(dev, PCMDIR_PLAY, &esschan_class, sc); 853 pcm_setstatus(dev, status); 854 855 return 0; 856 857no: 858 ess_release_resources(sc, dev); 859 return ENXIO; |
890} 891 | 860} 861 |
862static int 863ess_detach(device_t dev) 864{ 865 int r; 866 struct ess_info *sc; 867 868 r = pcm_unregister(dev); 869 if (r) 870 return r; 871 872 sc = pcm_getdevinfo(dev); 873 ess_release_resources(sc, dev); 874 return 0; 875} 876 |
|
892static device_method_t ess_methods[] = { 893 /* Device interface */ 894 DEVMETHOD(device_probe, ess_probe), 895 DEVMETHOD(device_attach, ess_attach), 896 DEVMETHOD(device_detach, ess_detach), 897 898 { 0, 0 } 899}; 900 901static driver_t ess_driver = { 902 "pcm", 903 ess_methods, 904 sizeof(snddev_info), 905}; 906 907DRIVER_MODULE(snd_ess, sbc, ess_driver, pcm_devclass, 0, 0); 908MODULE_DEPEND(snd_ess, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 909MODULE_VERSION(snd_ess, 1); 910 | 877static device_method_t ess_methods[] = { 878 /* Device interface */ 879 DEVMETHOD(device_probe, ess_probe), 880 DEVMETHOD(device_attach, ess_attach), 881 DEVMETHOD(device_detach, ess_detach), 882 883 { 0, 0 } 884}; 885 886static driver_t ess_driver = { 887 "pcm", 888 ess_methods, 889 sizeof(snddev_info), 890}; 891 892DRIVER_MODULE(snd_ess, sbc, ess_driver, pcm_devclass, 0, 0); 893MODULE_DEPEND(snd_ess, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 894MODULE_VERSION(snd_ess, 1); 895 |
896/************************************************************/ |
|
911 912static devclass_t esscontrol_devclass; 913 914static struct isa_pnp_id essc_ids[] = { 915 {0x06007316, "ESS Control"}, 916 {0} 917}; 918 --- 55 unchanged lines hidden --- | 897 898static devclass_t esscontrol_devclass; 899 900static struct isa_pnp_id essc_ids[] = { 901 {0x06007316, "ESS Control"}, 902 {0} 903}; 904 --- 55 unchanged lines hidden --- |