1 /* 2 * Copyright (c) 2000 Dmitry Dicky diwil@dataart.com 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include <dev/sound/pcm/sound.h> 30 #include <dev/sound/pcm/ac97.h> 31 #include <pci/pcireg.h> 32 #include <pci/pcivar.h> 33 34 #define PCI_VENDOR_FORTEMEDIA 0x1319 35 #define PCI_DEVICE_FORTEMEDIA1 0x08011319 36 #define PCI_DEVICE_FORTEMEDIA2 0x08021319 /* ??? have no idea what's this... */ 37 38 #define FM_PCM_VOLUME 0x00 39 #define FM_FM_VOLUME 0x02 40 #define FM_I2S_VOLUME 0x04 41 #define FM_RECORD_SOURCE 0x06 42 43 #define FM_PLAY_CTL 0x08 44 #define FM_PLAY_RATE_MASK 0x0f00 45 #define FM_PLAY_BUF1_LAST 0x0001 46 #define FM_PLAY_BUF2_LAST 0x0002 47 #define FM_PLAY_START 0x0020 48 #define FM_PLAY_PAUSE 0x0040 49 #define FM_PLAY_STOPNOW 0x0080 50 #define FM_PLAY_16BIT 0x4000 51 #define FM_PLAY_STEREO 0x8000 52 53 #define FM_PLAY_DMALEN 0x0a 54 #define FM_PLAY_DMABUF1 0x0c 55 #define FM_PLAY_DMABUF2 0x10 56 57 58 #define FM_REC_CTL 0x14 59 #define FM_REC_RATE_MASK 0x0f00 60 #define FM_REC_BUF1_LAST 0x0001 61 #define FM_REC_BUF2_LAST 0x0002 62 #define FM_REC_START 0x0020 63 #define FM_REC_PAUSE 0x0040 64 #define FM_REC_STOPNOW 0x0080 65 #define FM_REC_16BIT 0x4000 66 #define FM_REC_STEREO 0x8000 67 68 69 #define FM_REC_DMALEN 0x16 70 #define FM_REC_DMABUF1 0x18 71 #define FM_REC_DMABUF2 0x1c 72 73 #define FM_CODEC_CTL 0x22 74 #define FM_VOLUME 0x26 75 #define FM_VOLUME_MUTE 0x8000 76 77 #define FM_CODEC_CMD 0x2a 78 #define FM_CODEC_CMD_READ 0x0080 79 #define FM_CODEC_CMD_VALID 0x0100 80 #define FM_CODEC_CMD_BUSY 0x0200 81 82 #define FM_CODEC_DATA 0x2c 83 84 #define FM_IO_CTL 0x52 85 #define FM_CARD_CTL 0x54 86 87 #define FM_INTMASK 0x56 88 #define FM_INTMASK_PLAY 0x0001 89 #define FM_INTMASK_REC 0x0002 90 #define FM_INTMASK_VOL 0x0040 91 #define FM_INTMASK_MPU 0x0080 92 93 #define FM_INTSTATUS 0x5a 94 #define FM_INTSTATUS_PLAY 0x0100 95 #define FM_INTSTATUS_REC 0x0200 96 #define FM_INTSTATUS_VOL 0x4000 97 #define FM_INTSTATUS_MPU 0x8000 98 99 #define FM801_BUFFSIZE 1024*4 /* Other values do not work!!! */ 100 101 /* debug purposes */ 102 #define DPRINT if(0) printf 103 104 105 /* channel interface */ 106 static void *fm801ch_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 107 static int fm801ch_setformat(void *data, u_int32_t format); 108 static int fm801ch_setspeed(void *data, u_int32_t speed); 109 static int fm801ch_setblocksize(void *data, u_int32_t blocksize); 110 static int fm801ch_trigger(void *data, int go); 111 static int fm801ch_getptr(void *data); 112 static pcmchan_caps *fm801ch_getcaps(void *data); 113 /* 114 static int fm801ch_setup(pcm_channel *c); 115 */ 116 117 static u_int32_t fmts[] = { 118 AFMT_U8, 119 AFMT_STEREO | AFMT_U8, 120 AFMT_S16_LE, 121 AFMT_STEREO | AFMT_S16_LE, 122 0 123 }; 124 125 static pcmchan_caps fm801ch_caps = { 126 4000, 48000, 127 fmts, 0 128 }; 129 130 static pcm_channel fm801_chantemplate = { 131 fm801ch_init, 132 NULL, /* setdir */ 133 fm801ch_setformat, 134 fm801ch_setspeed, 135 fm801ch_setblocksize, 136 fm801ch_trigger, 137 fm801ch_getptr, 138 fm801ch_getcaps, 139 NULL, /* free */ 140 NULL, /* nop1 */ 141 NULL, /* nop2 */ 142 NULL, /* nop3 */ 143 NULL, /* nop4 */ 144 NULL, /* nop5 */ 145 NULL, /* nop6 */ 146 NULL, /* nop7 */ 147 }; 148 149 struct fm801_info; 150 151 struct fm801_chinfo { 152 struct fm801_info *parent; 153 pcm_channel *channel; 154 snd_dbuf *buffer; 155 u_int32_t spd, dir, fmt; /* speed, direction, format */ 156 u_int32_t shift; 157 }; 158 159 struct fm801_info { 160 int type; 161 bus_space_tag_t st; 162 bus_space_handle_t sh; 163 bus_dma_tag_t parent_dmat; 164 165 device_t dev; 166 int num; 167 u_int32_t unit; 168 169 struct resource *reg, *irq; 170 int regtype, regid, irqid; 171 void *ih; 172 173 u_int32_t play_flip, 174 play_nextblk, 175 play_start, 176 play_blksize, 177 play_fmt, 178 play_shift, 179 play_size; 180 181 u_int32_t rec_flip, 182 rec_nextblk, 183 rec_start, 184 rec_blksize, 185 rec_fmt, 186 rec_shift, 187 rec_size; 188 189 struct fm801_chinfo pch, rch; 190 }; 191 192 /* Bus Read / Write routines */ 193 static u_int32_t 194 fm801_rd(struct fm801_info *fm801, int regno, int size) 195 { 196 switch(size) { 197 case 1: 198 return (bus_space_read_1(fm801->st, fm801->sh, regno)); 199 case 2: 200 return (bus_space_read_2(fm801->st, fm801->sh, regno)); 201 case 4: 202 return (bus_space_read_4(fm801->st, fm801->sh, regno)); 203 default: 204 return 0xffffffff; 205 } 206 } 207 208 static void 209 fm801_wr(struct fm801_info *fm801, int regno, u_int32_t data, int size) 210 { 211 switch(size) { 212 case 1: 213 return bus_space_write_1(fm801->st, fm801->sh, regno, data); 214 case 2: 215 return bus_space_write_2(fm801->st, fm801->sh, regno, data); 216 case 4: 217 return bus_space_write_4(fm801->st, fm801->sh, regno, data); 218 default: 219 return; 220 } 221 } 222 223 /* 224 * ac97 codec routines 225 */ 226 #define TIMO 50 227 static u_int32_t 228 fm801_rdcd(void *devinfo, int regno) 229 { 230 struct fm801_info *fm801 = (struct fm801_info *)devinfo; 231 int i; 232 233 for (i = 0; i < TIMO && fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_BUSY; i++) { 234 DELAY(10000); 235 DPRINT("fm801 rdcd: 1 - DELAY\n"); 236 } 237 if (i >= TIMO) { 238 printf("fm801 rdcd: codec busy\n"); 239 return 0; 240 } 241 242 fm801_wr(fm801,FM_CODEC_CMD, regno|FM_CODEC_CMD_READ,2); 243 244 for (i = 0; i < TIMO && !(fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_VALID); i++) 245 { 246 DELAY(10000); 247 DPRINT("fm801 rdcd: 2 - DELAY\n"); 248 } 249 if (i >= TIMO) { 250 printf("fm801 rdcd: write codec invalid\n"); 251 return 0; 252 } 253 254 return fm801_rd(fm801,FM_CODEC_DATA,2); 255 } 256 257 static void 258 fm801_wrcd(void *devinfo, int regno, u_int32_t data) 259 { 260 struct fm801_info *fm801 = (struct fm801_info *)devinfo; 261 int i; 262 263 DPRINT("fm801_wrcd reg 0x%x val 0x%x\n",regno, data); 264 /* 265 if(regno == AC97_REG_RECSEL) return; 266 */ 267 /* Poll until codec is ready */ 268 for (i = 0; i < TIMO && fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_BUSY; i++) { 269 DELAY(10000); 270 DPRINT("fm801 rdcd: 1 - DELAY\n"); 271 } 272 if (i >= TIMO) { 273 printf("fm801 wrcd: read codec busy\n"); 274 return; 275 } 276 277 fm801_wr(fm801,FM_CODEC_DATA,data, 2); 278 fm801_wr(fm801,FM_CODEC_CMD, regno,2); 279 280 /* wait until codec is ready */ 281 for (i = 0; i < TIMO && fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_BUSY; i++) { 282 DELAY(10000); 283 DPRINT("fm801 wrcd: 2 - DELAY\n"); 284 } 285 if (i >= TIMO) { 286 printf("fm801 wrcd: read codec busy\n"); 287 return; 288 } 289 DPRINT("fm801 wrcd release reg 0x%x val 0x%x\n",regno, data); 290 return; 291 } 292 293 /* 294 * The interrupt handler 295 */ 296 static void 297 fm801_intr(void *p) 298 { 299 struct fm801_info *fm801 = (struct fm801_info *)p; 300 u_int32_t intsrc = fm801_rd(fm801, FM_INTSTATUS, 2); 301 struct fm801_chinfo *ch = &(fm801->pch); 302 snd_dbuf *b = ch->buffer; 303 304 DPRINT("\nfm801_intr intsrc 0x%x ", intsrc); 305 DPRINT("rp %d, rl %d, fp %d fl %d, size=%d\n", 306 b->rp,b->rl, b->fp,b->fl, b->blksz); 307 308 if(intsrc & FM_INTSTATUS_PLAY) { 309 fm801->play_flip++; 310 if(fm801->play_flip & 1) { 311 fm801_wr(fm801, FM_PLAY_DMABUF1, fm801->play_start,4); 312 } else 313 fm801_wr(fm801, FM_PLAY_DMABUF2, fm801->play_nextblk,4); 314 chn_intr(fm801->pch.channel); 315 } 316 317 if(intsrc & FM_INTSTATUS_REC) { 318 fm801->rec_flip++; 319 if(fm801->rec_flip & 1) { 320 fm801_wr(fm801, FM_REC_DMABUF1, fm801->rec_start,4); 321 } else 322 fm801_wr(fm801, FM_REC_DMABUF2, fm801->rec_nextblk,4); 323 chn_intr(fm801->rch.channel); 324 } 325 326 if ( intsrc & FM_INTSTATUS_MPU ) { 327 /* This is a TODOish thing... */ 328 fm801_wr(fm801, FM_INTSTATUS, intsrc & FM_INTSTATUS_MPU,2); 329 } 330 331 if ( intsrc & FM_INTSTATUS_VOL ) { 332 /* This is a TODOish thing... */ 333 fm801_wr(fm801, FM_INTSTATUS, intsrc & FM_INTSTATUS_VOL,2); 334 } 335 336 DPRINT("fm801_intr clear\n\n"); 337 fm801_wr(fm801, FM_INTSTATUS, intsrc & (FM_INTSTATUS_PLAY | FM_INTSTATUS_REC), 2); 338 } 339 340 /* 341 * Init routine is taken from an original NetBSD driver 342 */ 343 static int 344 fm801_init(struct fm801_info *fm801) 345 { 346 u_int32_t k1; 347 348 /* reset codec */ 349 fm801_wr(fm801, FM_CODEC_CTL, 0x0020,2); 350 DELAY(100000); 351 fm801_wr(fm801, FM_CODEC_CTL, 0x0000,2); 352 DELAY(100000); 353 354 fm801_wr(fm801, FM_PCM_VOLUME, 0x0808,2); 355 fm801_wr(fm801, FM_FM_VOLUME, 0x0808,2); 356 fm801_wr(fm801, FM_I2S_VOLUME, 0x0808,2); 357 fm801_wr(fm801, 0x40,0x107f,2); /* enable legacy audio */ 358 359 fm801_wr((void *)fm801, FM_RECORD_SOURCE, 0x0000,2); 360 361 /* Unmask playback, record and mpu interrupts, mask the rest */ 362 k1 = fm801_rd((void *)fm801, FM_INTMASK,2); 363 fm801_wr(fm801, FM_INTMASK, 364 (k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) | 365 FM_INTMASK_VOL,2); 366 fm801_wr(fm801, FM_INTSTATUS, 367 FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU | 368 FM_INTSTATUS_VOL,2); 369 370 DPRINT("FM801 init Ok\n"); 371 return 0; 372 } 373 374 static int 375 fm801_pci_attach(device_t dev) 376 { 377 u_int32_t data; 378 struct ac97_info *codec = 0; 379 struct fm801_info *fm801; 380 int i; 381 int mapped = 0; 382 char status[SND_STATUSLEN]; 383 384 if ((fm801 = (struct fm801_info *)malloc(sizeof(*fm801),M_DEVBUF, M_NOWAIT)) == NULL) { 385 device_printf(dev, "cannot allocate softc\n"); 386 return ENXIO; 387 } 388 389 bzero(fm801, sizeof(*fm801)); 390 fm801->type = pci_get_devid(dev); 391 392 data = pci_read_config(dev, PCIR_COMMAND, 2); 393 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 394 pci_write_config(dev, PCIR_COMMAND, data, 2); 395 data = pci_read_config(dev, PCIR_COMMAND, 2); 396 397 for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) { 398 fm801->regid = PCIR_MAPS + i*4; 399 fm801->regtype = SYS_RES_MEMORY; 400 fm801->reg = bus_alloc_resource(dev, fm801->regtype, &fm801->regid, 401 0, ~0, 1, RF_ACTIVE); 402 if(!fm801->reg) 403 { 404 fm801->regtype = SYS_RES_IOPORT; 405 fm801->reg = bus_alloc_resource(dev, fm801->regtype, &fm801->regid, 406 0, ~0, 1, RF_ACTIVE); 407 } 408 409 if(fm801->reg) { 410 fm801->st = rman_get_bustag(fm801->reg); 411 fm801->sh = rman_get_bushandle(fm801->reg); 412 mapped++; 413 } 414 } 415 416 if (mapped == 0) { 417 device_printf(dev, "unable to map register space\n"); 418 goto oops; 419 } 420 421 fm801_init(fm801); 422 423 codec = ac97_create(dev, (void *)fm801, NULL, fm801_rdcd, fm801_wrcd); 424 if (codec == NULL) goto oops; 425 426 if (mixer_init(dev, &ac97_mixer, codec) == -1) goto oops; 427 428 fm801->irqid = 0; 429 fm801->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &fm801->irqid, 430 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 431 if (!fm801->irq || 432 bus_setup_intr(dev, fm801->irq, INTR_TYPE_TTY, 433 fm801_intr, fm801, &fm801->ih)) { 434 device_printf(dev, "unable to map interrupt\n"); 435 goto oops; 436 } 437 438 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 439 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 440 /*highaddr*/BUS_SPACE_MAXADDR, 441 /*filter*/NULL, /*filterarg*/NULL, 442 /*maxsize*/FM801_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff, 443 /*flags*/0, &fm801->parent_dmat) != 0) { 444 device_printf(dev, "unable to create dma tag\n"); 445 goto oops; 446 } 447 448 snprintf(status, 64, "at %s 0x%lx irq %ld", 449 (fm801->regtype == SYS_RES_IOPORT)? "io" : "memory", 450 rman_get_start(fm801->reg), rman_get_start(fm801->irq)); 451 452 #define FM801_MAXPLAYCH 1 453 if (pcm_register(dev, fm801, FM801_MAXPLAYCH, 1)) goto oops; 454 pcm_addchan(dev, PCMDIR_PLAY, &fm801_chantemplate, fm801); 455 pcm_addchan(dev, PCMDIR_REC, &fm801_chantemplate, fm801); 456 pcm_setstatus(dev, status); 457 458 return 0; 459 460 oops: 461 if (codec) ac97_destroy(codec); 462 if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg); 463 if (fm801->ih) bus_teardown_intr(dev, fm801->irq, fm801->ih); 464 if (fm801->irq) bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq); 465 if (fm801->parent_dmat) bus_dma_tag_destroy(fm801->parent_dmat); 466 free(fm801, M_DEVBUF); 467 return ENXIO; 468 } 469 470 static int 471 fm801_pci_detach(device_t dev) 472 { 473 int r; 474 struct fm801_info *fm801; 475 476 DPRINT("Forte Media FM801 detach\n"); 477 478 r = pcm_unregister(dev); 479 if (r) 480 return r; 481 482 fm801 = pcm_getdevinfo(dev); 483 bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg); 484 bus_teardown_intr(dev, fm801->irq, fm801->ih); 485 bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq); 486 bus_dma_tag_destroy(fm801->parent_dmat); 487 free(fm801, M_DEVBUF); 488 return 0; 489 } 490 491 static int 492 fm801_pci_probe( device_t dev ) 493 { 494 int id; 495 if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA1 ) { 496 device_set_desc(dev, "Forte Media FM801 Audio Controller"); 497 return 0; 498 } 499 /* 500 if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA2 ) { 501 device_set_desc(dev, "Forte Media FM801 Joystick (Not Supported)"); 502 return ENXIO; 503 } 504 */ 505 return ENXIO; 506 } 507 508 509 510 /* channel interface */ 511 static void * 512 fm801ch_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 513 { 514 struct fm801_info *fm801 = (struct fm801_info *)devinfo; 515 struct fm801_chinfo *ch = (dir == PCMDIR_PLAY)? &fm801->pch : &fm801->rch; 516 517 DPRINT("fm801ch_init, direction = %d\n", dir); 518 ch->parent = fm801; 519 ch->channel = c; 520 ch->buffer = b; 521 ch->buffer->bufsize = FM801_BUFFSIZE; 522 ch->dir = dir; 523 if( chn_allocbuf(ch->buffer, fm801->parent_dmat) == -1) return NULL; 524 return (void *)ch; 525 } 526 527 static int 528 fm801ch_setformat(void *data, u_int32_t format) 529 { 530 struct fm801_chinfo *ch = data; 531 struct fm801_info *fm801 = ch->parent; 532 533 DPRINT("fm801ch_setformat 0x%x : %s, %s, %s, %s\n", format, 534 (format & AFMT_STEREO)?"stereo":"mono", 535 (format & (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)) ? "16bit":"8bit", 536 (format & AFMT_SIGNED)? "signed":"unsigned", 537 (format & AFMT_BIGENDIAN)?"bigendiah":"littleendian" ); 538 539 if(ch->dir == PCMDIR_PLAY) { 540 fm801->play_fmt = (format & AFMT_STEREO)? FM_PLAY_STEREO : 0; 541 fm801->play_fmt |= (format & AFMT_16BIT) ? FM_PLAY_16BIT : 0; 542 return 0; 543 } 544 545 if(ch->dir == PCMDIR_REC ) { 546 fm801->rec_fmt = (format & AFMT_STEREO)? FM_REC_STEREO:0; 547 fm801->rec_fmt |= (format & AFMT_16BIT) ? FM_PLAY_16BIT : 0; 548 return 0; 549 } 550 551 return 0; 552 } 553 554 struct { 555 int limit; 556 int rate; 557 } fm801_rates[11] = { 558 { 6600, 5500 }, 559 { 8750, 8000 }, 560 { 10250, 9600 }, 561 { 13200, 11025 }, 562 { 17500, 16000 }, 563 { 20500, 19200 }, 564 { 26500, 22050 }, 565 { 35000, 32000 }, 566 { 41000, 38400 }, 567 { 46000, 44100 }, 568 { 48000, 48000 }, 569 /* anything above -> 48000 */ 570 }; 571 572 static int 573 fm801ch_setspeed(void *data, u_int32_t speed) 574 { 575 struct fm801_chinfo *ch = data; 576 struct fm801_info *fm801 = ch->parent; 577 register int i; 578 579 580 for (i = 0; i < 10 && fm801_rates[i].limit <= speed; i++) ; 581 582 if(ch->dir == PCMDIR_PLAY) { 583 fm801->pch.spd = fm801_rates[i].rate; 584 fm801->play_shift = (i<<8); 585 fm801->play_shift &= FM_PLAY_RATE_MASK; 586 } 587 588 if(ch->dir == PCMDIR_REC ) { 589 fm801->rch.spd = fm801_rates[i].rate; 590 fm801->rec_shift = (i<<8); 591 fm801->rec_shift &= FM_REC_RATE_MASK; 592 } 593 594 ch->spd = fm801_rates[i].rate; 595 596 return fm801_rates[i].rate; 597 } 598 599 static int 600 fm801ch_setblocksize(void *data, u_int32_t blocksize) 601 { 602 struct fm801_chinfo *ch = data; 603 struct fm801_info *fm801 = ch->parent; 604 605 if(ch->dir == PCMDIR_PLAY) { 606 if(fm801->play_flip) return fm801->play_blksize; 607 fm801->play_blksize = blocksize; 608 } 609 610 if(ch->dir == PCMDIR_REC) { 611 if(fm801->rec_flip) return fm801->rec_blksize; 612 fm801->rec_blksize = blocksize; 613 } 614 615 DPRINT("fm801ch_setblocksize %d (dir %d)\n",blocksize, ch->dir); 616 617 return blocksize; 618 } 619 620 static int 621 fm801ch_trigger(void *data, int go) 622 { 623 struct fm801_chinfo *ch = data; 624 struct fm801_info *fm801 = ch->parent; 625 u_int32_t baseaddr = vtophys(ch->buffer->buf); 626 snd_dbuf *b = ch->buffer; 627 u_int32_t k1; 628 629 DPRINT("fm801ch_trigger go %d , ", go); 630 DPRINT("rp %d, rl %d, fp %d fl %d, dl %d, blksize=%d\n", 631 b->rp,b->rl, b->fp,b->fl, b->dl, b->blksz); 632 633 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) { 634 return 0; 635 } 636 637 if (ch->dir == PCMDIR_PLAY) { 638 if (go == PCMTRIG_START) { 639 640 fm801->play_start = baseaddr; 641 fm801->play_nextblk = fm801->play_start + fm801->play_blksize; 642 fm801->play_flip = 0; 643 fm801_wr(fm801, FM_PLAY_DMALEN, fm801->play_blksize - 1, 2); 644 fm801_wr(fm801, FM_PLAY_DMABUF1,fm801->play_start,4); 645 fm801_wr(fm801, FM_PLAY_DMABUF2,fm801->play_nextblk,4); 646 fm801_wr(fm801, FM_PLAY_CTL, 647 FM_PLAY_START | FM_PLAY_STOPNOW | fm801->play_fmt | fm801->play_shift, 648 2 ); 649 } else { 650 fm801->play_flip = 0; 651 k1 = fm801_rd(fm801, FM_PLAY_CTL,2); 652 fm801_wr(fm801, FM_PLAY_CTL, 653 (k1 & ~(FM_PLAY_STOPNOW | FM_PLAY_START)) | 654 FM_PLAY_BUF1_LAST | FM_PLAY_BUF2_LAST, 2 ); 655 } 656 } else if(ch->dir == PCMDIR_REC) { 657 if (go == PCMTRIG_START) { 658 fm801->rec_start = baseaddr; 659 fm801->rec_nextblk = fm801->rec_start + fm801->rec_blksize; 660 fm801->rec_flip = 0; 661 fm801_wr(fm801, FM_REC_DMALEN, fm801->rec_blksize - 1, 2); 662 fm801_wr(fm801, FM_REC_DMABUF1,fm801->rec_start,4); 663 fm801_wr(fm801, FM_REC_DMABUF2,fm801->rec_nextblk,4); 664 fm801_wr(fm801, FM_REC_CTL, 665 FM_REC_START | FM_REC_STOPNOW | fm801->rec_fmt | fm801->rec_shift, 666 2 ); 667 } else { 668 fm801->rec_flip = 0; 669 k1 = fm801_rd(fm801, FM_REC_CTL,2); 670 fm801_wr(fm801, FM_REC_CTL, 671 (k1 & ~(FM_REC_STOPNOW | FM_REC_START)) | 672 FM_REC_BUF1_LAST | FM_REC_BUF2_LAST, 2); 673 } 674 } 675 676 return 0; 677 } 678 679 /* Almost ALSA copy */ 680 static int 681 fm801ch_getptr(void *data) 682 { 683 struct fm801_chinfo *ch = data; 684 struct fm801_info *fm801 = ch->parent; 685 int result = 0; 686 snd_dbuf *b = ch->buffer; 687 688 if (ch->dir == PCMDIR_PLAY) { 689 result = fm801_rd(fm801, 690 (fm801->play_flip&1) ? 691 FM_PLAY_DMABUF2:FM_PLAY_DMABUF1, 4) - fm801->play_start; 692 } 693 694 if (ch->dir == PCMDIR_REC) { 695 result = fm801_rd(fm801, 696 (fm801->rec_flip&1) ? 697 FM_REC_DMABUF2:FM_REC_DMABUF1, 4) - fm801->rec_start; 698 } 699 700 DPRINT("fm801ch_getptr:%d, rp %d, rl %d, fp %d fl %d\n", 701 result, b->rp,b->rl, b->fp,b->fl); 702 703 return result; 704 } 705 706 static pcmchan_caps * 707 fm801ch_getcaps(void *data) 708 { 709 return &fm801ch_caps; 710 } 711 712 static device_method_t fm801_methods[] = { 713 /* Device interface */ 714 DEVMETHOD(device_probe, fm801_pci_probe), 715 DEVMETHOD(device_attach, fm801_pci_attach), 716 DEVMETHOD(device_detach, fm801_pci_detach), 717 { 0, 0} 718 }; 719 720 static driver_t fm801_driver = { 721 "pcm", 722 fm801_methods, 723 sizeof(snddev_info), 724 }; 725 726 static devclass_t pcm_devclass; 727 728 DRIVER_MODULE(fm801, pci, fm801_driver, pcm_devclass, 0, 0); 729