1 /* 2 * ES1370 Haiku Driver for ES1370 audio 3 * 4 * Copyright 2002-2007, Haiku, Inc. 5 * Distributed under the terms of the MIT License. 6 * 7 * Authors: 8 * Jerome Duval, jerome.duval@free.fr 9 */ 10 11 #include <KernelExport.h> 12 #include <PCI.h> 13 #include <driver_settings.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include "es1370.h" 18 #include "debug.h" 19 #include "config.h" 20 #include "util.h" 21 #include "io.h" 22 #include <fcntl.h> 23 #include <unistd.h> 24 #include <malloc.h> 25 26 status_t init_hardware(void); 27 status_t init_driver(void); 28 void uninit_driver(void); 29 const char ** publish_devices(void); 30 device_hooks * find_device(const char *); 31 status_t es1370_init(es1370_dev * card); 32 33 static char pci_name[] = B_PCI_MODULE_NAME; 34 pci_module_info *pci; 35 36 int32 num_cards; 37 es1370_dev cards[NUM_CARDS]; 38 int32 num_names; 39 char * names[NUM_CARDS*20+1]; 40 41 extern device_hooks multi_hooks; 42 43 es1370_settings current_settings = { 44 44100, // sample rate 45 512, // buffer frames 46 2, // buffer count 47 }; 48 49 50 /* es1370 Memory management */ 51 52 static es1370_mem * 53 es1370_mem_new(es1370_dev *card, size_t size) 54 { 55 es1370_mem *mem; 56 57 if ((mem = malloc(sizeof(*mem))) == NULL) 58 return (NULL); 59 60 mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "es1370 buffer"); 61 mem->size = size; 62 if (mem->area < B_OK) { 63 free(mem); 64 return NULL; 65 } 66 return mem; 67 } 68 69 static void 70 es1370_mem_delete(es1370_mem *mem) 71 { 72 if(mem->area > B_OK) 73 delete_area(mem->area); 74 free(mem); 75 } 76 77 static void * 78 es1370_mem_alloc(es1370_dev *card, size_t size) 79 { 80 es1370_mem *mem; 81 82 mem = es1370_mem_new(card, size); 83 if (mem == NULL) 84 return (NULL); 85 86 LIST_INSERT_HEAD(&(card->mems), mem, next); 87 88 return mem; 89 } 90 91 static void 92 es1370_mem_free(es1370_dev *card, void *ptr) 93 { 94 es1370_mem *mem; 95 96 LIST_FOREACH(mem, &card->mems, next) { 97 if (mem->log_base != ptr) 98 continue; 99 LIST_REMOVE(mem, next); 100 101 es1370_mem_delete(mem); 102 break; 103 } 104 } 105 106 /* es1370 stream functions */ 107 108 status_t 109 es1370_stream_set_audioparms(es1370_stream *stream, uint8 channels, 110 uint8 b16, uint32 sample_rate) 111 { 112 uint8 sample_size, frame_size; 113 LOG(("es1370_stream_set_audioparms\n")); 114 115 if ((stream->channels == channels) && 116 (stream->b16 == b16) && 117 (stream->sample_rate == sample_rate)) 118 return B_OK; 119 120 if(stream->buffer) 121 es1370_mem_free(stream->card, stream->buffer->log_base); 122 123 stream->b16 = b16; 124 stream->sample_rate = sample_rate; 125 stream->channels = channels; 126 127 sample_size = stream->b16 + 1; 128 frame_size = sample_size * stream->channels; 129 130 stream->buffer = es1370_mem_alloc(stream->card, stream->bufframes * frame_size * stream->bufcount); 131 132 stream->trigblk = 0; /* This shouldn't be needed */ 133 stream->blkmod = stream->bufcount; 134 stream->blksize = stream->bufframes * frame_size; 135 136 return B_OK; 137 } 138 139 status_t 140 es1370_stream_commit_parms(es1370_stream *stream) 141 { 142 uint8 sample_size, frame_size; 143 uint32 ctrl; 144 es1370_dev *card = stream->card; 145 LOG(("es1370_stream_commit_parms\n")); 146 147 ctrl = es1370_reg_read_32(&card->config, ES1370_REG_CONTROL) & ~CTRL_PCLKDIV; 148 ctrl |= DAC2_SRTODIV((uint16)stream->sample_rate) << CTRL_SH_PCLKDIV; 149 es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, ctrl); 150 151 sample_size = stream->b16 + 1; 152 frame_size = sample_size * stream->channels; 153 154 if (stream->use & ES1370_USE_RECORD) { 155 es1370_reg_write_32(&card->config, ES1370_REG_MEMPAGE, 0xd); 156 es1370_reg_write_32(&card->config, ES1370_REG_ADC_FRAMEADR & 0xff, (uint32)stream->buffer->phy_base); 157 es1370_reg_write_32(&card->config, ES1370_REG_ADC_FRAMECNT & 0xff, ((stream->blksize * stream->bufcount) >> 2) - 1); 158 es1370_reg_write_32(&card->config, ES1370_REG_ADC_SCOUNT & 0xff, stream->bufframes - 1); 159 } else { 160 es1370_reg_write_32(&card->config, ES1370_REG_MEMPAGE, 0xc); 161 es1370_reg_write_32(&card->config, ES1370_REG_DAC2_FRAMEADR & 0xff, (uint32)stream->buffer->phy_base); 162 es1370_reg_write_32(&card->config, ES1370_REG_DAC2_FRAMECNT & 0xff, ((stream->blksize * stream->bufcount) >> 2) - 1); 163 es1370_reg_write_32(&card->config, ES1370_REG_DAC2_SCOUNT & 0xff, stream->bufframes - 1); 164 LOG(("es1370_stream_commit_parms %" B_PRId32 " %" B_PRId32 "\n", 165 ((stream->blksize * stream->bufcount) >> 2) - 1, 166 (stream->blksize / frame_size) - 1)); 167 } 168 169 return B_OK; 170 } 171 172 status_t 173 es1370_stream_get_nth_buffer(es1370_stream *stream, uint8 chan, uint8 buf, 174 char** buffer, size_t *stride) 175 { 176 uint8 sample_size, frame_size; 177 LOG(("es1370_stream_get_nth_buffer\n")); 178 179 sample_size = stream->b16 + 1; 180 frame_size = sample_size * stream->channels; 181 182 *buffer = (char *)stream->buffer->log_base 183 + (buf * stream->bufframes * frame_size) + chan * sample_size; 184 *stride = frame_size; 185 186 return B_OK; 187 } 188 189 static uint32 190 es1370_stream_curaddr(es1370_stream *stream) 191 { 192 es1370_dev *card = stream->card; 193 uint32 reg = 0, cnt = 0; 194 if (stream->use & ES1370_USE_RECORD) { 195 reg = ES1370_REG_ADC_FRAMECNT; 196 } else { 197 reg = ES1370_REG_DAC2_FRAMECNT; 198 } 199 es1370_reg_write_32(&card->config, ES1370_REG_MEMPAGE, reg >> 8); 200 cnt = es1370_reg_read_32(&card->config, reg & 0xff) >> 16; 201 //TRACE(("stream_curaddr %lx\n", (cnt << 2) / stream->blksize)); 202 return (cnt << 2) / stream->blksize; 203 } 204 205 void 206 es1370_stream_start(es1370_stream *stream, void (*inth) (void *), void *inthparam) 207 { 208 uint32 sctrl = 0, ctrl = 0; 209 es1370_dev *card = stream->card; 210 LOG(("es1370_stream_start\n")); 211 212 stream->inth = inth; 213 stream->inthparam = inthparam; 214 215 stream->state |= ES1370_STATE_STARTED; 216 217 sctrl = es1370_reg_read_32(&card->config, ES1370_REG_SERIAL_CONTROL); 218 ctrl = es1370_reg_read_32(&card->config, ES1370_REG_CONTROL); 219 220 if (stream->use & ES1370_USE_RECORD) { 221 sctrl &= ~(SCTRL_R1SEB | SCTRL_R1SMB); 222 if (stream->b16) 223 sctrl |= SCTRL_R1SEB; 224 if (stream->channels == 2) 225 sctrl |= SCTRL_R1SMB; 226 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_R1INTEN); 227 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_R1INTEN); 228 229 ctrl |= CTRL_ADC_EN; 230 } else { 231 sctrl &= ~(SCTRL_P2SEB | SCTRL_P2SMB | 0x003f0000); 232 if (stream->b16) 233 sctrl |= SCTRL_P2SEB; 234 if (stream->channels == 2) 235 sctrl |= SCTRL_P2SMB; 236 sctrl |= (stream->b16 + 1) << SCTRL_SH_P2ENDINC; 237 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_P2INTEN); 238 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_P2INTEN); 239 240 ctrl |= CTRL_DAC2_EN; 241 } 242 243 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl); 244 es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, ctrl); 245 246 #ifdef DEBUG 247 //dump_hardware_regs(&stream->card->config); 248 #endif 249 } 250 251 void 252 es1370_stream_halt(es1370_stream *stream) 253 { 254 uint32 ctrl; 255 es1370_dev *card = stream->card; 256 LOG(("es1370_stream_halt\n")); 257 258 stream->state &= ~ES1370_STATE_STARTED; 259 260 ctrl = es1370_reg_read_32(&card->config, ES1370_REG_CONTROL); 261 if (stream->use & ES1370_USE_RECORD) 262 ctrl &= ~CTRL_ADC_EN; 263 else 264 ctrl &= ~CTRL_DAC2_EN; 265 es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, ctrl); 266 } 267 268 es1370_stream * 269 es1370_stream_new(es1370_dev *card, uint8 use, uint32 bufframes, uint8 bufcount) 270 { 271 es1370_stream *stream; 272 cpu_status status; 273 LOG(("es1370_stream_new\n")); 274 275 stream = malloc(sizeof(es1370_stream)); 276 if (stream == NULL) 277 return (NULL); 278 stream->card = card; 279 stream->use = use; 280 stream->state = !ES1370_STATE_STARTED; 281 stream->b16 = 0; 282 stream->sample_rate = 0; 283 stream->channels = 0; 284 stream->bufframes = bufframes; 285 stream->bufcount = bufcount; 286 stream->inth = NULL; 287 stream->inthparam = NULL; 288 stream->buffer = NULL; 289 stream->blksize = 0; 290 stream->trigblk = 0; 291 stream->blkmod = 0; 292 293 stream->buffer_cycle = 0; 294 stream->frames_count = 0; 295 stream->real_time = 0; 296 stream->update_needed = false; 297 298 status = lock(); 299 LIST_INSERT_HEAD((&card->streams), stream, next); 300 unlock(status); 301 302 return stream; 303 } 304 305 void 306 es1370_stream_delete(es1370_stream *stream) 307 { 308 cpu_status status; 309 LOG(("es1370_stream_delete\n")); 310 311 es1370_stream_halt(stream); 312 313 if(stream->buffer) 314 es1370_mem_free(stream->card, stream->buffer->log_base); 315 316 status = lock(); 317 LIST_REMOVE(stream, next); 318 unlock(status); 319 320 free(stream); 321 } 322 323 /* es1370 interrupt */ 324 325 static int32 326 es1370_int(void *arg) 327 { 328 es1370_dev *card = arg; 329 bool gotone = false; 330 uint32 curblk; 331 es1370_stream *stream = NULL; 332 uint32 sta, sctrl; 333 334 // TRACE(("es1370_int(%p)\n", card)); 335 336 sta = es1370_reg_read_32(&card->config, ES1370_REG_STATUS); 337 if (sta & card->interrupt_mask) { 338 339 //TRACE(("interrupt !! %x\n", sta)); 340 sctrl = es1370_reg_read_32(&card->config, ES1370_REG_SERIAL_CONTROL); 341 342 LIST_FOREACH(stream, &card->streams, next) { 343 if (stream->use & ES1370_USE_RECORD) { 344 if ((sta & STAT_ADC) == 0) 345 continue; 346 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_R1INTEN); 347 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_R1INTEN); 348 } else { 349 if ((sta & STAT_DAC2) == 0) 350 continue; 351 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl & ~SCTRL_P2INTEN); 352 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, sctrl | SCTRL_P2INTEN); 353 } 354 355 curblk = es1370_stream_curaddr(stream); 356 // TRACE(("INTR at trigblk %lu, stream->trigblk %lu\n", curblk, stream->trigblk)); 357 if (curblk == stream->trigblk) { 358 stream->trigblk++; 359 stream->trigblk = stream->trigblk % stream->blkmod; 360 if (stream->inth) 361 stream->inth(stream->inthparam); 362 } 363 gotone = true; 364 } 365 } else { 366 //TRACE(("interrupt masked %x, ", card->interrupt_mask)); 367 //TRACE(("sta %x\n", sta)); 368 } 369 370 if (gotone) 371 return B_INVOKE_SCHEDULER; 372 373 //TRACE(("Got unhandled interrupt\n")); 374 return B_UNHANDLED_INTERRUPT; 375 } 376 377 378 /* es1370 driver functions */ 379 380 381 /* detect presence of our hardware */ 382 status_t 383 init_hardware(void) 384 { 385 int ix=0; 386 pci_info info; 387 status_t err = ENODEV; 388 389 LOG_CREATE(); 390 391 PRINT(("init_hardware()\n")); 392 393 if (get_module(pci_name, (module_info **)&pci)) 394 return ENOSYS; 395 396 while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) { 397 if (info.vendor_id == 0x1274 398 && (info.device_id == 0x5000 399 /*|| info.device_id == 0x1371 400 || info.device_id == 0x5880*/) 401 ) 402 { 403 err = B_OK; 404 } 405 ix++; 406 } 407 408 put_module(pci_name); 409 410 return err; 411 } 412 413 static void 414 make_device_names( 415 es1370_dev * card) 416 { 417 sprintf(card->name, "audio/hmulti/es1370/%ld", card-cards+1); 418 names[num_names++] = card->name; 419 420 names[num_names] = NULL; 421 } 422 423 424 status_t 425 es1370_init(es1370_dev * card) 426 { 427 card->interrupt_mask = STAT_DAC2 | STAT_ADC; 428 429 /* Init streams list */ 430 LIST_INIT(&(card->streams)); 431 432 /* Init mems list */ 433 LIST_INIT(&(card->mems)); 434 435 return B_OK; 436 } 437 438 static status_t 439 es1370_setup(es1370_dev * card) 440 { 441 status_t err = B_OK; 442 unsigned char cmd; 443 444 PRINT(("es1370_setup(%p)\n", card)); 445 446 make_device_names(card); 447 448 card->config.base = card->info.u.h0.base_registers[0]; 449 card->config.irq = card->info.u.h0.interrupt_line; 450 card->config.type = 0; 451 452 PRINT(("%s deviceid = %#04x chiprev = %x model = %x enhanced at %" B_PRIx32 453 "\n", card->name, card->info.device_id, card->info.revision, 454 card->info.u.h0.subsystem_id, card->config.base)); 455 456 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2); 457 PRINT(("PCI command before: %x\n", cmd)); 458 (*pci->write_pci_config)(card->info.bus, card->info.device, 459 card->info.function, PCI_command, 2, 460 cmd | PCI_command_master | PCI_command_io); 461 cmd = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, PCI_command, 2); 462 PRINT(("PCI command after: %x\n", cmd)); 463 464 es1370_reg_write_32(&card->config, ES1370_REG_SERIAL_CONTROL, SCTRL_P2INTEN | SCTRL_R1INTEN); 465 es1370_reg_write_32(&card->config, ES1370_REG_CONTROL, CTRL_CDC_EN); 466 467 /* reset the codec */ 468 PRINT(("codec reset\n")); 469 es1370_codec_write(&card->config, CODEC_RESET_PWRDWN, 0x2); 470 snooze (20); 471 es1370_codec_write(&card->config, CODEC_RESET_PWRDWN, 0x3); 472 snooze (20); 473 es1370_codec_write(&card->config, CODEC_CLOCK_SEL, 0x0); 474 475 /* set max volume on master and mixer outputs */ 476 es1370_codec_write(&card->config, CODEC_MASTER_VOL_L, 0x0); 477 es1370_codec_write(&card->config, CODEC_MASTER_VOL_R, 0x0); 478 es1370_codec_write(&card->config, CODEC_VOICE_VOL_L, 0x0); 479 es1370_codec_write(&card->config, CODEC_VOICE_VOL_R, 0x0); 480 481 /* unmute CD playback */ 482 es1370_codec_write(&card->config, CODEC_OUTPUT_MIX1, ES1370_OUTPUT_MIX1_CDL | ES1370_OUTPUT_MIX1_CDR); 483 /* unmute mixer output */ 484 es1370_codec_write(&card->config, CODEC_OUTPUT_MIX2, ES1370_OUTPUT_MIX2_VOICEL | ES1370_OUTPUT_MIX2_VOICER); 485 486 snooze(50000); // 50 ms 487 488 PRINT(("installing interrupt : %" B_PRIu32 "\n", card->config.irq)); 489 err = install_io_interrupt_handler(card->config.irq, es1370_int, card, 0); 490 if (err != B_OK) { 491 PRINT(("failed to install interrupt\n")); 492 return err; 493 } 494 495 if ((err = es1370_init(card))) 496 return (err); 497 498 PRINT(("init_driver done\n")); 499 500 return err; 501 } 502 503 504 status_t 505 init_driver(void) 506 { 507 void *settings_handle; 508 pci_info info; 509 int ix = 0; 510 status_t err; 511 num_cards = 0; 512 513 PRINT(("init_driver()\n")); 514 515 // get driver settings 516 settings_handle = load_driver_settings ("es1370.settings"); 517 if (settings_handle != NULL) { 518 const char *item; 519 char *end; 520 uint32 value; 521 522 item = get_driver_parameter (settings_handle, "sample_rate", "44100", "44100"); 523 value = strtoul (item, &end, 0); 524 if (*end == '\0') current_settings.sample_rate = value; 525 526 item = get_driver_parameter (settings_handle, "buffer_frames", "512", "512"); 527 value = strtoul (item, &end, 0); 528 if (*end == '\0') current_settings.buffer_frames = value; 529 530 item = get_driver_parameter (settings_handle, "buffer_count", "2", "2"); 531 value = strtoul (item, &end, 0); 532 if (*end == '\0') current_settings.buffer_count = value; 533 534 unload_driver_settings (settings_handle); 535 } 536 537 if (get_module(pci_name, (module_info **) &pci)) 538 return ENOSYS; 539 540 while ((*pci->get_nth_pci_info)(ix++, &info) == B_OK) { 541 if (info.vendor_id == 0x1274 542 && (info.device_id == 0x5000 543 /*|| info.device_id == 0x1371 544 || info.device_id == 0x5880*/) 545 ) { 546 if (num_cards == NUM_CARDS) { 547 PRINT(("Too many es1370 cards installed!\n")); 548 break; 549 } 550 memset(&cards[num_cards], 0, sizeof(es1370_dev)); 551 cards[num_cards].info = info; 552 #ifdef __HAIKU__ 553 if ((err = (*pci->reserve_device)(info.bus, info.device, info.function, 554 DRIVER_NAME, &cards[num_cards])) < B_OK) { 555 dprintf("%s: failed to reserve_device(%d, %d, %d,): %s\n", 556 DRIVER_NAME, info.bus, info.device, info.function, 557 strerror(err)); 558 continue; 559 } 560 #endif 561 if (es1370_setup(&cards[num_cards])) { 562 PRINT(("Setup of es1370 %" B_PRId32 " failed\n", num_cards+1)); 563 #ifdef __HAIKU__ 564 (*pci->unreserve_device)(info.bus, info.device, info.function, 565 DRIVER_NAME, &cards[num_cards]); 566 #endif 567 } 568 else { 569 num_cards++; 570 } 571 } 572 } 573 if (!num_cards) { 574 PRINT(("no cards\n")); 575 put_module(pci_name); 576 PRINT(("no suitable cards found\n")); 577 return ENODEV; 578 } 579 580 return B_OK; 581 } 582 583 584 static void 585 es1370_shutdown(es1370_dev *card) 586 { 587 PRINT(("shutdown(%p)\n", card)); 588 //ac97_amp_enable(&card->config, false); 589 card->interrupt_mask = 0; 590 591 remove_io_interrupt_handler(card->config.irq, es1370_int, card); 592 } 593 594 595 void 596 uninit_driver(void) 597 { 598 int ix, cnt = num_cards; 599 num_cards = 0; 600 601 PRINT(("uninit_driver()\n")); 602 for (ix=0; ix<cnt; ix++) { 603 es1370_shutdown(&cards[ix]); 604 #ifdef __HAIKU__ 605 (*pci->unreserve_device)(cards[ix].info.bus, 606 cards[ix].info.device, cards[ix].info.function, 607 DRIVER_NAME, &cards[ix]); 608 #endif 609 } 610 memset(&cards, 0, sizeof(cards)); 611 put_module(pci_name); 612 } 613 614 615 const char ** 616 publish_devices(void) 617 { 618 int ix = 0; 619 PRINT(("publish_devices()\n")); 620 621 for (ix=0; names[ix]; ix++) { 622 PRINT(("publish %s\n", names[ix])); 623 } 624 return (const char **)names; 625 } 626 627 628 device_hooks * 629 find_device(const char * name) 630 { 631 int ix; 632 633 PRINT(("find_device(%s)\n", name)); 634 635 for (ix=0; ix<num_cards; ix++) { 636 if (!strcmp(cards[ix].name, name)) { 637 return &multi_hooks; 638 } 639 } 640 PRINT(("find_device(%s) failed\n", name)); 641 return NULL; 642 } 643 644 int32 api_version = B_CUR_DRIVER_API_VERSION; 645 646