Changeset a333b7f in mainline
- Timestamp:
- 2014-08-25T09:28:39Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 932e2f5
- Parents:
- 1412a184
- Location:
- uspace/drv/audio/hdaudio
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/audio/hdaudio/hdactl.c
r1412a184 ra333b7f 39 39 #include <ddi.h> 40 40 #include <errno.h> 41 #include <fibril_synch.h> 41 42 #include <macros.h> 42 43 #include <stdint.h> … … 222 223 223 224 /* Set RINTCNT - Qemu won't read from CORB if this is zero */ 224 hda_reg16_write(&hda->regs->rintcnt, 128);225 hda_reg16_write(&hda->regs->rintcnt, hda->ctl->rirb_entries / 2); 225 226 226 227 hda->ctl->rirb_rp = 0; 227 228 228 /* Start RIRB */229 /* Start RIRB and enable RIRB interrupt */ 229 230 ctl = hda_reg8_read(&hda->regs->rirbctl); 230 231 ddf_msg(LVL_NOTE, "RIRBctl (0x%x) = 0x%x", 231 232 (unsigned)((void *)&hda->regs->rirbctl - (void *)hda->regs), ctl | BIT_V(uint8_t, rirbctl_run)); 232 hda_reg8_write(&hda->regs->rirbctl, ctl | BIT_V(uint8_t, rirbctl_run)); 233 hda_reg8_write(&hda->regs->rirbctl, ctl | BIT_V(uint8_t, rirbctl_run) | 234 BIT_V(uint8_t, rirbctl_int)); 233 235 234 236 ddf_msg(LVL_NOTE, "RIRB initialized"); … … 327 329 } 328 330 329 static int hda_rirb_read(hda_t *hda, hda_rirb_entry_t *data , size_t count)331 static int hda_rirb_read(hda_t *hda, hda_rirb_entry_t *data) 330 332 { 331 333 size_t wp; 332 334 hda_rirb_entry_t resp; 333 335 hda_rirb_entry_t *rirb; 336 337 rirb = (hda_rirb_entry_t *)hda->ctl->rirb_virt; 338 339 wp = hda_get_rirbwp(hda); 340 ddf_msg(LVL_DEBUG2, "hda_rirb_read: wp=%d", wp); 341 if (hda->ctl->rirb_rp == wp) 342 return ENOENT; 343 344 ++hda->ctl->rirb_rp; 345 resp = rirb[hda->ctl->rirb_rp]; 346 347 ddf_msg(LVL_DEBUG2, "RESPONSE resp=0x%x respex=0x%x", 348 resp.resp, resp.respex); 349 *data = resp; 350 return EOK; 351 } 352 353 static int hda_solrb_read(hda_t *hda, hda_rirb_entry_t *data, size_t count) 354 { 355 hda_rirb_entry_t resp; 334 356 int wcnt; 335 357 336 rirb = (hda_rirb_entry_t *)hda->ctl->rirb_virt; 358 wcnt = 10; 359 360 fibril_mutex_lock(&hda->ctl->solrb_lock); 337 361 338 362 while (count > 0) { 339 wp = hda_get_rirbwp(hda); 340 ddf_msg(LVL_DEBUG2, "hda_rirb_read: wp=%d", wp); 341 while (count > 0 && hda->ctl->rirb_rp != wp) { 342 ++hda->ctl->rirb_rp; 343 resp = rirb[hda->ctl->rirb_rp]; 344 345 ddf_msg(LVL_DEBUG2, "RESPONSE resp=0x%x respex=0x%x", 363 while (count > 0 && hda->ctl->solrb_rp != hda->ctl->solrb_wp) { 364 ++hda->ctl->solrb_rp; 365 resp = hda->ctl->solrb[hda->ctl->solrb_rp]; 366 367 ddf_msg(LVL_DEBUG2, "solrb RESPONSE resp=0x%x respex=0x%x", 346 368 resp.resp, resp.respex); 347 369 if ((resp.respex & BIT_V(uint32_t, respex_unsol)) == 0) { … … 353 375 354 376 if (count > 0) { 355 w cnt = rirb_wait_max;356 while (wcnt > 0 && hda_get_rirbwp(hda) == hda->ctl->rirb_rp) {377 while (wcnt > 0 && hda->ctl->solrb_wp == hda->ctl->solrb_rp) { 378 fibril_mutex_unlock(&hda->ctl->solrb_lock); 357 379 async_usleep(100); 380 fibril_mutex_lock(&hda->ctl->solrb_lock); 358 381 --wcnt; 359 382 } 360 383 361 if (hda_get_rirbwp(hda) == hda->ctl->rirb_rp) 384 if (hda->ctl->solrb_wp == hda->ctl->solrb_rp) { 385 ddf_msg(LVL_NOTE, "hda_solrb_read() time out"); 386 fibril_mutex_unlock(&hda->ctl->solrb_lock); 362 387 return ETIMEOUT; 363 } 364 } 365 388 } 389 } 390 } 391 392 fibril_mutex_unlock(&hda->ctl->solrb_lock); 366 393 return EOK; 367 394 } … … 371 398 hda_ctl_t *ctl; 372 399 uint32_t gctl; 400 uint32_t intctl; 373 401 int cnt; 374 402 int rc; … … 378 406 return NULL; 379 407 408 fibril_mutex_initialize(&ctl->solrb_lock); 409 fibril_condvar_initialize(&ctl->solrb_cv); 410 380 411 hda->ctl = ctl; 412 ctl->hda = hda; 381 413 382 414 uint8_t vmaj = hda_reg8_read(&hda->regs->vmaj); … … 391 423 392 424 ddf_msg(LVL_NOTE, "reg 0x%zx STATESTS = 0x%x", 393 (void *)&hda->regs->statests - (void *)hda->regs, hda_reg16_read(&hda->regs->statests)); 425 (void *)&hda->regs->statests - (void *)hda->regs, 426 hda_reg16_read(&hda->regs->statests)); 427 /** 428 * Clear STATESTS bits so they don't generate an interrupt later 429 * when we enable interrupts. 430 */ 431 hda_reg16_write(&hda->regs->statests, 0x7f); 432 433 ddf_msg(LVL_NOTE, "after clearing reg 0x%zx STATESTS = 0x%x", 434 (void *)&hda->regs->statests - (void *)hda->regs, 435 hda_reg16_read(&hda->regs->statests)); 394 436 395 437 gctl = hda_reg32_read(&hda->regs->gctl); … … 437 479 hda_reg16_read(&hda->regs->statests)); 438 480 481 async_usleep(1000*1000); 482 483 /* Enable interrupts */ 484 intctl = hda_reg32_read(&hda->regs->intctl); 485 ddf_msg(LVL_NOTE, "intctl (0x%x) := 0x%x", 486 (unsigned)((void *)&hda->regs->intctl - (void *)hda->regs), 487 intctl | BIT_V(uint32_t, intctl_gie) | BIT_V(uint32_t, intctl_cie)); 488 hda_reg32_write(&hda->regs->intctl, intctl | 489 BIT_V(uint32_t, intctl_gie) | BIT_V(uint32_t, intctl_cie)); 490 491 async_usleep(1000*1000); 492 439 493 rc = hda_corb_init(hda); 440 494 if (rc != EOK) 441 495 goto error; 442 496 497 498 async_usleep(1000*1000); 499 443 500 rc = hda_rirb_init(hda); 444 501 if (rc != EOK) 445 502 goto error; 446 503 504 async_usleep(1000*1000); 505 506 ddf_msg(LVL_NOTE, "call hda_codec_init()"); 447 507 hda->ctl->codec = hda_codec_init(hda, 0); 448 if (hda->ctl->codec == NULL) 449 goto error; 508 if (hda->ctl->codec == NULL) { 509 ddf_msg(LVL_NOTE, "hda_codec_init() failed"); 510 goto error; 511 } 450 512 451 513 return ctl; … … 466 528 467 529 if (resp != NULL) { 468 rc = hda_ rirb_read(hda, &rentry, 1);530 rc = hda_solrb_read(hda, &rentry, 1); 469 531 if (rc != EOK) 470 532 return rc; … … 483 545 } 484 546 547 void hda_ctl_interrupt(hda_ctl_t *ctl) 548 { 549 hda_rirb_entry_t resp; 550 int rc; 551 552 while (true) { 553 rc = hda_rirb_read(ctl->hda, &resp); 554 if (rc != EOK) { 555 // ddf_msg(LVL_NOTE, "nothing in rirb"); 556 break; 557 } 558 559 ddf_msg(LVL_NOTE, "writing to solrb"); 560 fibril_mutex_lock(&ctl->solrb_lock); 561 ctl->solrb_wp = (ctl->solrb_wp + 1) % softrb_entries; 562 ctl->solrb[ctl->solrb_wp] = resp; 563 fibril_mutex_unlock(&ctl->solrb_lock); 564 fibril_condvar_broadcast(&ctl->solrb_cv); 565 } 566 } 567 485 568 /** @} 486 569 */ -
uspace/drv/audio/hdaudio/hdactl.h
r1412a184 ra333b7f 36 36 #define HDACTL_H 37 37 38 #include <fibril_synch.h> 38 39 #include <stdbool.h> 39 40 #include "hdaudio.h" 41 #include "spec/regs.h" 42 43 enum { 44 /** Software response buffer size in entries */ 45 softrb_entries = 128 46 }; 40 47 41 48 typedef struct hda_ctl { … … 54 61 size_t rirb_rp; 55 62 63 fibril_mutex_t solrb_lock; 64 fibril_condvar_t solrb_cv; 65 hda_rirb_entry_t solrb[softrb_entries]; 66 size_t solrb_rp; 67 size_t solrb_wp; 68 69 hda_rirb_entry_t unsolrb[softrb_entries]; 70 size_t unsolrb_rp; 71 size_t unsolrb_wp; 72 56 73 struct hda_codec *codec; 74 struct hda *hda; 57 75 } hda_ctl_t; 58 76 59 77 extern hda_ctl_t *hda_ctl_init(hda_t *); 60 78 extern void hda_ctl_fini(hda_ctl_t *); 79 extern void hda_ctl_interrupt(hda_ctl_t *); 61 80 extern int hda_cmd(hda_t *, uint32_t, uint32_t *); 62 81 -
uspace/drv/audio/hdaudio/hdaudio.c
r1412a184 ra333b7f 34 34 35 35 #include <assert.h> 36 #include <bitops.h> 36 37 #include <ddi.h> 37 38 #include <device/hw_res_parsed.h> … … 40 41 #include <str_error.h> 41 42 #include <ddf/driver.h> 43 #include <ddf/interrupt.h> 42 44 #include <ddf/log.h> 43 45 … … 53 55 static int hda_fun_online(ddf_fun_t *fun); 54 56 static int hda_fun_offline(ddf_fun_t *fun); 57 58 static void hdaudio_interrupt(ddf_dev_t *, ipc_callid_t, ipc_call_t *); 55 59 56 60 static driver_ops_t driver_ops = { … … 67 71 }; 68 72 73 irq_pio_range_t hdaudio_irq_pio_ranges[] = { 74 { 75 .base = 0, 76 .size = 8192 77 } 78 }; 79 80 irq_cmd_t hdaudio_irq_commands[] = { 81 { 82 .cmd = CMD_PIO_READ_8, 83 .addr = NULL, 84 .dstarg = 2 85 }, 86 { 87 .cmd = CMD_AND, 88 .value = BIT_V(uint8_t, rirbsts_intfl), 89 .srcarg = 2, 90 .dstarg = 3 91 }, 92 { 93 .cmd = CMD_PREDICATE, 94 .value = 2, 95 .srcarg = 3 96 }, 97 { 98 .cmd = CMD_PIO_WRITE_8, 99 .addr = NULL, 100 .value = BIT_V(uint8_t, rirbsts_intfl), 101 }, 102 { 103 .cmd = CMD_ACCEPT 104 } 105 }; 106 107 irq_code_t hdaudio_irq_code = { 108 .rangecount = sizeof(hdaudio_irq_pio_ranges) / sizeof(irq_pio_range_t), 109 .ranges = hdaudio_irq_pio_ranges, 110 .cmdcount = sizeof(hdaudio_irq_commands) / sizeof(irq_cmd_t), 111 .cmds = hdaudio_irq_commands 112 }; 113 69 114 static int hda_dev_add(ddf_dev_t *dev) 70 115 { … … 110 155 hda->rwsize = RNGSZ(res.mem_ranges.ranges[0]); 111 156 157 ddf_msg(LVL_NOTE, "hda reg base: %" PRIx64, 158 RNGABS(res.mem_ranges.ranges[0])); 159 112 160 if (hda->rwsize < sizeof(hda_regs_t)) { 113 161 ddf_msg(LVL_ERROR, "Memory range is too small."); … … 124 172 125 173 hda->regs = (hda_regs_t *)regs; 174 175 ddf_msg(LVL_NOTE, "IRQs: %d", res.irqs.count); 176 if (res.irqs.count != 1) { 177 ddf_msg(LVL_ERROR, "Unexpected IRQ count %d (!= 1)", 178 res.irqs.count); 179 goto error; 180 } 181 ddf_msg(LVL_NOTE, "interrupt no: %d", res.irqs.irqs[0]); 182 183 hda_regs_t *rphys = (hda_regs_t *)(uintptr_t)hda->rwbase; 184 hdaudio_irq_pio_ranges[0].base = (uintptr_t)hda->rwbase; 185 hdaudio_irq_commands[0].addr = (void *)&rphys->rirbsts; 186 hdaudio_irq_commands[3].addr = (void *)&rphys->rirbsts; 187 ddf_msg(LVL_NOTE, "range0.base=%x", hdaudio_irq_pio_ranges[0].base); 188 ddf_msg(LVL_NOTE, "cmd0.addr=%p", hdaudio_irq_commands[0].addr); 189 ddf_msg(LVL_NOTE, "cmd3.addr=%p", hdaudio_irq_commands[3].addr); 190 191 rc = register_interrupt_handler(dev, res.irqs.irqs[0], 192 hdaudio_interrupt, &hdaudio_irq_code); 193 if (rc != EOK) { 194 ddf_msg(LVL_ERROR, "Failed registering interrupt handler. (%d)", 195 rc); 196 goto error; 197 } 126 198 127 199 if (hda_ctl_init(hda) == NULL) { … … 157 229 } 158 230 231 ddf_msg(LVL_NOTE, "Failing hda_dev_add() -> %d", rc); 159 232 return rc; 160 233 } … … 208 281 } 209 282 283 static void hdaudio_interrupt(ddf_dev_t *dev, ipc_callid_t iid, 284 ipc_call_t *icall) 285 { 286 hda_t *hda = (hda_t *)ddf_dev_data_get(dev); 287 288 ddf_msg(LVL_NOTE, "## interrupt ##"); 289 hda_ctl_interrupt(hda->ctl); 290 } 291 210 292 int main(int argc, char *argv[]) 211 293 { -
uspace/drv/audio/hdaudio/hdaudio.h
r1412a184 ra333b7f 43 43 44 44 /** High Definition Audio driver instance */ 45 typedef struct {45 typedef struct hda { 46 46 async_sess_t *parent_sess; 47 47 ddf_fun_t *fun_a; -
uspace/drv/audio/hdaudio/hdaudio.ma
r1412a184 ra333b7f 1 1 10 pci/ven=1002&dev=4383 2 10 pci/ven=8086&dev=1e20 2 3 10 pci/ven=8086&dev=2668 -
uspace/drv/audio/hdaudio/spec/regs.h
r1412a184 ra333b7f 196 196 197 197 typedef enum { 198 /** Global Interrupt Enable */ 199 intctl_gie = 31, 200 /** Controller Interrupt Enable */ 201 intctl_cie = 30, 202 /** Stream Interrupt Enable */ 203 intctl_sie = 29 204 } hda_intctl_bits_t; 205 206 typedef enum { 198 207 /** CORB Read Pointer Reset */ 199 208 corbrp_rst = 15, … … 248 257 249 258 typedef enum { 259 /** Response Overrun Interrupt Status */ 260 rirbsts_ois = 2, 261 /** Response Interrupt */ 262 rirbsts_intfl = 0 263 } hda_rirbsts_bits_t; 264 265 typedef enum { 250 266 /** RIRB Size Capability (H) */ 251 267 rirbsize_cap_h = 7, -
uspace/drv/audio/hdaudio/stream.c
r1412a184 ra333b7f 175 175 void hda_stream_start(hda_stream_t *stream) 176 176 { 177 ddf_msg(LVL_NOTE, "hda_stream_start()"); 177 178 hda_stream_set_run(stream, true); 178 179 }
Note:
See TracChangeset
for help on using the changeset viewer.