1 /* 2 * Copyright 2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jérôme Duval (korli@users.berlios.de) 7 */ 8 9 10 #include "driver.h" 11 12 #define ALIGN(size, align) (((size) + align - 1) & ~(align - 1)) 13 #define PAGE_ALIGN(size) (((size) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1)) 14 15 #define STREAM_CMD 0x0 /* Command */ 16 #define STREAM_STATUS 0x1 /* IRQ Status */ 17 #define STREAM_PRD 0x4 /* PRD Table Address */ 18 19 static const struct { 20 uint32 multi_rate; 21 uint32 rate; 22 } kRates[] = { 23 {B_SR_8000, 8000}, 24 {B_SR_11025, 11025}, 25 {B_SR_16000, 16000}, 26 {B_SR_22050, 22050}, 27 {B_SR_32000, 32000}, 28 {B_SR_44100, 44100}, 29 {B_SR_48000, 48000}, 30 {B_SR_88200, 88200}, 31 {B_SR_96000, 96000}, 32 {B_SR_176400, 176400}, 33 {B_SR_192000, 192000}, 34 }; 35 36 static int 37 geode_codec_wait(geode_controller *controller) 38 { 39 int i; 40 41 #define GCSCAUDIO_WAIT_READY_CODEC_TIMEOUT 500 42 for (i = GCSCAUDIO_WAIT_READY_CODEC_TIMEOUT; (i >= 0) 43 && (controller->Read32(ACC_CODEC_CNTL) & ACC_CODEC_CNTL_CMD_NEW); i--) 44 snooze(10); 45 46 return (i < 0); 47 } 48 49 uint16 50 geode_codec_read(geode_controller *controller, uint8 regno) 51 { 52 int i; 53 uint32 v; 54 ASSERT(regno >= 0); 55 56 controller->Write32(ACC_CODEC_CNTL, 57 ACC_CODEC_CNTL_READ_CMD | ACC_CODEC_CNTL_CMD_NEW | 58 ACC_CODEC_REG2ADDR(regno)); 59 60 if (geode_codec_wait(controller) != B_OK) { 61 dprintf("codec busy (2)\n"); 62 return 0xffff; 63 } 64 65 #define GCSCAUDIO_READ_CODEC_TIMEOUT 50 66 for (i = GCSCAUDIO_READ_CODEC_TIMEOUT; i >= 0; i--) { 67 v = controller->Read32(ACC_CODEC_STATUS); 68 if ((v & ACC_CODEC_STATUS_STS_NEW) && 69 (ACC_CODEC_ADDR2REG(v) == regno)) 70 break; 71 72 snooze(10); 73 } 74 75 if (i < 0) { 76 dprintf("codec busy (3)\n"); 77 return 0xffff; 78 } 79 80 return v; 81 } 82 83 void 84 geode_codec_write(geode_controller *controller, uint8 regno, uint16 value) 85 { 86 ASSERT(regno >= 0); 87 88 controller->Write32(ACC_CODEC_CNTL, 89 ACC_CODEC_CNTL_WRITE_CMD | 90 ACC_CODEC_CNTL_CMD_NEW | 91 ACC_CODEC_REG2ADDR(regno) | 92 (value & ACC_CODEC_CNTL_CMD_DATA_MASK)); 93 94 if (geode_codec_wait(controller) != B_OK) { 95 dprintf("codec busy (4)\n"); 96 } 97 } 98 99 100 //! Called with interrupts off 101 static void 102 stream_handle_interrupt(geode_controller* controller, geode_stream* stream) 103 { 104 uint8 status; 105 uint32 position, bufferSize; 106 107 if (!stream->running) 108 return; 109 110 status = stream->Read8(STREAM_STATUS); 111 112 if (status & ACC_BMx_STATUS_BM_EOP_ERR) { 113 dprintf("geode: stream status bus master error\n"); 114 } 115 if (status & ACC_BMx_STATUS_EOP) { 116 dprintf("geode: stream status end of page\n"); 117 } 118 119 position = controller->Read32(ACC_BM0_PNTR + stream->dma_offset); 120 bufferSize = ALIGN(stream->sample_size * stream->num_channels * stream->buffer_length, 128); 121 122 // Buffer Completed Interrupt 123 acquire_spinlock(&stream->lock); 124 125 stream->real_time = system_time(); 126 stream->frames_count += stream->buffer_length; 127 stream->buffer_cycle = 1 - (position / (bufferSize + 1)); // added 1 to avoid having 2 128 129 release_spinlock(&stream->lock); 130 131 release_sem_etc(stream->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE); 132 } 133 134 135 static int32 136 geode_interrupt_handler(geode_controller* controller) 137 { 138 uint16 intr = controller->Read16(ACC_IRQ_STATUS); 139 if (intr == 0) 140 return B_UNHANDLED_INTERRUPT; 141 142 for (uint32 index = 0; index < GEODE_MAX_STREAMS; index++) { 143 if (controller->streams[index] 144 && (intr & controller->streams[index]->status) != 0) { 145 stream_handle_interrupt(controller, 146 controller->streams[index]); 147 } 148 } 149 150 return B_HANDLED_INTERRUPT; 151 } 152 153 154 static status_t 155 reset_controller(geode_controller* controller) 156 { 157 controller->Write32(ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST 158 | ACC_CODEC_CNTL_CMD_NEW); 159 160 if (geode_codec_wait(controller) != B_OK) { 161 dprintf("codec reset busy (1)\n"); 162 } 163 164 // stop streams 165 166 // stop DMA 167 168 // reset DMA position buffer 169 170 return B_OK; 171 } 172 173 // #pragma mark - public stream functions 174 175 176 void 177 geode_stream_delete(geode_stream* stream) 178 { 179 if (stream->buffer_ready_sem >= B_OK) 180 delete_sem(stream->buffer_ready_sem); 181 182 if (stream->buffer_area >= B_OK) 183 delete_area(stream->buffer_area); 184 185 if (stream->buffer_descriptors_area >= B_OK) 186 delete_area(stream->buffer_descriptors_area); 187 188 free(stream); 189 } 190 191 192 geode_stream* 193 geode_stream_new(geode_controller* controller, int type) 194 { 195 geode_stream* stream = (geode_stream*)calloc(1, sizeof(geode_stream)); 196 if (stream == NULL) 197 return NULL; 198 199 stream->buffer_ready_sem = B_ERROR; 200 stream->buffer_area = B_ERROR; 201 stream->buffer_descriptors_area = B_ERROR; 202 stream->type = type; 203 stream->controller = controller; 204 205 switch (type) { 206 case STREAM_PLAYBACK: 207 stream->status = ACC_IRQ_STATUS_BM0_IRQ_STS; 208 stream->offset = 0; 209 stream->dma_offset = 0; 210 stream->ac97_rate_reg = AC97_PCM_FRONT_DAC_RATE; 211 break; 212 213 case STREAM_RECORD: 214 stream->status = ACC_IRQ_STATUS_BM1_IRQ_STS; 215 stream->offset = 0x8; 216 stream->dma_offset = 0x4; 217 stream->ac97_rate_reg = AC97_PCM_L_R_ADC_RATE; 218 break; 219 220 default: 221 dprintf("%s: Unknown stream type %d!\n", __func__, type); 222 free(stream); 223 stream = NULL; 224 } 225 226 controller->streams[controller->num_streams++] = stream; 227 return stream; 228 } 229 230 231 /*! Starts a stream's DMA engine, and enables generating and receiving 232 interrupts for this stream. 233 */ 234 status_t 235 geode_stream_start(geode_stream* stream) 236 { 237 uint8 value; 238 dprintf("geode_stream_start()\n"); 239 stream->buffer_ready_sem = create_sem(0, stream->type == STREAM_PLAYBACK 240 ? "geode_playback_sem" : "geode_record_sem"); 241 if (stream->buffer_ready_sem < B_OK) 242 return stream->buffer_ready_sem; 243 244 if (stream->type == STREAM_PLAYBACK) 245 value = ACC_BMx_CMD_WRITE; 246 else 247 value = ACC_BMx_CMD_READ; 248 249 stream->Write8(STREAM_CMD, value | ACC_BMx_CMD_BYTE_ORD_EL 250 | ACC_BMx_CMD_BM_CTL_ENABLE); 251 252 stream->running = true; 253 return B_OK; 254 } 255 256 257 /*! Stops the stream's DMA engine, and turns off interrupts for this 258 stream. 259 */ 260 status_t 261 geode_stream_stop(geode_stream* stream) 262 { 263 dprintf("geode_stream_stop()\n"); 264 stream->Write8(STREAM_CMD, ACC_BMx_CMD_BM_CTL_DISABLE); 265 266 stream->running = false; 267 delete_sem(stream->buffer_ready_sem); 268 stream->buffer_ready_sem = -1; 269 270 return B_OK; 271 } 272 273 274 status_t 275 geode_stream_setup_buffers(geode_stream* stream, const char* desc) 276 { 277 uint32 bufferSize, alloc; 278 uint32 index; 279 physical_entry pe; 280 struct acc_prd* bufferDescriptors; 281 uint8* buffer; 282 status_t rc; 283 284 /* Clear previously allocated memory */ 285 if (stream->buffer_area >= B_OK) { 286 delete_area(stream->buffer_area); 287 stream->buffer_area = B_ERROR; 288 } 289 290 if (stream->buffer_descriptors_area >= B_OK) { 291 delete_area(stream->buffer_descriptors_area); 292 stream->buffer_descriptors_area = B_ERROR; 293 } 294 295 /* Calculate size of buffer (aligned to 128 bytes) */ 296 bufferSize = stream->sample_size * stream->num_channels 297 * stream->buffer_length; 298 bufferSize = ALIGN(bufferSize, 128); 299 300 dprintf("geode: sample size %ld, num channels %ld, buffer length %ld ****************\n", 301 stream->sample_size, stream->num_channels, stream->buffer_length); 302 303 /* Calculate total size of all buffers (aligned to size of B_PAGE_SIZE) */ 304 alloc = bufferSize * stream->num_buffers; 305 alloc = PAGE_ALIGN(alloc); 306 307 /* Allocate memory for buffers */ 308 stream->buffer_area = create_area("geode buffers", (void**)&buffer, 309 B_ANY_KERNEL_ADDRESS, alloc, B_32_BIT_CONTIGUOUS, 310 B_READ_AREA | B_WRITE_AREA); 311 // TODO: The rest of the code doesn't deal correctly with physical 312 // addresses > 4 GB, so we have to force 32 bit addresses here. 313 if (stream->buffer_area < B_OK) 314 return stream->buffer_area; 315 316 /* Get the physical address of memory */ 317 rc = get_memory_map(buffer, alloc, &pe, 1); 318 if (rc != B_OK) { 319 delete_area(stream->buffer_area); 320 return rc; 321 } 322 323 phys_addr_t bufferPhysicalAddress = pe.address; 324 325 dprintf("%s(%s): Allocated %lu bytes for %ld buffers\n", __func__, desc, 326 alloc, stream->num_buffers); 327 328 /* Store pointers (both virtual/physical) */ 329 for (index = 0; index < stream->num_buffers; index++) { 330 stream->buffers[index] = buffer + (index * bufferSize); 331 stream->physical_buffers[index] = bufferPhysicalAddress 332 + (index * bufferSize); 333 } 334 335 /* Now allocate BDL for buffer range */ 336 alloc = stream->num_buffers * sizeof(struct acc_prd) + 1; 337 alloc = PAGE_ALIGN(alloc); 338 339 stream->buffer_descriptors_area = create_area("geode buffer descriptors", 340 (void**)&bufferDescriptors, B_ANY_KERNEL_ADDRESS, alloc, 341 B_32_BIT_CONTIGUOUS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 342 // TODO: The rest of the code doesn't deal correctly with physical 343 // addresses > 4 GB, so we have to force 32 bit addresses here. 344 if (stream->buffer_descriptors_area < B_OK) { 345 delete_area(stream->buffer_area); 346 return stream->buffer_descriptors_area; 347 } 348 349 /* Get the physical address of memory */ 350 rc = get_memory_map(bufferDescriptors, alloc, &pe, 1); 351 if (rc != B_OK) { 352 delete_area(stream->buffer_area); 353 delete_area(stream->buffer_descriptors_area); 354 return rc; 355 } 356 357 stream->physical_buffer_descriptors = pe.address; 358 359 dprintf("%s(%s): Allocated %ld bytes for %ld BDLEs\n", __func__, desc, 360 alloc, stream->num_buffers); 361 362 /* Setup buffer descriptor list (BDL) entries */ 363 for (index = 0; index < stream->num_buffers; index++, bufferDescriptors++) { 364 bufferDescriptors->address = stream->physical_buffers[index]; 365 bufferDescriptors->ctrlsize = bufferSize | ACC_BMx_PRD_CTRL_EOP; 366 // we want an interrupt after every buffer 367 } 368 bufferDescriptors->address = stream->physical_buffer_descriptors; 369 bufferDescriptors->ctrlsize = ACC_BMx_PRD_CTRL_JMP; 370 371 for (index = 0; index < sizeof(kRates) / sizeof(kRates[0]); index++) { 372 if (kRates[index].multi_rate == stream->sample_rate) { 373 stream->rate = kRates[index].rate; 374 break; 375 } 376 } 377 378 /* Configure stream registers */ 379 dprintf("IRA: %s: setup stream SR=%ld\n", __func__, stream->rate); 380 381 stream->Write32(STREAM_PRD, stream->physical_buffer_descriptors); 382 383 ac97_set_rate(stream->controller->ac97, stream->ac97_rate_reg, stream->rate); 384 snooze(1000); 385 return B_OK; 386 } 387 388 389 // #pragma mark - public controller functions 390 391 392 /*! Setup hardware for use; detect codecs; etc */ 393 status_t 394 geode_hw_init(geode_controller* controller) 395 { 396 uint16 cmd; 397 status_t status; 398 399 cmd = (gPci->read_pci_config)(controller->pci_info.bus, 400 controller->pci_info.device, controller->pci_info.function, PCI_command, 2); 401 if (!(cmd & PCI_command_master)) { 402 (gPci->write_pci_config)(controller->pci_info.bus, 403 controller->pci_info.device, controller->pci_info.function, 404 PCI_command, 2, cmd | PCI_command_master); 405 dprintf("geode: enabling PCI bus mastering\n"); 406 } 407 408 controller->nabmbar = controller->pci_info.u.h0.base_registers[0]; 409 410 /* Absolute minimum hw is online; we can now install interrupt handler */ 411 controller->irq = controller->pci_info.u.h0.interrupt_line; 412 status = install_io_interrupt_handler(controller->irq, 413 (interrupt_handler)geode_interrupt_handler, controller, 0); 414 if (status != B_OK) 415 goto error; 416 417 /* Get controller into valid state */ 418 status = reset_controller(controller); 419 if (status != B_OK) { 420 dprintf("geode: reset_controller failed\n"); 421 goto reset_failed; 422 } 423 424 /* attach the codec */ 425 ac97_attach(&controller->ac97, (codec_reg_read)geode_codec_read, 426 (codec_reg_write)geode_codec_write, controller, 427 controller->pci_info.u.h0.subsystem_vendor_id, 428 controller->pci_info.u.h0.subsystem_id); 429 430 snooze(1000); 431 432 controller->multi = (geode_multi*)calloc(1, sizeof(geode_multi)); 433 if (controller->multi == NULL) 434 return B_NO_MEMORY; 435 436 controller->playback_stream = geode_stream_new(controller, STREAM_PLAYBACK); 437 controller->record_stream = geode_stream_new(controller, STREAM_RECORD); 438 439 return B_OK; 440 441 reset_failed: 442 remove_io_interrupt_handler(controller->irq, 443 (interrupt_handler)geode_interrupt_handler, controller); 444 error: 445 dprintf("geode: ERROR: %s(%ld)\n", strerror(status), status); 446 447 return status; 448 } 449 450 451 /*! Stop any activity */ 452 void 453 geode_hw_stop(geode_controller* controller) 454 { 455 int index; 456 457 /* Stop all audio streams */ 458 for (index = 0; index < GEODE_MAX_STREAMS; index++) { 459 if (controller->streams[index] && controller->streams[index]->running) 460 geode_stream_stop(controller->streams[index]); 461 } 462 } 463 464 465 /*! Free resources */ 466 void 467 geode_hw_uninit(geode_controller* controller) 468 { 469 if (controller == NULL) 470 return; 471 472 /* Stop all audio streams */ 473 geode_hw_stop(controller); 474 475 reset_controller(controller); 476 477 remove_io_interrupt_handler(controller->irq, 478 (interrupt_handler)geode_interrupt_handler, controller); 479 480 free(controller->multi); 481 482 geode_stream_delete(controller->playback_stream); 483 geode_stream_delete(controller->record_stream); 484 485 } 486 487