source: mainline/uspace/drv/audio/hdaudio/hdactl.c@ c67195c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c67195c was c67195c, checked in by Jiri Svoboda <jiri@…>, 11 years ago

Fix resetting of CORBRP.

  • Property mode set to 100644
File size: 16.4 KB
Line 
1/*
2 * Copyright (c) 2014 Jiri Svoboda
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 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup hdaudio
30 * @{
31 */
32/** @file High Definition Audio controller
33 */
34
35#include <as.h>
36#include <async.h>
37#include <bitops.h>
38#include <ddf/log.h>
39#include <ddi.h>
40#include <errno.h>
41#include <fibril_synch.h>
42#include <macros.h>
43#include <stdint.h>
44
45#include "codec.h"
46#include "hdactl.h"
47#include "regif.h"
48#include "spec/regs.h"
49
50enum {
51 ctrl_init_wait_max = 10,
52 codec_enum_wait_us = 512,
53 corb_wait_max = 10,
54 rirb_wait_max = 100
55};
56
57/** Perform set-reset handshake on a 16-bit register.
58 *
59 * The bit(s) specified in the mask are written as 1, then we wait
60 * for them to read as 1. Then we write them as 0 and we wait for them
61 * to read as 0.
62 */
63static int hda_ctl_reg16_set_reset(uint16_t *reg, uint16_t mask)
64{
65 uint16_t val;
66 int wcnt;
67
68 val = hda_reg16_read(reg);
69 hda_reg16_write(reg, val | mask);
70
71 wcnt = 1000;
72 while (wcnt > 0) {
73 val = hda_reg16_read(reg);
74 if ((val & mask) == mask)
75 break;
76
77 async_usleep(1000);
78 --wcnt;
79 }
80
81 if ((val & mask) != mask)
82 return ETIMEOUT;
83
84 val = hda_reg16_read(reg);
85 hda_reg16_write(reg, val & ~mask);
86
87 wcnt = 1000;
88 while (wcnt > 0) {
89 val = hda_reg16_read(reg);
90 if ((val & mask) == 0)
91 break;
92
93 async_usleep(1000);
94 --wcnt;
95 }
96
97 if ((val & mask) != 0)
98 return ETIMEOUT;
99
100 return EOK;
101}
102
103/** Select an appropriate CORB/RIRB size.
104 *
105 * We always use the largest available size. In @a sizecap each of bits
106 * 0, 1, 2 determine whether one of the supported size (0 == 2 enries,
107 * 1 == 16 entries, 2 == 256 entries) is supported. @a *selsz is set to
108 * one of 0, 1, 2 on success.
109 *
110 * @param sizecap CORB/RIRB Size Capability
111 * @param selsz Place to store CORB/RIRB Size
112 * @return EOK on success, EINVAL if sizecap has no valid bits set
113 *
114 */
115static int hda_rb_size_select(uint8_t sizecap, uint8_t *selsz)
116{
117 int i;
118
119 for (i = 2; i >= 0; --i) {
120 if ((sizecap & BIT_V(uint8_t, i)) != 0) {
121 *selsz = i;
122 return EOK;
123 }
124 }
125
126 return EINVAL;
127}
128
129static size_t hda_rb_entries(uint8_t selsz)
130{
131 switch (selsz) {
132 case 0:
133 return 2;
134 case 1:
135 return 16;
136 case 2:
137 return 256;
138 default:
139 assert(false);
140 return 0;
141 }
142}
143
144/** Initialize the CORB */
145static int hda_corb_init(hda_t *hda)
146{
147 uint8_t ctl;
148 uint8_t corbsz;
149 uint8_t sizecap;
150 uint8_t selsz;
151 int rc;
152
153 ddf_msg(LVL_NOTE, "hda_corb_init()");
154
155 /* Stop CORB if not stopped */
156 ctl = hda_reg8_read(&hda->regs->corbctl);
157 if ((ctl & BIT_V(uint8_t, corbctl_run)) != 0) {
158 ddf_msg(LVL_NOTE, "CORB is enabled, disabling first.");
159 hda_reg8_write(&hda->regs->corbctl, ctl & ~BIT_V(uint8_t,
160 corbctl_run));
161 }
162
163 /* Determine CORB size and allocate CORB buffer */
164 corbsz = hda_reg8_read(&hda->regs->corbsize);
165 sizecap = BIT_RANGE_EXTRACT(uint8_t, corbsize_cap_h,
166 corbsize_cap_l, corbsz);
167 rc = hda_rb_size_select(sizecap, &selsz);
168 if (rc != EOK) {
169 ddf_msg(LVL_ERROR, "Invalid CORB Size Capability");
170 goto error;
171 }
172 corbsz = corbsz & ~BIT_RANGE(uint8_t, corbsize_size_h, corbsize_size_l);
173 corbsz = corbsz | selsz;
174
175 ddf_msg(LVL_NOTE, "Setting CORB Size register to 0x%x", corbsz);
176 hda_reg8_write(&hda->regs->corbsize, corbsz);
177 hda->ctl->corb_entries = hda_rb_entries(selsz);
178
179
180 /*
181 * CORB must be aligned to 128 bytes. If 64OK is not set,
182 * it must be within the 32-bit address space.
183 */
184 hda->ctl->corb_virt = AS_AREA_ANY;
185 rc = dmamem_map_anonymous(hda->ctl->corb_entries * sizeof(uint32_t),
186 hda->ctl->ok64bit ? 0 : DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0,
187 &hda->ctl->corb_phys, &hda->ctl->corb_virt);
188
189 ddf_msg(LVL_NOTE, "Set CORB base registers");
190
191 /* Update CORB base registers */
192 hda_reg32_write(&hda->regs->corblbase, LOWER32(hda->ctl->corb_phys));
193 hda_reg32_write(&hda->regs->corbubase, UPPER32(hda->ctl->corb_phys));
194
195 ddf_msg(LVL_NOTE, "Reset CORB Read/Write pointers");
196
197 /* Reset CORB Read Pointer */
198 rc = hda_ctl_reg16_set_reset(&hda->regs->corbrp,
199 BIT_V(uint16_t, corbrp_rst));
200 if (rc != EOK) {
201 ddf_msg(LVL_NOTE, "Failed resetting CORBRP");
202 goto error;
203 }
204
205 /* Reset CORB Write Pointer */
206 hda_reg16_write(&hda->regs->corbwp, 0);
207
208 /* Start CORB */
209 ctl = hda_reg8_read(&hda->regs->corbctl);
210 ddf_msg(LVL_NOTE, "CORBctl (0x%x) = 0x%x",
211 (unsigned)((void *)&hda->regs->corbctl - (void *)hda->regs), ctl | BIT_V(uint8_t, corbctl_run));
212 hda_reg8_write(&hda->regs->corbctl, ctl | BIT_V(uint8_t, corbctl_run));
213
214 ddf_msg(LVL_NOTE, "CORB initialized");
215 return EOK;
216error:
217 return EIO;
218}
219
220/** Initialize the RIRB */
221static int hda_rirb_init(hda_t *hda)
222{
223 uint8_t ctl;
224 uint8_t rirbsz;
225 uint8_t sizecap;
226 uint8_t selsz;
227 int rc;
228
229 ddf_msg(LVL_NOTE, "hda_rirb_init()");
230
231 /* Stop RIRB if not stopped */
232 ctl = hda_reg8_read(&hda->regs->rirbctl);
233 if ((ctl & BIT_V(uint8_t, rirbctl_run)) != 0) {
234 ddf_msg(LVL_NOTE, "RIRB is enabled, disabling first.");
235 hda_reg8_write(&hda->regs->corbctl, ctl & ~BIT_V(uint8_t,
236 rirbctl_run));
237 }
238
239 /* Determine RIRB size and allocate RIRB buffer */
240 rirbsz = hda_reg8_read(&hda->regs->rirbsize);
241 sizecap = BIT_RANGE_EXTRACT(uint8_t, rirbsize_cap_h,
242 rirbsize_cap_l, rirbsz);
243 rc = hda_rb_size_select(sizecap, &selsz);
244 if (rc != EOK) {
245 ddf_msg(LVL_ERROR, "Invalid RIRB Size Capability");
246 goto error;
247 }
248 rirbsz = rirbsz & ~BIT_RANGE(uint8_t, rirbsize_size_h, rirbsize_size_l);
249 rirbsz = rirbsz | selsz;
250
251 ddf_msg(LVL_NOTE, "Setting RIRB Size register to 0x%x", rirbsz);
252 hda_reg8_write(&hda->regs->rirbsize, rirbsz);
253 hda->ctl->rirb_entries = hda_rb_entries(selsz);
254
255 /*
256 * RIRB must be aligned to 128 bytes. If 64OK is not set,
257 * it must be within the 32-bit address space.
258 */
259 hda->ctl->rirb_virt = AS_AREA_ANY;
260 rc = dmamem_map_anonymous(hda->ctl->rirb_entries * sizeof(uint64_t),
261 hda->ctl->ok64bit ? 0 : DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0,
262 &hda->ctl->rirb_phys, &hda->ctl->rirb_virt);
263
264 ddf_msg(LVL_NOTE, "Set RIRB base registers");
265
266 /* Update RIRB base registers */
267 hda_reg32_write(&hda->regs->rirblbase, LOWER32(hda->ctl->rirb_phys));
268 hda_reg32_write(&hda->regs->rirbubase, UPPER32(hda->ctl->rirb_phys));
269
270 ddf_msg(LVL_NOTE, "Reset RIRB Write pointer");
271
272 /* Reset RIRB Write Pointer */
273 hda_reg16_write(&hda->regs->rirbwp, BIT_V(uint16_t, rirbwp_rst));
274
275 /* Set RINTCNT - Qemu won't read from CORB if this is zero */
276 hda_reg16_write(&hda->regs->rintcnt, hda->ctl->rirb_entries / 2);
277
278 hda->ctl->rirb_rp = 0;
279
280 /* Start RIRB and enable RIRB interrupt */
281 ctl = hda_reg8_read(&hda->regs->rirbctl);
282 ddf_msg(LVL_NOTE, "RIRBctl (0x%x) = 0x%x",
283 (unsigned)((void *)&hda->regs->rirbctl - (void *)hda->regs), ctl | BIT_V(uint8_t, rirbctl_run));
284 hda_reg8_write(&hda->regs->rirbctl, ctl | BIT_V(uint8_t, rirbctl_run) |
285 BIT_V(uint8_t, rirbctl_int));
286
287 ddf_msg(LVL_NOTE, "RIRB initialized");
288 return EOK;
289error:
290 return EIO;
291}
292
293static size_t hda_get_corbrp(hda_t *hda)
294{
295 uint16_t corbrp;
296
297 corbrp = hda_reg16_read(&hda->regs->corbrp);
298 return BIT_RANGE_EXTRACT(uint16_t, corbrp_rp_h, corbrp_rp_l, corbrp);
299}
300
301static size_t hda_get_corbwp(hda_t *hda)
302{
303 uint16_t corbwp;
304
305 corbwp = hda_reg16_read(&hda->regs->corbwp);
306 return BIT_RANGE_EXTRACT(uint16_t, corbwp_wp_h, corbwp_wp_l, corbwp);
307}
308
309static void hda_set_corbwp(hda_t *hda, size_t wp)
310{
311 ddf_msg(LVL_DEBUG2, "Set CORBWP = %d", wp);
312 hda_reg16_write(&hda->regs->corbwp, wp);
313}
314
315static size_t hda_get_rirbwp(hda_t *hda)
316{
317 uint16_t rirbwp;
318
319 rirbwp = hda_reg16_read(&hda->regs->rirbwp);
320 return BIT_RANGE_EXTRACT(uint16_t, rirbwp_wp_h, rirbwp_wp_l, rirbwp);
321}
322
323/** Determine number of free entries in CORB */
324static size_t hda_corb_avail(hda_t *hda)
325{
326 int rp, wp;
327 int avail;
328
329 rp = hda_get_corbrp(hda);
330 wp = hda_get_corbwp(hda);
331
332 avail = rp - wp - 1;
333 while (avail < 0)
334 avail += hda->ctl->corb_entries;
335
336 return avail;
337}
338
339/** Write to CORB */
340static int hda_corb_write(hda_t *hda, uint32_t *data, size_t count)
341{
342 size_t avail;
343 size_t wp;
344 size_t idx;
345 size_t now;
346 size_t i;
347 uint32_t *corb;
348 int wcnt;
349
350 avail = hda_corb_avail(hda);
351 wp = hda_get_corbwp(hda);
352 corb = (uint32_t *)hda->ctl->corb_virt;
353
354 idx = 0;
355 while (idx < count) {
356 now = min(avail, count - idx);
357
358 for (i = 0; i < now; i++) {
359 wp = (wp + 1) % hda->ctl->corb_entries;
360 corb[wp] = data[idx++];
361 }
362
363 hda_set_corbwp(hda, wp);
364
365 if (idx < count) {
366 /* We filled up CORB but still data remaining */
367 wcnt = corb_wait_max;
368 while (hda_corb_avail(hda) < 1 && wcnt > 0) {
369 async_usleep(100);
370 --wcnt;
371 }
372
373 /* If CORB is still full return timeout error */
374 if (hda_corb_avail(hda) < 1)
375 return ETIMEOUT;
376 }
377 }
378
379 return EOK;
380}
381
382static int hda_rirb_read(hda_t *hda, hda_rirb_entry_t *data)
383{
384 size_t wp;
385 hda_rirb_entry_t resp;
386 hda_rirb_entry_t *rirb;
387
388 rirb = (hda_rirb_entry_t *)hda->ctl->rirb_virt;
389
390 wp = hda_get_rirbwp(hda);
391 ddf_msg(LVL_DEBUG2, "hda_rirb_read: wp=%d", wp);
392 if (hda->ctl->rirb_rp == wp)
393 return ENOENT;
394
395 ++hda->ctl->rirb_rp;
396 resp = rirb[hda->ctl->rirb_rp];
397
398 ddf_msg(LVL_DEBUG2, "RESPONSE resp=0x%x respex=0x%x",
399 resp.resp, resp.respex);
400 *data = resp;
401 return EOK;
402}
403
404static int hda_solrb_read(hda_t *hda, hda_rirb_entry_t *data, size_t count)
405{
406 hda_rirb_entry_t resp;
407 int wcnt;
408
409 ddf_msg(LVL_NOTE, "hda_solrb_read()");
410 wcnt = 100;
411
412 ddf_msg(LVL_NOTE, "hda_solrb_read() - lock mutex");
413 fibril_mutex_lock(&hda->ctl->solrb_lock);
414
415 while (count > 0) {
416 ddf_msg(LVL_NOTE, "hda_solrb_read() - while(1)");
417 while (count > 0 && hda->ctl->solrb_rp != hda->ctl->solrb_wp) {
418 ddf_msg(LVL_NOTE, "hda_solrb_read() - while(2)");
419 ++hda->ctl->solrb_rp;
420 resp = hda->ctl->solrb[hda->ctl->solrb_rp];
421
422 ddf_msg(LVL_NOTE, "solrb RESPONSE resp=0x%x respex=0x%x",
423 resp.resp, resp.respex);
424 if ((resp.respex & BIT_V(uint32_t, respex_unsol)) == 0) {
425 /* Solicited response */
426 *data++ = resp;
427 --count;
428 }
429 }
430
431 if (count > 0) {
432 ddf_msg(LVL_NOTE, "hda_solrb_read() - count > 0");
433 while (wcnt > 0 && hda->ctl->solrb_wp == hda->ctl->solrb_rp) {
434 ddf_msg(LVL_NOTE, "hda_solrb_read() - while(3), wcnt=%d", wcnt);
435 fibril_mutex_unlock(&hda->ctl->solrb_lock);
436 ddf_msg(LVL_NOTE, "hda_solrb_read() - sleep");
437 async_usleep(10000);
438 ddf_msg(LVL_NOTE, "hda_solrb_read() - re-lock");
439 fibril_mutex_lock(&hda->ctl->solrb_lock);
440 --wcnt;
441 }
442
443 if (hda->ctl->solrb_wp == hda->ctl->solrb_rp) {
444 ddf_msg(LVL_NOTE, "hda_solrb_read() time out");
445 ddf_msg(LVL_NOTE, "corbwp=%d corbrp=%d",
446 hda_reg16_read(&hda->regs->corbwp),
447 hda_reg16_read(&hda->regs->corbrp));
448 ddf_msg(LVL_NOTE, "corbctl=0x%x, corbsts=0x%x",
449 hda_reg8_read(&hda->regs->corbctl),
450 hda_reg8_read(&hda->regs->corbsts));
451 ddf_msg(LVL_NOTE, "rirbwp=%d",
452 hda_reg16_read(&hda->regs->rirbwp));
453 ddf_msg(LVL_NOTE, "rirbctl=0x%x, rirbsts=0x%x",
454 hda_reg8_read(&hda->regs->rirbctl),
455 hda_reg8_read(&hda->regs->rirbsts));
456 fibril_mutex_unlock(&hda->ctl->solrb_lock);
457 return ETIMEOUT;
458 }
459 }
460 }
461
462 fibril_mutex_unlock(&hda->ctl->solrb_lock);
463 ddf_msg(LVL_NOTE, "hda_solrb_read() success");
464 return EOK;
465}
466
467hda_ctl_t *hda_ctl_init(hda_t *hda)
468{
469 hda_ctl_t *ctl;
470 uint32_t gctl;
471 uint32_t intctl;
472 int cnt;
473 int rc;
474
475 ctl = calloc(1, sizeof(hda_ctl_t));
476 if (ctl == NULL)
477 return NULL;
478
479 fibril_mutex_initialize(&ctl->solrb_lock);
480 fibril_condvar_initialize(&ctl->solrb_cv);
481
482 hda->ctl = ctl;
483 ctl->hda = hda;
484
485 uint8_t vmaj = hda_reg8_read(&hda->regs->vmaj);
486 uint8_t vmin = hda_reg8_read(&hda->regs->vmin);
487 ddf_msg(LVL_NOTE, "HDA version %d.%d", vmaj, vmin);
488
489 if (vmaj != 1 || vmin != 0) {
490 ddf_msg(LVL_ERROR, "Unsupported HDA version (%d.%d).",
491 vmaj, vmin);
492 goto error;
493 }
494
495 ddf_msg(LVL_NOTE, "reg 0x%zx STATESTS = 0x%x",
496 (void *)&hda->regs->statests - (void *)hda->regs,
497 hda_reg16_read(&hda->regs->statests));
498 /**
499 * Clear STATESTS bits so they don't generate an interrupt later
500 * when we enable interrupts.
501 */
502 hda_reg16_write(&hda->regs->statests, 0x7f);
503
504 ddf_msg(LVL_NOTE, "after clearing reg 0x%zx STATESTS = 0x%x",
505 (void *)&hda->regs->statests - (void *)hda->regs,
506 hda_reg16_read(&hda->regs->statests));
507
508 gctl = hda_reg32_read(&hda->regs->gctl);
509 if ((gctl & BIT_V(uint32_t, gctl_crst)) != 0) {
510 ddf_msg(LVL_NOTE, "Controller not in reset. Resetting.");
511 hda_reg32_write(&hda->regs->gctl, gctl & ~BIT_V(uint32_t, gctl_crst));
512 }
513
514 ddf_msg(LVL_NOTE, "Taking controller out of reset.");
515 hda_reg32_write(&hda->regs->gctl, gctl | BIT_V(uint32_t, gctl_crst));
516
517 /* Wait for CRST to read as 1 */
518 cnt = ctrl_init_wait_max;
519 while (cnt > 0) {
520 gctl = hda_reg32_read(&hda->regs->gctl);
521 if ((gctl & BIT_V(uint32_t, gctl_crst)) != 0) {
522 ddf_msg(LVL_NOTE, "gctl=0x%x", gctl);
523 break;
524 }
525
526 ddf_msg(LVL_NOTE, "Waiting for controller to initialize.");
527 async_usleep(100*1000);
528 --cnt;
529 }
530
531 if (cnt == 0) {
532 ddf_msg(LVL_ERROR, "Timed out waiting for controller to come up.");
533 goto error;
534 }
535
536 ddf_msg(LVL_NOTE, "Controller is out of reset.");
537
538 ddf_msg(LVL_NOTE, "Read GCAP");
539 uint16_t gcap = hda_reg16_read(&hda->regs->gcap);
540 ctl->ok64bit = (gcap & BIT_V(uint16_t, gcap_64ok)) != 0;
541 ctl->oss = BIT_RANGE_EXTRACT(uint16_t, gcap_oss_h, gcap_oss_l, gcap);
542 ctl->iss = BIT_RANGE_EXTRACT(uint16_t, gcap_iss_h, gcap_iss_l, gcap);
543 ctl->bss = BIT_RANGE_EXTRACT(uint16_t, gcap_bss_h, gcap_bss_l, gcap);
544 ddf_msg(LVL_NOTE, "GCAP: 0x%x (64OK=%d)", gcap, ctl->ok64bit);
545
546 /* Give codecs enough time to enumerate themselves */
547 async_usleep(codec_enum_wait_us);
548
549 ddf_msg(LVL_NOTE, "STATESTS = 0x%x",
550 hda_reg16_read(&hda->regs->statests));
551
552 /* Enable interrupts */
553 intctl = hda_reg32_read(&hda->regs->intctl);
554 ddf_msg(LVL_NOTE, "intctl (0x%x) := 0x%x",
555 (unsigned)((void *)&hda->regs->intctl - (void *)hda->regs),
556 intctl | BIT_V(uint32_t, intctl_gie) | BIT_V(uint32_t, intctl_cie));
557 hda_reg32_write(&hda->regs->intctl, intctl |
558 BIT_V(uint32_t, intctl_gie) | BIT_V(uint32_t, intctl_cie) |
559 0x3fffffff);
560
561 rc = hda_corb_init(hda);
562 if (rc != EOK)
563 goto error;
564
565 rc = hda_rirb_init(hda);
566 if (rc != EOK)
567 goto error;
568
569 ddf_msg(LVL_NOTE, "call hda_codec_init()");
570 hda->ctl->codec = hda_codec_init(hda, 0);
571 if (hda->ctl->codec == NULL) {
572 ddf_msg(LVL_NOTE, "hda_codec_init() failed");
573 goto error;
574 }
575
576 async_usleep(5*1000*1000);
577 ddf_msg(LVL_NOTE, "intsts=0x%x", hda_reg32_read(&hda->regs->intsts));
578 ddf_msg(LVL_NOTE, "sdesc[%d].sts=0x%x",
579 hda->ctl->iss, hda_reg8_read(&hda->regs->sdesc[hda->ctl->iss].sts));
580
581 return ctl;
582error:
583 free(ctl);
584 hda->ctl = NULL;
585 return NULL;
586}
587
588int hda_cmd(hda_t *hda, uint32_t verb, uint32_t *resp)
589{
590 int rc;
591 hda_rirb_entry_t rentry;
592
593 rc = hda_corb_write(hda, &verb, 1);
594 if (rc != EOK)
595 return rc;
596
597 if (resp != NULL) {
598 rc = hda_solrb_read(hda, &rentry, 1);
599 if (rc != EOK)
600 return rc;
601
602 /* XXX Verify that response came from the correct codec */
603 *resp = rentry.resp;
604 }
605
606 return EOK;
607}
608
609void hda_ctl_fini(hda_ctl_t *ctl)
610{
611 ddf_msg(LVL_NOTE, "hda_ctl_fini()");
612 free(ctl);
613}
614
615void hda_ctl_interrupt(hda_ctl_t *ctl)
616{
617 hda_rirb_entry_t resp;
618 int rc;
619
620 while (true) {
621 rc = hda_rirb_read(ctl->hda, &resp);
622 if (rc != EOK) {
623// ddf_msg(LVL_NOTE, "nothing in rirb");
624 break;
625 }
626
627 ddf_msg(LVL_NOTE, "writing to solrb");
628 fibril_mutex_lock(&ctl->solrb_lock);
629 ctl->solrb_wp = (ctl->solrb_wp + 1) % softrb_entries;
630 ctl->solrb[ctl->solrb_wp] = resp;
631 fibril_mutex_unlock(&ctl->solrb_lock);
632 fibril_condvar_broadcast(&ctl->solrb_cv);
633 }
634}
635
636/** @}
637 */
Note: See TracBrowser for help on using the repository browser.