1 /* 2 Copyright 1999, Be Incorporated. All Rights Reserved. 3 This file may be used under the terms of the Be Sample Code License. 4 */ 5 #include <string.h> 6 7 #include <ByteOrder.h> 8 #include "R3MediaDefs.h" 9 10 #include "cm_private.h" 11 #include "sound.h" 12 13 #if !defined(_KERNEL_EXPORT_H) 14 #include <KernelExport.h> 15 #endif /* _KERNEL_EXPORT_H */ 16 17 extern int sprintf(char *, const char *, ...); 18 19 20 extern void dump_card(cmedia_pci_dev * card); 21 22 #if !defined(OLDAPI) 23 #if DEBUG 24 #define OLDAPI(x) dprintf x 25 #else 26 #define OLDAPI(x) 27 #endif 28 #endif 29 30 #if DEBUG 31 int32 int_cnt; 32 int32 put_cnt; 33 bigtime_t the_time; 34 #endif 35 36 #if 0 37 /* early Intel kernels forgot to export these functions */ 38 #undef B_HOST_TO_LENDIAN_FLOAT 39 #undef B_HOST_TO_BENDIAN_FLOAT 40 #undef B_LENDIAN_TO_HOST_FLOAT 41 #undef B_BENDIAN_TO_HOST_FLOAT 42 43 static float 44 _swap_float_(float x) 45 { 46 uint32 temp1 = *(uint32*)&x; 47 uint32 temp2 = ((temp1>>24)|((temp1>>8)&0xff00)|((temp1<<8)&0xff0000)| 48 (temp1<<24)); 49 return *(float *)&temp2; 50 } 51 52 #if B_HOST_IS_BENDIAN 53 #define B_HOST_TO_LENDIAN_FLOAT(x) _swap_float_(x) 54 #define B_HOST_TO_BENDIAN_FLOAT(x) ((float)(x)) 55 #define B_LENDIAN_TO_HOST_FLOAT(x) _swap_float_(x) 56 #define B_BENDIAN_TO_HOST_FLOAT(x) ((float)(x)) 57 #else 58 #define B_HOST_TO_LENDIAN_FLOAT(x) ((float)(x)) 59 #define B_HOST_TO_BENDIAN_FLOAT(x) _swap_float_(x) 60 #define B_LENDIAN_TO_HOST_FLOAT(x) ((float)(x)) 61 #define B_BENDIAN_TO_HOST_FLOAT(x) _swap_float_(x) 62 #endif 63 64 #endif 65 66 67 static status_t pcm_open(const char *name, uint32 flags, void **cookie); 68 static status_t pcm_close(void *cookie); 69 static status_t pcm_free(void *cookie); 70 static status_t pcm_control(void *cookie, uint32 op, void *data, size_t len); 71 static status_t pcm_read(void *cookie, off_t pos, void *data, size_t *len); 72 static status_t pcm_write(void *cookie, off_t pos, const void *data, size_t *len); 73 //static status_t pcm_writev(void *cookie, off_t pos, const iovec *vec, size_t count, size_t *len); /* */ 74 75 device_hooks pcm_hooks = { 76 &pcm_open, 77 &pcm_close, 78 &pcm_free, 79 &pcm_control, 80 &pcm_read, 81 &pcm_write, 82 NULL, /* select */ 83 NULL, /* deselect */ 84 NULL, /* readv */ 85 NULL // &pcm_writev /* writev */ 86 }; 87 88 static pcm_cfg default_pcm = { 89 44100.0, /* sample rate */ 90 2, /* channels */ 91 0x2, /* format */ 92 #if B_HOST_IS_BENDIAN 93 1, /* endian (big) */ 94 #else 95 0, /* endian (little) */ 96 #endif 97 0, /* header size */ 98 PLAYBACK_BUF_SIZE, /* these are currently hard-coded */ 99 RECORD_BUF_SIZE /* and cannot be changed without re-compile */ 100 }; 101 102 103 #if 0 104 105 typedef struct { 106 uint8 control; 107 uint8 imask; 108 uint8 regs[0x2e]; 109 } chip_state; 110 111 static void 112 save_state( 113 pcm_dev * port, 114 chip_state * state) 115 { 116 int ix; 117 state->control = get_direct(port->card, 0); 118 state->imask = get_direct(port->card, 1); 119 for (ix=0; ix<0x0e; ix++) { 120 if (ix != 0x28 && ix != 0x29 && ix != 0x1a && ix != 0x1b) { 121 state->regs[ix] = get_indirect(port->card, ix+0x30); 122 } 123 } 124 } 125 126 127 static void 128 restore_state( 129 pcm_dev * port, 130 const chip_state * state) 131 { 132 int ix; 133 set_direct(port->card, 0, state->control, 0xff); 134 for (ix=0; ix<0x0e; ix++) { 135 if (ix != 0x28 && ix != 0x29 && ix != 0x1a && ix != 0x1b) { 136 set_indirect(port->card, ix, state->regs[ix]+0x30, 0xff); 137 } 138 } 139 set_direct(port->card, 1, state->imask, 0xff); 140 } 141 142 143 static void 144 reset_chip( 145 pcm_dev * port) 146 { 147 set_direct(port->card, 0x1b, 0x40, 0x40); 148 snooze(2); 149 set_direct(port->card, 0x1b, 0x00, 0x40); 150 } 151 152 #endif 153 154 155 static void 156 stop_dma( 157 pcm_dev * port) 158 { 159 set_direct(port->card, 0x24, 0x40, 0x40); // mute wave stream 160 set_direct(port->card, 0x02, 0, 0x03); // stop both ch0 and ch1 161 162 set_direct(port->card, 0x02, 0x0c, 0x0c); // reset both ch0 and ch1 163 set_direct(port->card, 0x02, 0, 0x0c); 164 ddprintf(("cmedia_pci: DMA stopped\n")); 165 } 166 167 168 static void 169 start_dma( 170 pcm_dev * port) 171 { 172 int sample_size = 1; 173 174 /* start out with a clean slate */ 175 176 KTRACE(); 177 ddprintf(("cmedia_pci: start_dma()\n")); 178 if (port->config.format == 0x11) { 179 memset((void*)port->card->low_mem, 0x80, port->config.play_buf_size + 180 port->config.rec_buf_size); 181 } 182 else { 183 memset((void *)port->card->low_mem, 0, port->config.play_buf_size + 184 port->config.rec_buf_size); 185 } 186 187 port->wr_cur = port->wr_2; 188 port->wr_silence = port->config.play_buf_size; 189 port->was_written = 0; 190 port->rd_cur = port->rd_2; 191 port->was_read = port->config.rec_buf_size/2; /* how much has been read */ 192 port->wr_total = 0; 193 port->rd_total = 0; 194 195 /* we split the available low memory buffer in a small chunk */ 196 /* for playback, and a large chunk for recording. Then we split */ 197 /* each of those in half for double-buffering. While the DMA */ 198 /* just runs the entire range of the buffer, wrapping around when */ 199 /* done, the count register is set up to generate interrupt after */ 200 /* each half of the buffer. Because of latency requirements, we */ 201 /* will get 187 interrupts a second from playback, and 94 interrupts */ 202 /* a second from recording, at 48 kHz sampling rate, when buffers */ 203 /* are 2048 for playback and 4096 for record. */ 204 205 ddprintf(("play_buf_size %lx rec_buf_size %lx\n", 206 port->config.play_buf_size/2, port->config.rec_buf_size/2)); 207 208 PCI_IO_WR(port->dma_c, ((uint32)port->card->low_phys+ 209 port->config.play_buf_size)&0xff); 210 PCI_IO_WR(port->dma_c+1, (((uint32)port->card->low_phys+ 211 port->config.play_buf_size)>>8)&0xff); 212 PCI_IO_WR(port->dma_c+2, (((uint32)port->card->low_phys+ 213 port->config.play_buf_size)>>16)&0xff); 214 PCI_IO_WR(port->dma_c+3, 0); 215 /* if this is a 16 bit channel, divide transfer count in 2 */ 216 if (port->config.format != 0x11) 217 sample_size *= 2; 218 /* if this is a stereo channel, divide transfer count in 2 */ 219 if (port->config.channels == 2) 220 sample_size *= 2; 221 PCI_IO_WR(port->dma_c+4, (port->config.rec_buf_size/sample_size-1)&0xff); 222 PCI_IO_WR(port->dma_c+5, ((port->config.rec_buf_size/sample_size-1)>>8)&0xff); 223 PCI_IO_WR(port->dma_c+6, (port->rd_size/sample_size-1)&0xff); 224 PCI_IO_WR(port->dma_c+7, ((port->rd_size/sample_size-1)>>8)&0xff); 225 226 PCI_IO_WR(port->dma_a, ((uint32)port->card->low_phys)&0xff); 227 PCI_IO_WR(port->dma_a+1, ((uint32)port->card->low_phys>>8)&0xff); 228 PCI_IO_WR(port->dma_a+2, ((uint32)port->card->low_phys>>16)&0xff); 229 PCI_IO_WR(port->dma_a+3, 0); 230 PCI_IO_WR(port->dma_a+4, (port->config.play_buf_size/sample_size-1)&0xff); 231 PCI_IO_WR(port->dma_a+5, ((port->config.play_buf_size/sample_size-1)>>8)&0xff); 232 PCI_IO_WR(port->dma_a+6, (port->wr_size/sample_size-1)&0xff); 233 PCI_IO_WR(port->dma_a+7, ((port->wr_size/sample_size-1)>>8)&0xff); 234 235 /* here, we should mute the PCM output to avoid clicking */ 236 237 ddprintf(("cmedia_pci: DMA starts as %lx/%lx\n", port->config.format, port->open_mode)); 238 set_direct(port->card, 0x24, 0x00, 0x40); 239 240 /* enable ch0 as play, and ch1 as record */ 241 set_direct(port->card, 0, 0x02, 0x03); 242 set_direct(port->card, 0x02, 0x03, 0x03); 243 244 /* here, we should snooze for 16 samples' time, then un-mute the PCM output */ 245 KTRACE(); 246 } 247 248 249 static status_t 250 configure_pcm( 251 pcm_dev * port, 252 pcm_cfg * config, 253 bool force) 254 { 255 status_t err = B_OK; 256 int m = 0, n = 0, r = 0; /* parameters for the PLL sample rate synthesizer */ 257 int asr = -1; /* alternate sample rate divisor */ 258 uint32 s; /* size of buffer */ 259 260 ddprintf(("cmedia_pci: configure_pcm()\n")); 261 262 /* check args */ 263 if (config->sample_rate < 4000.0) { 264 config->sample_rate = default_pcm.sample_rate; 265 } 266 if (config->sample_rate > 48000.0) { 267 config->sample_rate = 48000.0; 268 } 269 if (config->channels < 1) { 270 config->channels = default_pcm.channels; 271 } 272 if (config->channels > 2) { 273 config->channels = default_pcm.channels; 274 } 275 /* secret format of format: upper nybble = signed, unsigned, float */ 276 /* lower nybble = bytes per sample */ 277 if ((config->format != 0x11) && (config->format != 0x2) && 278 (config->format != 0x24) && (config->format != 0x4)) { 279 config->format = default_pcm.format; 280 } 281 if (config->buf_header < 0) { 282 config->buf_header = 0; 283 } 284 285 /* figure out buffer size that's a power of two and within size limits */ 286 if (!config->play_buf_size) { 287 /* default is 256 samples for a comfy 6 ms latency */ 288 s = 256*config->channels*(config->format&0xf); 289 } /* minimum is 32 samples for a more extreme 0.75ms latency */ 290 else for (s = 32*config->channels*(config->format&0xf); s < MIN_MEMORY_SIZE/2; s = (s<<1)) { 291 if (s >= config->play_buf_size) { 292 break; 293 } 294 } 295 config->play_buf_size = s; 296 if (!config->rec_buf_size) { 297 s = 256*config->channels*(config->format&0xf); 298 } 299 else for (s = 32*config->channels*(config->format&0xf); s < MIN_MEMORY_SIZE/2; s = (s<<1)) { 300 if (s >= config->rec_buf_size) { 301 break; 302 } 303 } 304 config->rec_buf_size = s; 305 306 /* calculate m, n and r (and asr) */ 307 308 if (!force && abs(config->sample_rate - port->config.sample_rate) < config->sample_rate/250) { 309 n = -1; 310 } 311 else if (config->sample_rate == 48000.0) { 312 asr = 7; 313 } 314 else if (config->sample_rate == 32000.0) { 315 asr = 6; 316 } 317 else if (config->sample_rate == 16000.0) { 318 asr = 5; 319 } 320 else if (config->sample_rate == 8000.0) { 321 asr = 4; 322 } 323 else if (config->sample_rate == 44100.0) { 324 asr = 3; 325 } 326 else if (config->sample_rate == 22050.0) { 327 asr = 2; 328 } 329 else if (config->sample_rate == 11025.0) { 330 asr = 1; 331 } 332 else { 333 float freq; 334 float delta = 1000000.0; 335 int sr = -1; 336 int sn = -1; 337 int sm = -1; 338 float diff; 339 340 for (r=0; r<8; r++) { 341 if ((1<<r)*config->sample_rate*512 < MIN_FREQ) { 342 continue; 343 } 344 break; 345 } 346 if (r == 8) { 347 OLDAPI(("cmedia_pci: r value is 8!\n")); 348 r = 7; 349 } 350 n = 0; 351 do { 352 n++; 353 m = config->sample_rate*512/1000*(n+2)*(1<<r)/(F_REF/1000)-2; 354 if (m < 1) { 355 continue; 356 } 357 if (m > 255) { 358 ddprintf(("cmedia_pci: m > 255; outahere\n")); 359 break; 360 } 361 freq = (m+2)*(F_REF/1000)/(512*(n+2)*(1<<r)/1000); 362 diff = freq-config->sample_rate; 363 if (diff < 0) { 364 diff = -diff; 365 } 366 if (diff < delta) { 367 sr = r; 368 sn = n; 369 sm = m; 370 } 371 } while (n < 31); 372 r = sr; 373 n = sn; 374 m = sm; 375 ddprintf(("cmedia_pci: m = %d r = %d n = %d\n", m, r, n)); 376 } 377 378 /* configure device */ 379 380 if (!force) { 381 stop_dma(port); 382 /* should mute PCM out, too */ 383 } 384 if (asr > -1 || n > -1) { /* new sampling rate */ 385 if (asr > -1) { 386 port->config.sample_rate = config->sample_rate; 387 set_direct(port->card, 0x05, (asr<<5)|(asr<<2), 0xfc); 388 } 389 else { 390 port->config.sample_rate = ((float)m+2.0)*(F_REF/1000.0)/ 391 (0.512*(n+2.0)*(1<<r)); 392 config->sample_rate = port->config.sample_rate; 393 #if 1 394 /* not exact the frequency supported */ 395 #else 396 set_indirect(port->card, 0x24, m, 0xff); 397 set_indirect(port->card, 0x25, (r<<5)|n, 0xff); 398 set_indirect(port->card, 0x22, 0x00, 0xff); 399 #endif 400 } 401 } 402 if (force || config->channels != port->config.channels || 403 config->format != port->config.format) { 404 uchar val = 0; 405 if (config->channels == 2) { 406 val |= 0x01; /* stereo */ 407 } 408 if (config->format != 0x11) { 409 val |= 0x02; /* 16 bits */ 410 } 411 set_direct(port->card, 0x08, (val<<2)|val, 0x0f); /* MCE -- may take time to take effect */ 412 port->config.channels = config->channels; 413 port->config.format = config->format; 414 } 415 if (force || config->big_endian != port->config.big_endian) { 416 port->config.big_endian = config->big_endian; 417 } 418 if (force || config->buf_header != port->config.buf_header) { 419 port->config.buf_header = config->buf_header; 420 } 421 if (force || config->play_buf_size != port->config.play_buf_size*2) { 422 port->config.play_buf_size = config->play_buf_size*2; /* because we break it in two */ 423 } 424 if (force || config->rec_buf_size != port->config.rec_buf_size*2) { 425 port->config.rec_buf_size = config->rec_buf_size*2; /* because we break it in two */ 426 } 427 428 /* here is where we should care about record and playback buffer sizes */ 429 430 ddprintf(("cmedia_pci: play %04lx rec %04lx\n", port->config.play_buf_size/2, 431 port->config.rec_buf_size/2)); 432 433 port->wr_1 = port->card->low_mem; 434 port->wr_2 = port->wr_1+port->config.play_buf_size/2; 435 port->wr_size = port->config.play_buf_size/2; 436 437 port->rd_1 = port->card->low_mem+port->config.play_buf_size; 438 port->rd_2 = port->rd_1+port->config.rec_buf_size/2; 439 port->rd_size = port->config.rec_buf_size/2; 440 441 if (!force) { 442 /* should un-mute PCM out, if we muted it */ 443 start_dma(port); 444 } 445 return err; 446 } 447 448 449 static status_t 450 pcm_open( 451 const char * name, 452 uint32 flags, 453 void ** cookie) 454 { 455 int ix; 456 pcm_dev * port = NULL; 457 char name_buf[256]; 458 int32 prev_mode; 459 460 ddprintf(("cmedia_pci: pcm_open()\n")); 461 462 *cookie = NULL; 463 for (ix=0; ix<num_cards; ix++) { 464 if (!strcmp(name, cards[ix].pcm.name)) { 465 goto gotit; 466 } 467 } 468 for (ix=0; ix<num_cards; ix++) { 469 if (!strcmp(name, cards[ix].pcm.oldname)) { 470 goto gotit; 471 } 472 } 473 ddprintf(("cmedia_pci: %s not found\n", name)); 474 return ENODEV; 475 476 gotit: 477 *cookie = port = &cards[ix].pcm; 478 479 acquire_sem(port->init_sem); 480 481 prev_mode = port->open_mode; 482 if ((flags & 3) == O_RDONLY) { 483 atomic_or(&port->open_mode, kRecord); 484 } 485 else if ((flags & 3) == O_WRONLY) { 486 atomic_or(&port->open_mode, kPlayback); 487 } 488 else { 489 atomic_or(&port->open_mode, kPlayback|kRecord); 490 } 491 492 if (atomic_add(&port->open_count, 1) == 0) { 493 494 /* initialize device first time */ 495 496 port->card = &cards[ix]; 497 port->config = default_pcm; 498 port->config.play_buf_size *= 2; 499 port->config.rec_buf_size *= 2; 500 501 /* playback */ 502 503 port->wr_lock = 0; 504 port->dma_a = cards[ix].dma_base; 505 port->wr_1 = cards[ix].low_mem; 506 port->wr_2 = cards[ix].low_mem+port->config.play_buf_size/2; 507 port->wr_size = port->config.play_buf_size/2; 508 port->write_waiting = 0; 509 sprintf(name_buf, "WS:%s", port->name); 510 name_buf[B_OS_NAME_LENGTH-1] = 0; 511 port->write_sem = create_sem(0, name_buf); 512 if (port->write_sem < B_OK) { 513 port->open_count = 0; 514 return port->write_sem; 515 } 516 set_sem_owner(port->write_sem, B_SYSTEM_TEAM); 517 name_buf[0] = 'W'; name_buf[1] = 'E'; 518 port->wr_entry = create_sem(1, name_buf); 519 if (port->wr_entry < B_OK) { 520 delete_sem(port->write_sem); 521 port->open_count = 0; 522 return port->wr_entry; 523 } 524 set_sem_owner(port->wr_entry, B_SYSTEM_TEAM); 525 name_buf[1] = 'T'; 526 port->wr_time_wait = 0; 527 port->wr_time_sem = create_sem(0, name_buf); 528 if (port->wr_time_sem < B_OK) { 529 delete_sem(port->write_sem); 530 delete_sem(port->wr_entry); 531 port->open_count = 0; 532 return port->wr_time_sem; 533 } 534 set_sem_owner(port->wr_time_sem, B_SYSTEM_TEAM); 535 536 /* recording */ 537 538 port->rd_lock = 0; 539 port->dma_c = cards[ix].dma_base+0x08; 540 port->rd_1 = cards[ix].low_mem+port->config.play_buf_size; 541 port->rd_2 = cards[ix].low_mem+port->config.play_buf_size+port->config.rec_buf_size/2; 542 port->rd_size = port->config.rec_buf_size/2; 543 port->read_waiting = 0; 544 name_buf[0] = 'R'; name_buf[1] = 'S'; 545 port->read_sem = create_sem(0, name_buf); 546 if (port->read_sem < B_OK) { 547 delete_sem(port->write_sem); 548 delete_sem(port->wr_entry); 549 delete_sem(port->wr_time_sem); 550 port->open_count = 0; 551 return port->read_sem; 552 } 553 set_sem_owner(port->read_sem, B_SYSTEM_TEAM); 554 name_buf[0] = 'R'; name_buf[1] = 'E'; 555 port->rd_entry = create_sem(1, name_buf); 556 if (port->rd_entry < B_OK) { 557 delete_sem(port->write_sem); 558 delete_sem(port->wr_entry); 559 delete_sem(port->read_sem); 560 delete_sem(port->wr_time_sem); 561 port->open_count = 0; 562 return port->rd_entry; 563 } 564 set_sem_owner(port->rd_entry, B_SYSTEM_TEAM); 565 name_buf[1] = 'T'; 566 port->rd_time_wait = 0; 567 port->rd_time_sem = create_sem(0, name_buf); 568 if (port->rd_time_sem < B_OK) { 569 delete_sem(port->write_sem); 570 delete_sem(port->wr_entry); 571 delete_sem(port->read_sem); 572 delete_sem(port->wr_time_sem); 573 delete_sem(port->rd_entry); 574 port->open_count = 0; 575 return port->rd_time_sem; 576 } 577 set_sem_owner(port->rd_time_sem, B_SYSTEM_TEAM); 578 579 port->rd_time = 0; 580 port->next_rd_time = 0; 581 port->wr_time = 0; 582 583 /* old API */ 584 585 port->old_cap_sem = -1; 586 port->old_play_sem = -1; 587 588 /* configuration */ 589 590 configure_pcm(port, &default_pcm, true); 591 592 /* interrupts */ 593 KTRACE(); 594 increment_interrupt_handler(port->card); 595 596 set_direct(port->card, 0x0e, 0x03, 0x03); /* */ 597 start_dma(port); 598 599 /* initialization is done, let other clients of the driver go */ 600 } else { 601 if (prev_mode != port->open_mode) { 602 pcm_cfg temp = port->config; 603 temp.play_buf_size /= 2; 604 temp.rec_buf_size /= 2; 605 configure_pcm(port, &temp, false); /* change rec/play if needed */ 606 } 607 } 608 release_sem(port->init_sem); 609 610 #if DEBUG 611 dump_card(&cards[ix]); 612 #endif 613 614 return B_OK; 615 } 616 617 618 static status_t 619 pcm_close( 620 void * cookie) 621 { 622 pcm_dev * port = (pcm_dev *)cookie; 623 cpu_status cp; 624 int spin = 0; 625 626 ddprintf(("cmedia_pci: pcm_close()\n")); 627 628 acquire_sem(port->init_sem); 629 630 if (atomic_add(&port->open_count, -1) == 1) { 631 632 KTRACE(); 633 cp = disable_interrupts(); 634 acquire_spinlock(&port->card->hardware); 635 636 /* turn off interrupts */ 637 stop_dma(port); 638 set_direct(port->card, 0x0e, 0x00, 0x03); /* */ 639 640 if (port->config.format == 0x11) { 641 memset((void *)port->wr_1, 0x80, port->config.play_buf_size); /* play silence */ 642 } 643 else { 644 memset((void *)port->wr_1, 0, port->config.play_buf_size); /* play silence */ 645 } 646 spin = 1; 647 648 release_spinlock(&port->card->hardware); 649 restore_interrupts(cp); 650 651 delete_sem(port->write_sem); 652 delete_sem(port->read_sem); 653 delete_sem(port->wr_entry); 654 delete_sem(port->rd_entry); 655 delete_sem(port->rd_time_sem); 656 delete_sem(port->wr_time_sem); 657 port->write_sem = -1; 658 port->read_sem = -1; 659 port->wr_entry = -1; 660 port->rd_entry = -1; 661 port->rd_time_sem = -1; 662 port->wr_time_sem = -1; 663 } 664 release_sem(port->init_sem); 665 666 if (spin) { 667 /* wait so we know FIFO gets filled with silence */ 668 snooze(port->config.play_buf_size*1000/(port->config.sample_rate* 669 (port->config.format&0xf)*port->config.channels/1000)); 670 } 671 return B_OK; 672 } 673 674 675 static status_t 676 pcm_free( 677 void * cookie) 678 { 679 cpu_status cp; 680 pcm_dev * port = (pcm_dev *)cookie; 681 682 ddprintf(("cmedia_pci: pcm_free()\n")); 683 684 acquire_sem(port->init_sem); 685 686 if (((pcm_dev *)cookie)->open_count == 0) { 687 688 /* the last free will actually stop everything */ 689 690 KTRACE(); 691 cp = disable_interrupts(); 692 acquire_spinlock(&port->card->hardware); 693 694 decrement_interrupt_handler(port->card); 695 696 release_spinlock(&port->card->hardware); 697 restore_interrupts(cp); 698 } 699 release_sem(port->init_sem); 700 701 return B_OK; 702 } 703 704 705 static status_t 706 pcm_control( 707 void * cookie, 708 uint32 iop, 709 void * data, 710 size_t len) 711 { 712 // declarations for SPDIF settings I/O 713 static int32 chipinfo[] = { 0,0 }; 714 uchar reg_value; 715 char DriverVersion[] = "1.3.2 (Jul 17, 2001)"; 716 717 pcm_dev * port = (pcm_dev *)cookie; 718 status_t err = B_BAD_VALUE; 719 pcm_cfg config = port->config; 720 static float rates[7] = { 48000.0, 44100.0, 32000.0, 22050.0, 16000.0, 11025.0, 8000.0 }; 721 bool configure = false; 722 config.play_buf_size /= 2; 723 config.rec_buf_size /= 2; 724 725 ddprintf(("cmedia_pci: pcm_control()\n")); 726 727 switch (iop) { 728 case B_AUDIO_GET_AUDIO_FORMAT: 729 memcpy(data, &config, sizeof(port->config)); 730 err = B_OK; 731 break; 732 case B_AUDIO_GET_PREFERRED_SAMPLE_RATES: 733 memcpy(data, rates, sizeof(rates)); 734 err = B_OK; 735 break; 736 case B_AUDIO_SET_AUDIO_FORMAT: 737 memcpy(&config, data, sizeof(config)); 738 configure = true; 739 err = B_OK; 740 break; 741 case SV_RD_TIME_WAIT: 742 atomic_add(&port->rd_time_wait, 1); 743 err = acquire_sem(port->rd_time_sem); 744 if (err >= B_OK) { 745 cpu_status cp; 746 KTRACE(); 747 cp = disable_interrupts(); 748 acquire_spinlock(&port->rd_lock); 749 ((sv_timing *)data)->time = port->rd_time; 750 ((sv_timing *)data)->bytes = port->rd_total; 751 ((sv_timing *)data)->skipped = port->rd_skipped; 752 ((sv_timing *)data)->_reserved_[0] = 0xffffffffUL; 753 release_spinlock(&port->rd_lock); 754 restore_interrupts(cp); 755 } 756 break; 757 case SV_WR_TIME_WAIT: 758 atomic_add(&port->wr_time_wait, 1); 759 err = acquire_sem(port->wr_time_sem); 760 if (err >= B_OK) { 761 cpu_status cp; 762 KTRACE(); 763 cp = disable_interrupts(); 764 acquire_spinlock(&port->wr_lock); 765 ((sv_timing *)data)->time = port->wr_time; 766 ((sv_timing *)data)->bytes = port->wr_total; 767 ((sv_timing *)data)->skipped = port->wr_skipped; 768 ((sv_timing *)data)->_reserved_[0] = 0xffffffffUL; 769 release_spinlock(&port->wr_lock); 770 restore_interrupts(cp); 771 } 772 break; 773 case SV_SECRET_HANDSHAKE: { 774 cpu_status cp; 775 KTRACE(); 776 cp = disable_interrupts(); 777 acquire_spinlock(&port->wr_lock); 778 acquire_spinlock(&port->rd_lock); 779 ((sv_handshake *)data)->wr_time = port->wr_time; 780 ((sv_handshake *)data)->wr_skipped = port->wr_skipped; 781 ((sv_handshake *)data)->rd_time = port->rd_time; 782 ((sv_handshake *)data)->rd_skipped = port->rd_skipped; 783 ((sv_handshake *)data)->wr_total = port->wr_total; 784 ((sv_handshake *)data)->rd_total = port->rd_total; 785 ((sv_handshake *)data)->_reserved_[0] = 0xffffffffUL; 786 err = B_OK; 787 release_spinlock(&port->rd_lock); 788 release_spinlock(&port->wr_lock); 789 restore_interrupts(cp); 790 } break; 791 case SOUND_GET_PARAMS: { 792 cpu_status cp; 793 uchar u; 794 sound_setup * sound = (sound_setup *)data; 795 err = B_OK; 796 cp = disable_interrupts(); 797 acquire_spinlock(&port->card->hardware); 798 /* Here we get to hard-code the mix/mux values. */ 799 /* Huh-huh; he said "hard-code"! */ 800 sound->sample_rate = kHz_44_1; 801 if (!port->config.big_endian == !B_HOST_IS_BENDIAN) { 802 sound->playback_format = linear_16bit_big_endian_stereo; 803 sound->capture_format = linear_16bit_big_endian_stereo; 804 } 805 else { 806 sound->playback_format = linear_16bit_little_endian_stereo; 807 sound->capture_format = linear_16bit_little_endian_stereo; 808 } 809 sound->dither_enable = false; 810 sound->loop_attn = 0; 811 sound->loop_enable = 0; 812 sound->output_boost = 0; 813 sound->highpass_enable = 0; 814 /* this is a master control on C-Media... */ 815 u = get_indirect(port->card, 0x30)>>2; 816 sound->mono_gain = u&63; 817 sound->mono_mute = 0; 818 819 /* left channel */ 820 u = get_indirect(port->card, 0x3d); // Legacy SB compatible Mixer 821 switch (u) 822 { 823 case 0x10: 824 sound->left.adc_source = line; // record line left 825 break; 826 827 case 4: 828 sound->left.adc_source = aux1; // record CD left ?? 829 break; 830 831 case 1: 832 sound->left.adc_source = mic; // record mic left 833 break; 834 835 default: 836 sound->left.adc_source = loopback; 837 break; 838 } 839 u = get_indirect(port->card, 0x3f)>>4; 840 sound->left.adc_gain = u&15; 841 842 u = get_direct(port->card, 0x25)<<4; 843 sound->left.mic_gain_enable = u&16; 844 845 u = get_indirect(port->card, 0x36)>>3; 846 sound->left.aux1_mix_gain = 31-(u&31); 847 848 u = get_indirect(port->card, 0x3c)<<5; 849 sound->left.aux1_mix_mute = ~u&128; 850 851 u = get_indirect(port->card, 0x34)>>3; 852 sound->left.aux2_mix_gain = 31-(u&31); 853 854 u = get_direct(port->card, 0x24); 855 sound->left.aux2_mix_mute = u&128; 856 857 u = get_indirect(port->card, 0x38)>>3; 858 sound->left.line_mix_gain = 31-(u&31); 859 860 u = get_indirect(port->card, 0x3c)<<3; 861 sound->left.line_mix_mute = ~u&128; 862 863 u = get_indirect(port->card, 0x32)>>2; 864 sound->left.dac_attn = 63-(u&63); 865 866 u = get_direct(port->card, 0x24)<<1; 867 sound->left.dac_mute = u&128; 868 869 /* right channel */ 870 u = get_indirect(port->card, 0x3e); 871 switch (u) 872 { 873 case 8: 874 sound->right.adc_source = line; //record line right 875 break; 876 877 case 2: 878 sound->right.adc_source = aux1; // record CD right? 879 break; 880 881 case 1: 882 sound->right.adc_source = mic; // record mic right 883 break; 884 885 default: 886 sound->right.adc_source = loopback; 887 break; 888 } 889 u = get_indirect(port->card, 0x40)>>4; 890 sound->right.adc_gain = u&15; 891 sound->right.mic_gain_enable = sound->left.mic_gain_enable; 892 u = get_indirect(port->card, 0x37)>>3; 893 sound->right.aux1_mix_gain = 31-(u&31); 894 u = get_indirect(port->card, 0x3c)<<6; 895 sound->right.aux1_mix_mute = ~u&128; 896 u = get_indirect(port->card, 0x35)>>3; 897 sound->right.aux2_mix_gain = 31-(u&31); 898 u = get_direct(port->card, 0x24); 899 sound->right.aux2_mix_mute = u&128; 900 u = get_indirect(port->card, 0x39)>>3; 901 sound->right.line_mix_gain = 31-(u&31); 902 u = get_indirect(port->card, 0x3c)<<4; 903 sound->right.line_mix_mute = ~u&128; 904 u = get_indirect(port->card, 0x33)>>2; 905 sound->right.dac_attn = 63-(u&63); 906 u = get_direct(port->card, 0x24)<<1; 907 sound->right.dac_mute = u&128; 908 /* done */ 909 release_spinlock(&port->card->hardware); 910 restore_interrupts(cp); 911 } break; 912 case SOUND_SET_PARAMS: { 913 cpu_status cp; 914 uchar u; 915 sound_setup * sound = (sound_setup *)data; 916 err = B_OK; 917 cp = disable_interrupts(); 918 acquire_spinlock(&port->card->hardware); 919 /* Here we get to hard-code the mix/mux values. */ 920 /* Huh-huh; he said "hard-code"! */ 921 922 /* ignore sample rate */ 923 sound->sample_rate = kHz_44_1; 924 if (config.sample_rate < 43999 || config.sample_rate > 44201) { 925 config.sample_rate = 44100.0; 926 configure = true; 927 } 928 /* we only support 16-bit formats */ 929 if (sound->playback_format == linear_16bit_big_endian_stereo && 930 sound->capture_format == linear_16bit_big_endian_stereo) { 931 if (!config.big_endian != !B_HOST_IS_BENDIAN || config.format != 0x2) { 932 config.big_endian = B_HOST_IS_BENDIAN; 933 config.format = 0x2; 934 configure = true; 935 } 936 OLDAPI(("same_endian\n")); 937 } 938 else if (sound->playback_format == linear_16bit_little_endian_stereo && 939 sound->capture_format == linear_16bit_little_endian_stereo) { 940 if (!config.big_endian != !!B_HOST_IS_BENDIAN || config.format != 0x2) { 941 config.big_endian = !B_HOST_IS_BENDIAN; 942 config.format = 0x2; 943 configure = true; 944 } 945 OLDAPI(("other_endian\n")); 946 } 947 else { 948 config.big_endian = !!B_HOST_IS_BENDIAN; 949 configure = true; 950 OLDAPI(("other format!!!\n")); 951 } 952 /* ignore these values */ 953 sound->dither_enable = false; 954 sound->loop_attn = 0; 955 sound->loop_enable = 0; 956 sound->output_boost = 0; 957 sound->highpass_enable = 0; 958 /* this is a stereo control on C-Media... */ 959 u = (sound->mono_gain>>1)&0x1f; 960 OLDAPI(("output: %x\n", u)); 961 set_indirect(port->card, 0x30, u<<3, 0xff); 962 set_indirect(port->card, 0x31, u<<3, 0xff); 963 /* left channel */ 964 switch (sound->left.adc_source) 965 { 966 case line: 967 u = 1<<4; 968 break; 969 case aux1: 970 u = 1<<2; 971 break; 972 case mic: 973 u = 1<<0; 974 break; 975 default: 976 u = 0x15; 977 break; 978 } 979 OLDAPI(("input: %x\n", u)); 980 set_indirect(port->card, 0x3d, u, 0xff); 981 u = (sound->left.adc_gain&15); 982 set_indirect(port->card, 0x3f, u<<4, 0xff); 983 u = sound->left.mic_gain_enable ? 0 : 0x01; 984 set_direct(port->card, 0x25, u, 0x01); 985 u = 31-(sound->left.aux1_mix_gain&31); 986 OLDAPI(("cd: %x\n", u)); 987 set_indirect(port->card, 0x36, u<<3, 0xff); 988 u = sound->left.aux1_mix_mute ? 0 : 0x04; 989 set_indirect(port->card, 0x3c, u, 0x04); 990 u = 31-(sound->left.aux2_mix_gain&31); 991 OLDAPI(("aux2: %x\n", u)); 992 set_indirect(port->card, 0x34, u<<3, 0xff); 993 u = sound->left.aux2_mix_mute ? 0x80 : 0; 994 set_direct(port->card, 0x24, u, 0x80); 995 u = 31-(sound->left.line_mix_gain&31); 996 OLDAPI(("line: %x\n", u)); 997 set_indirect(port->card, 0x38, u<<3, 0xff); 998 u = sound->left.line_mix_mute ? 0 : 0x10; 999 set_indirect(port->card, 0x3c, u, 0x10); 1000 u = 63-(sound->left.dac_attn & 63); 1001 OLDAPI(("PCM: %x\n", u)); 1002 set_indirect(port->card, 0x32, u<<2, 0xff); 1003 u = sound->left.dac_mute ? 0x40 : 0; 1004 set_direct(port->card, 0x24, u, 0x40); 1005 /* right channel */ 1006 switch (sound->right.adc_source) { 1007 case line: 1008 u = 1<<3; 1009 break; 1010 case aux1: 1011 u = 1<<1; 1012 break; 1013 case mic: 1014 u = 1<<0; 1015 break; 1016 default: 1017 u = 0x0a; 1018 break; 1019 } 1020 sound->right.mic_gain_enable = sound->left.mic_gain_enable; 1021 set_indirect(port->card, 0x3e, u, 0xff); 1022 u = (sound->right.adc_gain&15); 1023 set_indirect(port->card, 0x40, u<<4, 0xff); 1024 u = sound->right.mic_gain_enable ? 0 : 0x01; 1025 set_direct(port->card, 0x25, u, 0x01); 1026 u = 31-(sound->right.aux1_mix_gain&31); 1027 set_indirect(port->card, 0x37, u<<3, 0xff); 1028 u = sound->right.aux1_mix_mute ? 0 : 0x02; 1029 set_indirect(port->card, 0x3c, u, 0x02); 1030 u = 31-(sound->right.aux2_mix_gain&31); 1031 set_indirect(port->card, 0x35, u<<3, 0xff); 1032 u = sound->right.aux2_mix_mute ? 0x80 : 0; 1033 set_direct(port->card, 0x24, u, 0x80); 1034 u = 31-(sound->right.line_mix_gain&31); 1035 set_indirect(port->card, 0x39, u<<3, 0xff); 1036 u = sound->right.line_mix_mute ? 0 : 0x08; 1037 set_indirect(port->card, 0x3c, u, 0x08); 1038 u = 63-(sound->right.dac_attn & 63); 1039 set_indirect(port->card, 0x33, u<<2, 0xff); 1040 u = sound->right.dac_mute ? 0x40 : 0; 1041 set_direct(port->card, 0x24, u, 0x40); 1042 /* done */ 1043 release_spinlock(&port->card->hardware); 1044 restore_interrupts(cp); 1045 } break; 1046 case SOUND_SET_PLAYBACK_COMPLETION_SEM: 1047 port->old_play_sem = *(sem_id *)data; 1048 err = B_OK; 1049 break; 1050 case SOUND_SET_CAPTURE_COMPLETION_SEM: 1051 port->old_cap_sem = *(sem_id *)data; 1052 err = B_OK; 1053 break; 1054 // case SOUND_GET_PLAYBACK_TIMESTAMP: 1055 // break; 1056 // case SOUND_GET_CAPTURE_TIMESTAMP: 1057 // break; 1058 // case SOUND_DEBUG_ON: 1059 // break; 1060 // case SOUND_DEBUG_OFF: 1061 // break; 1062 case SOUND_UNSAFE_WRITE: { 1063 audio_buffer_header * buf = (audio_buffer_header *)data; 1064 size_t n = buf->reserved_1-sizeof(*buf); 1065 pcm_write(cookie, 0, buf+1, &n); 1066 buf->time = port->wr_time; 1067 buf->sample_clock = port->wr_total/4 * 10000 / 441; 1068 err = release_sem(port->old_play_sem); 1069 } break; 1070 case SOUND_UNSAFE_READ: { 1071 audio_buffer_header * buf = (audio_buffer_header *)data; 1072 size_t n = buf->reserved_1-sizeof(*buf); 1073 pcm_read(cookie, 0, buf+1, &n); 1074 buf->time = port->rd_time; 1075 buf->sample_clock = port->rd_total/4 * 10000 / 441; 1076 err = release_sem(port->old_cap_sem); 1077 } break; 1078 case SOUND_LOCK_FOR_DMA: 1079 err = B_OK; 1080 break; 1081 case SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE: 1082 config.play_buf_size = (int32)data; 1083 configure = true; 1084 err = B_OK; 1085 break; 1086 case SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE: 1087 config.rec_buf_size = (int32)data; 1088 configure = true; 1089 err = B_OK; 1090 break; 1091 case SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE: 1092 *(int32*)data = config.play_buf_size; 1093 err = B_OK; 1094 break; 1095 case SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE: 1096 *(int32*)data = config.rec_buf_size; 1097 err = B_OK; 1098 break; 1099 1100 1101 // control ports for SPDIF settings 1102 case SOUND_GET_SPDIF_IN_OUT_LOOPBACK: 1103 *(int8 *)data = 0; 1104 reg_value = get_direct( port->card, 0x04 ); 1105 if( reg_value && 0x80 ) *(int8 *)data = 1; 1106 err = B_OK; 1107 break; 1108 1109 case SOUND_SET_SPDIF_IN_OUT_LOOPBACK: 1110 if( *(int8 *)data == 0 ) // disable SPDIF-IN loopback to SPDIF (bypass) 1111 set_direct( port->card, 0x04, 0x00, 0x80 ); 1112 else // enable SPDIF-IN loopback to SPDIF (bypass) 1113 set_direct( port->card, 0x04, 0x80, 0x80 ); 1114 err = B_OK; 1115 break; 1116 1117 1118 1119 1120 case SOUND_GET_SPDIF_OUT: 1121 *(int8 *)data = 0; 1122 reg_value = get_direct( port->card, 0x16 ); // Adresse 0x16 1123 if( reg_value && 0x80 ) *(int8 *)data = 1; 1124 err = B_OK; 1125 break; 1126 1127 case SOUND_SET_SPDIF_OUT: 1128 if( *(int8 *)data == 0 ) // disable SPDIF-OUT 1129 set_direct( port->card, 0x16, 0x00, 0x80); 1130 else // enable SPDIF-OUT 1131 set_direct( port->card, 0x16, 0x80, 0x80 ); 1132 err = B_OK; 1133 break; 1134 1135 1136 1137 case SOUND_GET_SPDIF_MONITOR: 1138 *(int8 *)data = 0; 1139 reg_value = get_direct( port->card, 0x24 ); 1140 if( reg_value && 0x01 ) *(int8 *)data = 1; 1141 err = B_OK; 1142 break; 1143 1144 1145 case SOUND_SET_SPDIF_MONITOR: 1146 if( *(int8 *)data == 0 ) // disable SPDIF_IN PCM to DAC (CDPlay) 1147 set_direct( port->card, 0x24, 0x00, 0x01 ); 1148 else // enable SPDIF_IN PCM to DAC (CDPlay) 1149 set_direct( port->card, 0x24, 0x01, 0x01 ); 1150 err = B_OK; 1151 break; 1152 1153 case SOUND_GET_SPDIF_OUT_LEVEL: 1154 *(int8 *)data = 0; 1155 reg_value = get_direct( port->card, 0x1b ); 1156 if( reg_value && 0x02 ) *(int8 *)data = 1; 1157 err = B_OK; 1158 break; 1159 1160 case SOUND_SET_SPDIF_OUT_LEVEL: 1161 if( *(int8 *)data == 0 ) // enable SPDIF-OUT optical 1162 set_direct( port->card, 0x1b, 0x00, 0x02 ); 1163 else // enable SPDIF-OUT coaxial 1164 set_direct( port->card, 0x1b, 0x02, 0x02 ); 1165 break; 1166 1167 case SOUND_GET_SPDIF_IN_FORMAT: 1168 *(int8 *)data = 0; 1169 reg_value = get_direct( port->card, 0x08 ); // Adresse 0x08 1170 if( reg_value && 0x80 ) *(int8 *)data = 1; 1171 err = B_OK; 1172 break; 1173 1174 1175 case SOUND_SET_SPDIF_IN_FORMAT: 1176 if( *(int8 *)data == 0 ) // disable SPDIF inverse (SPDIF normal) 1177 set_direct( port->card, 0x08, 0x00, 0x80 ); 1178 else // enable SPDIF inverse 1179 set_direct( port->card, 0x08, 0x80, 0x80 ); // Adresse 0x08, Daten 0x80 1180 err = B_OK; 1181 break; 1182 1183 1184 case SOUND_GET_SPDIF_IN_OUT_COPYRIGHT: 1185 *(int8 *)data = 0; 1186 reg_value = get_direct( port->card, 0x16 ); 1187 if( reg_value && 0x40 ) *(int8 *)data = 1; 1188 err = B_OK; 1189 break; 1190 1191 case SOUND_SET_SPDIF_IN_OUT_COPYRIGHT: 1192 if( *(int8 *)data == 0 ) // disable SPDIF-IN/OUT copyright protection 1193 set_direct( port->card, 0x16, 0x00, 0x40 ); 1194 else // enable SPDIF-IN/OUT copyright protection 1195 set_direct( port->card, 0x16, 0x40, 0x40 ); 1196 err = B_OK; 1197 break; 1198 1199 case SOUND_GET_SPDIF_IN_VALIDITY: 1200 *(int8 *)data = 0; 1201 reg_value = get_direct( port->card, 0x27 ); 1202 if( reg_value && 0x02 ) *(int8 *)data = 1; 1203 err = B_OK; 1204 break; 1205 1206 case SOUND_SET_SPDIF_IN_VALIDITY: 1207 if( *(int8 *)data == 0 ) // disable SPDIF-IN validity detection 1208 set_direct( port->card, 0x27, 0x00, 0x02 ); 1209 else // enable SPDIF-IN validity detection 1210 set_direct( port->card, 0x27, 0x02, 0x02 ); 1211 err = B_OK; 1212 break; 1213 // control ports for analog settings 1214 1215 case SOUND_GET_4_CHANNEL_DUPLICATE: 1216 *(int8 *)data = 0; 1217 reg_value = get_direct( port->card, 0x1b ); 1218 if( reg_value && 0x04 ) *(int8 *)data = 1; 1219 1220 // 0x1b, 0x04, 0x04, /* dual channel mode enable */ 1221 // 0x1a, 0x00, 0x80, /* Double DAC structure disable */ 1222 1223 err = B_OK; 1224 break; 1225 1226 case SOUND_SET_4_CHANNEL_DUPLICATE: 1227 if( *(int8 *)data == 0 ) // disable 4 channel analog duplicate mode 1228 set_direct( port->card, 0x1b, 0x00, 0x04 ); 1229 else // enable 4 channel analog duplicate mode 1230 set_direct( port->card, 0x1b, 0x04, 0x04 ); 1231 err = B_OK; 1232 break; 1233 // control ports for additional info 1234 1235 case SOUND_GET_DEVICE_ID: 1236 // *(int32*)data.vendor_id = cards[0].info.vendor_id; 1237 // *(int32*)data.device_id = cards[0].info.device_id; 1238 1239 // chipinfo[0] = cards[0].info.vendor_id; 1240 *(int32 *)data = cards[0].info.device_id; 1241 1242 // memcpy(data, &chipinfo, sizeof(chipinfo)); 1243 err = B_OK; 1244 break; 1245 1246 case SOUND_GET_INTERNAL_CHIP_ID: 1247 // XXX 1248 break; 1249 1250 case SOUND_GET_DRIVER_VERSION: 1251 memcpy(data, &DriverVersion, sizeof(DriverVersion)); 1252 break; 1253 1254 default: 1255 OLDAPI(("cmedia_pci: unknown code %ld\n", iop)); 1256 err = B_BAD_VALUE; 1257 break; 1258 } 1259 if ((err == B_OK) && configure) { 1260 cpu_status cp; 1261 KTRACE(); 1262 cp = disable_interrupts(); 1263 acquire_spinlock(&port->card->hardware); 1264 err = configure_pcm(port, &config, false); 1265 release_spinlock(&port->card->hardware); 1266 restore_interrupts(cp); 1267 } 1268 return err; 1269 } 1270 1271 1272 static void 1273 copy_short_to_float( 1274 float * f, 1275 const short * s, 1276 int c, 1277 int endian) /* endian means float data in big-endian */ 1278 { 1279 if (endian) { 1280 while (c > 1) { 1281 short sh = B_LENDIAN_TO_HOST_FLOAT(*s); 1282 *(f++) = B_HOST_TO_BENDIAN_FLOAT((float)B_LENDIAN_TO_HOST_INT16(sh)); 1283 s++; 1284 c -= 2; 1285 } 1286 } 1287 else { 1288 while (c > 1) { 1289 short sh = B_LENDIAN_TO_HOST_FLOAT(*s); 1290 *(f++) = B_HOST_TO_LENDIAN_FLOAT((float)B_LENDIAN_TO_HOST_INT16(sh)); 1291 s++; 1292 c -= 2; 1293 } 1294 } 1295 } 1296 1297 1298 static void 1299 copy_float_to_short( 1300 short * s, 1301 const float * f, 1302 int c, 1303 int endian) /* endian means float data in big-endian */ 1304 { 1305 if (endian) { 1306 while (c > 1) { 1307 float fl = *(f++); 1308 *(s++) = B_HOST_TO_LENDIAN_INT16((float)B_BENDIAN_TO_HOST_FLOAT(fl)); 1309 c -= 2; 1310 } 1311 } 1312 else { 1313 while (c > 1) { 1314 float fl = *(f++); 1315 *(s++) = B_HOST_TO_LENDIAN_INT16((float)B_LENDIAN_TO_HOST_FLOAT(fl)); 1316 c -= 2; 1317 } 1318 } 1319 } 1320 1321 1322 static void 1323 swap_copy( 1324 short * dest, 1325 const short * src, 1326 int c) 1327 { 1328 while (c > 1) { 1329 unsigned short sh = *(src++); 1330 *(dest++) = ((sh << 8) | (sh >> 8)); 1331 c -= 2; 1332 } 1333 } 1334 1335 1336 static status_t 1337 pcm_read( 1338 void * cookie, 1339 off_t pos, 1340 void * data, 1341 size_t * nread) 1342 { 1343 pcm_dev * port = (pcm_dev *)cookie; 1344 size_t to_read = *nread; 1345 status_t err; 1346 int block; 1347 cpu_status cp; 1348 int bytes_xferred; 1349 void * hdrptr = data; 1350 int hdrsize = port->config.buf_header; 1351 cmedia_pci_audio_buf_header hdr; 1352 1353 // ddprintf(("cmedia_pci: pcm_read()\n")); /* we're here */ 1354 1355 *nread = 0; 1356 data = ((char *)data)+hdrsize; 1357 to_read -= hdrsize; 1358 1359 err = acquire_sem_etc(port->rd_entry, 1, B_CAN_INTERRUPT, 0); 1360 if (err < B_OK) { 1361 return err; 1362 } 1363 1364 hdr.capture_time = port->rd_time; 1365 1366 goto first_time; 1367 1368 while (to_read > 0) { 1369 /* wait for more data */ 1370 atomic_add(&port->read_waiting, 1); 1371 err = acquire_sem_etc(port->read_sem, 1, B_CAN_INTERRUPT, 0); 1372 if (err < B_OK) { 1373 release_sem(port->rd_entry); 1374 return err; 1375 } 1376 1377 first_time: /* we need to check whether anything's available first */ 1378 KTRACE(); 1379 cp = disable_interrupts(); 1380 acquire_spinlock(&port->rd_lock); 1381 1382 block = port->rd_size-port->was_read; 1383 1384 if (port->config.format == 0x24) { 1385 if (block > (to_read>>1)) { /* floats expand by factor 2 */ 1386 block = to_read>>1; 1387 } 1388 } 1389 else if (block > to_read) { 1390 block = to_read; 1391 } 1392 switch (port->config.format) { 1393 case 0x24: /* floats */ 1394 copy_short_to_float((float *)data, (const short *)(port->rd_cur+port->was_read), 1395 block, !B_HOST_IS_LENDIAN == !port->config.big_endian); 1396 bytes_xferred = block * 2; 1397 break; 1398 case 0x02: /* shorts */ 1399 if (!B_HOST_IS_LENDIAN == !port->config.big_endian) { 1400 /* we need to swap */ 1401 swap_copy((short *)data, (const short *)(port->rd_cur+port->was_read), block); 1402 bytes_xferred = block; 1403 break; 1404 } 1405 /* else fall through to default case */ 1406 case 0x11: /* bytes */ 1407 default: 1408 memcpy(data, (void *)(port->rd_cur+port->was_read), block); 1409 bytes_xferred = block; 1410 break; 1411 } 1412 port->was_read += block; 1413 1414 release_spinlock(&port->rd_lock); 1415 restore_interrupts(cp); 1416 1417 to_read -= bytes_xferred; 1418 data = ((char *)data)+bytes_xferred; 1419 *nread += bytes_xferred; 1420 } 1421 1422 /* provide header if requested */ 1423 if (hdrsize > 0) { 1424 ddprintf(("header %d\n", hdrsize)); 1425 *nread += hdrsize; 1426 hdr.capture_size = *nread; 1427 hdr.sample_rate = port->config.sample_rate; 1428 if (hdrsize > sizeof(hdr)) { 1429 hdrsize = sizeof(hdr); 1430 } 1431 memcpy(hdrptr, &hdr, hdrsize); 1432 } 1433 1434 release_sem(port->rd_entry); 1435 1436 return B_OK; 1437 } 1438 1439 1440 static status_t 1441 pcm_write( 1442 void * cookie, 1443 off_t pos, 1444 const void * data, 1445 size_t * nwritten) 1446 { 1447 pcm_dev * port = (pcm_dev *)cookie; 1448 status_t err; 1449 cpu_status cp; 1450 int written = 0; 1451 int to_write = *nwritten; /* in play bytes, not input bytes! */ 1452 int block; 1453 int bytes_xferred; 1454 1455 // ddprintf(("cmedia_pci: pcm_write()\n")); /* we're here */ 1456 1457 *nwritten = 0; 1458 1459 err = acquire_sem_etc(port->wr_entry, 1, B_CAN_INTERRUPT, 0); 1460 if (err < B_OK) { 1461 return err; 1462 } 1463 1464 atomic_add(&port->write_waiting, 1); 1465 if (port->config.format == 0x24) { 1466 to_write >>= 1; /* floats collapse by 2 */ 1467 } 1468 while (to_write > 0) { 1469 1470 /* wait to write */ 1471 1472 err = acquire_sem_etc(port->write_sem, 1, B_CAN_INTERRUPT, 0); 1473 if (err < B_OK) { 1474 release_sem(port->wr_entry); 1475 return err; 1476 } 1477 1478 #if DEBUG 1479 put_cnt++; 1480 { 1481 bigtime_t delta = system_time() - the_time; 1482 if (delta < 1) { 1483 ddprintf(("cmedia_pci: delta %Ld (low!) #%ld\n", delta, put_cnt)); 1484 } 1485 else if (delta > 2000) { 1486 ddprintf(("cmedia_pci: delta %Ld (high!) #%ld\n", delta, put_cnt)); 1487 } 1488 } 1489 if (put_cnt != int_cnt) { 1490 static int last; 1491 if (last != int_cnt-put_cnt) 1492 OLDAPI(("cmedia_pci: %ld mismatch\n", int_cnt-put_cnt)); 1493 last = int_cnt-put_cnt; 1494 } 1495 #endif /* DEBUG */ 1496 1497 KTRACE(); 1498 cp = disable_interrupts(); 1499 acquire_spinlock(&port->wr_lock); 1500 1501 block = port->wr_size-port->was_written; 1502 if (block > to_write) { 1503 /* must let next guy in */ 1504 if (atomic_add(&port->write_waiting, -1) > 0) { 1505 release_sem_etc(port->write_sem, 1, B_DO_NOT_RESCHEDULE); 1506 } 1507 else { 1508 atomic_add(&port->write_waiting, 1); /* undo damage */ 1509 } 1510 block = to_write; 1511 } 1512 else if (block < to_write) { 1513 atomic_add(&port->write_waiting, 1); /* we will loop back */ 1514 } 1515 switch (port->config.format) { 1516 case 0x24: /* floats */ 1517 copy_float_to_short((short *)(port->wr_cur+port->was_written), (const float *)data, 1518 block, !B_HOST_IS_LENDIAN == !port->config.big_endian); 1519 bytes_xferred = block * 2; 1520 break; 1521 case 0x02: /* shorts */ 1522 if (!B_HOST_IS_LENDIAN == !port->config.big_endian) { 1523 /* we need to swap */ 1524 swap_copy((short *)(port->wr_cur+port->was_written), (const short *)data, block); 1525 bytes_xferred = block; 1526 break; 1527 } 1528 /* else fall through to default case */ 1529 case 0x11: /* bytes */ 1530 default: 1531 memcpy((void *)(port->wr_cur+port->was_written), data, block); 1532 bytes_xferred = block; 1533 break; 1534 } 1535 port->was_written += block; 1536 port->wr_silence = 0; 1537 1538 release_spinlock(&port->wr_lock); 1539 restore_interrupts(cp); 1540 1541 data = ((char *)data)+bytes_xferred; 1542 written += bytes_xferred; 1543 to_write -= block; 1544 } 1545 1546 *nwritten = written; 1547 release_sem(port->wr_entry); 1548 1549 return B_OK; 1550 } 1551 1552 1553 bool 1554 dma_a_interrupt( 1555 cmedia_pci_dev * dev) 1556 { 1557 bool ret = false; 1558 pcm_dev * port = &dev->pcm; 1559 volatile uchar * ptr; 1560 uint32 addr; 1561 uint32 offs; 1562 bigtime_t st = system_time(); 1563 int32 ww; 1564 1565 #if 0 1566 ddprintf(("cmedia_pci: dma_a 0x%x+0x%x\n", PCI_IO_RD_32((int)port->dma_a), PCI_IO_RD_32((int)port->dma_a+4))); 1567 #endif 1568 // KTRACE(); /* */ 1569 acquire_spinlock(&port->wr_lock); 1570 1571 if (port->write_sem < 0) { 1572 kprintf("cmedia_pci: spurious DMA A interrupt!\n"); 1573 release_spinlock(&port->wr_lock); 1574 return false; 1575 } 1576 /* copy possible silence into playback buffer */ 1577 1578 if (port->was_written > 0 && port->was_written < port->wr_size) { 1579 if (port->config.format == 0x11) { 1580 memset((void *)(port->wr_cur+port->was_written), 0x80, port->wr_size-port->was_written); 1581 } 1582 else { 1583 memset((void *)(port->wr_cur+port->was_written), 0, port->wr_size-port->was_written); 1584 } 1585 } 1586 1587 /* because the system may be lacking and not hand us the */ 1588 /* interrupt in time, we check which half is currently being */ 1589 /* played, and set the pointer to the other half */ 1590 1591 addr = PCI_IO_RD_32((uint32)port->dma_a); 1592 if ((offs = addr-(uint32)port->card->low_phys) < port->wr_size) { 1593 ptr = port->wr_2; 1594 } 1595 else { 1596 ptr = port->wr_1; 1597 } 1598 port->wr_total += port->config.play_buf_size/2; 1599 /* compensate for interrupt latency */ 1600 /* assuming 4 byte frames */ 1601 port->wr_time = st-(offs&(port->config.play_buf_size/2-1))*250000LL/(int64)port->config.sample_rate; 1602 if ((ww = atomic_add(&port->wr_time_wait, -1)) > 0) { 1603 release_sem_etc(port->wr_time_sem, 1, B_DO_NOT_RESCHEDULE); 1604 ret = true; 1605 } 1606 else { 1607 atomic_add(&port->wr_time_wait, 1); /* re-set to 0 */ 1608 } 1609 1610 if (port->wr_cur == ptr) { 1611 port->wr_skipped++; 1612 OLDAPI(("cmedia_pci: write skipped %ld\n", port->wr_skipped)); 1613 } 1614 port->wr_cur = ptr; 1615 port->was_written = 0; 1616 1617 /* check for client there to write into buffer */ 1618 1619 if (atomic_add(&port->write_waiting, -1) > 0) { 1620 #if DEBUG 1621 int_cnt++; 1622 the_time = st; 1623 #endif 1624 release_sem_etc(port->write_sem, 1, B_DO_NOT_RESCHEDULE); 1625 ret = true; 1626 } 1627 else { 1628 atomic_add(&port->write_waiting, 1); 1629 /* if none there, fill with silence */ 1630 if (port->wr_silence < port->config.play_buf_size*2) { 1631 if (port->config.format == 0x11) { 1632 memset((void *)ptr, 0x80, port->wr_size); 1633 } 1634 else { 1635 memset((void *)ptr, 0, port->wr_size); 1636 } 1637 port->wr_silence += port->wr_size; 1638 } 1639 } 1640 /* copying will be done in user thread */ 1641 1642 release_spinlock(&port->wr_lock); 1643 return ret; 1644 } 1645 1646 1647 bool 1648 dma_c_interrupt( 1649 cmedia_pci_dev * dev) 1650 { 1651 bool ret = false; 1652 pcm_dev * port = &dev->pcm; 1653 volatile uchar * ptr; 1654 uint32 addr; 1655 uint32 offs; 1656 int32 rr; 1657 bigtime_t st = system_time(); 1658 1659 /* mark data as readable in record buffer */ 1660 #if 0 1661 ddprintf(("cmedia_pci: dma_c 0x%x+0x%x\n", PCI_IO_RD_32((int)port->dma_c), PCI_IO_RD_32((int)port->dma_c+4))); 1662 #endif 1663 // KTRACE(); /* */ 1664 acquire_spinlock(&port->rd_lock); 1665 1666 if (port->read_sem < 0) { 1667 kprintf("cmedia_pci: spurious DMA C interrupt!\n"); 1668 release_spinlock(&port->rd_lock); 1669 return false; 1670 } 1671 /* if we lose an interrupt, we automatically avoid constant glitching by setting */ 1672 /* the write pointer based on where the DMA counter is everytime */ 1673 addr = PCI_IO_RD_32((uint32)port->dma_c); 1674 if ((offs = addr-port->config.play_buf_size-(uint32)port->card->low_phys) < port->rd_size) { 1675 ptr = port->rd_2; 1676 } 1677 else { 1678 ptr = port->rd_1; 1679 } 1680 if (port->rd_cur == ptr) { 1681 port->rd_skipped++; 1682 OLDAPI(("cmedia_pci: read skipped %ld\n", port->rd_skipped)); 1683 } 1684 port->rd_total += port->rd_size; 1685 1686 port->rd_cur = ptr; 1687 port->was_read = 0; 1688 port->rd_time = port->next_rd_time; 1689 /* time stamp when this buffer became available -- compensate for interrupt latency */ 1690 port->next_rd_time = st-(offs&(port->config.rec_buf_size/2-1))*1000000LL/(int64)port->config.sample_rate; 1691 if ((rr = atomic_add(&port->rd_time_wait, -1)) > 0) { 1692 release_sem_etc(port->rd_time_sem, 1, B_DO_NOT_RESCHEDULE); 1693 ret = true; 1694 } 1695 else { 1696 atomic_add(&port->rd_time_wait, 1); /* re-set to 0 */ 1697 } 1698 1699 if (atomic_add(&port->read_waiting, -1) > 0) { 1700 release_sem_etc(port->read_sem, 1, B_DO_NOT_RESCHEDULE); 1701 ret = true; 1702 } 1703 else { 1704 atomic_add(&port->read_waiting, 1); 1705 } 1706 /* copying will be done in the user thread */ 1707 release_spinlock(&port->rd_lock); 1708 return ret; 1709 } 1710 1711