source: mainline/uspace/drv/audio/hdaudio/codec.c

Last change on this file was 0d59ea7e, checked in by Jiri Svoboda <jiri@…>, 3 years ago

Multiple HD Audio converters cannot pull from a single stream

We select one arbitrary output converter for out PCM output, similar to what
we do for input.

We filter the 'other' VirtualBox output converters based on rates/formats
being zero.

  • Property mode set to 100644
File size: 16.7 KB
Line 
1/*
2 * Copyright (c) 2022 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 codec
33 */
34
35#include <async.h>
36#include <bitops.h>
37#include <ddf/log.h>
38#include <errno.h>
39#include <str_error.h>
40#include <stdlib.h>
41
42#include "codec.h"
43#include "hdactl.h"
44#include "spec/codec.h"
45#include "spec/fmt.h"
46#include "stream.h"
47
48static errno_t hda_ccmd(hda_codec_t *codec, int node, uint32_t vid, uint32_t payload,
49 uint32_t *resp)
50{
51 uint32_t verb;
52 uint32_t myresp;
53
54 if (resp == NULL)
55 resp = &myresp;
56
57 if ((vid & 0x700) != 0) {
58 verb = (codec->address << 28) |
59 ((node & 0x1ff) << 20) |
60 ((vid & 0xfff) << 8) |
61 (payload & 0xff);
62 } else {
63 verb = (codec->address << 28) |
64 ((node & 0x1ff) << 20) |
65 ((vid & 0xf) << 16) |
66 (payload & 0xffff);
67 }
68 errno_t rc = hda_cmd(codec->hda, verb, resp);
69
70#if 0
71 if (resp != NULL) {
72 ddf_msg(LVL_DEBUG, "verb 0x%" PRIx32 " -> 0x%" PRIx32, verb,
73 *resp);
74 } else {
75 ddf_msg(LVL_DEBUG, "verb 0x%" PRIx32, verb);
76 }
77#endif
78 return rc;
79}
80
81static errno_t hda_get_parameter(hda_codec_t *codec, int node, hda_param_id_t param,
82 uint32_t *resp)
83{
84 return hda_ccmd(codec, node, hda_param_get, param, resp);
85}
86
87static errno_t hda_get_subnc(hda_codec_t *codec, int node, int *startnode,
88 int *nodecount)
89{
90 errno_t rc;
91 uint32_t resp;
92
93 rc = hda_get_parameter(codec, node, hda_sub_nc, &resp);
94 if (rc != EOK)
95 return rc;
96
97 *startnode = BIT_RANGE_EXTRACT(uint32_t, subnc_startnode_h,
98 subnc_startnode_l, resp);
99 *nodecount = BIT_RANGE_EXTRACT(uint32_t, subnc_nodecount_h,
100 subnc_nodecount_l, resp);
101
102 return EOK;
103}
104
105/** Get Function Group Type */
106static errno_t hda_get_fgrp_type(hda_codec_t *codec, int node, bool *unsol,
107 hda_fgrp_type_t *type)
108{
109 errno_t rc;
110 uint32_t resp;
111
112 rc = hda_get_parameter(codec, node, hda_fgrp_type, &resp);
113 if (rc != EOK)
114 return rc;
115
116 *unsol = (resp & BIT_V(uint32_t, fgrpt_unsol)) != 0;
117 *type = BIT_RANGE_EXTRACT(uint32_t, fgrpt_type_h, fgrpt_type_l, resp);
118
119 return EOK;
120}
121
122static errno_t hda_get_clist_len(hda_codec_t *codec, int node, bool *longform,
123 int *items)
124{
125 errno_t rc;
126 uint32_t resp;
127
128 rc = hda_get_parameter(codec, node, hda_clist_len, &resp);
129 if (rc != EOK)
130 return rc;
131
132 ddf_msg(LVL_DEBUG2, "hda_get_clist_len: resp=0x%x", resp);
133 *longform = resp & BIT_V(uint32_t, cll_longform);
134 *items = resp & BIT_RANGE_EXTRACT(uint32_t, cll_len_h, cll_len_l, resp);
135 return EOK;
136}
137
138static errno_t hda_get_clist_entry(hda_codec_t *codec, int node, int n, uint32_t *resp)
139{
140 return hda_ccmd(codec, node, hda_clist_entry_get, n, resp);
141}
142
143static errno_t hda_get_eapd_btl_enable(hda_codec_t *codec, int node, uint32_t *resp)
144{
145 return hda_ccmd(codec, node, hda_eapd_btl_enable_get, 0, resp);
146}
147
148static errno_t hda_set_eapd_btl_enable(hda_codec_t *codec, int node, uint8_t payload)
149{
150 return hda_ccmd(codec, node, hda_eapd_btl_enable_set, payload, NULL);
151}
152
153/** Get Suppported PCM Size, Rates */
154static errno_t hda_get_supp_rates(hda_codec_t *codec, int node, uint32_t *rates)
155{
156 return hda_get_parameter(codec, node, hda_supp_rates, rates);
157}
158
159/** Get Suppported Stream Formats */
160static errno_t hda_get_supp_formats(hda_codec_t *codec, int node, uint32_t *fmts)
161{
162 return hda_get_parameter(codec, node, hda_supp_formats, fmts);
163}
164
165static errno_t hda_set_converter_fmt(hda_codec_t *codec, int node, uint16_t fmt)
166{
167 return hda_ccmd(codec, node, hda_converter_fmt_set, fmt, NULL);
168}
169
170static errno_t hda_set_converter_ctl(hda_codec_t *codec, int node, uint8_t stream,
171 uint8_t channel)
172{
173 uint32_t ctl;
174
175 ctl = (stream << cctl_stream_l) | (channel << cctl_channel_l);
176 return hda_ccmd(codec, node, hda_converter_ctl_set, ctl, NULL);
177}
178
179static errno_t hda_set_pin_ctl(hda_codec_t *codec, int node, uint8_t pctl)
180{
181 return hda_ccmd(codec, node, hda_pin_ctl_set, pctl, NULL);
182}
183
184static errno_t hda_get_pin_ctl(hda_codec_t *codec, int node, uint8_t *pctl)
185{
186 errno_t rc;
187 uint32_t resp;
188
189 rc = hda_ccmd(codec, node, hda_pin_ctl_get, 0, &resp);
190 if (rc != EOK)
191 return rc;
192
193 *pctl = resp;
194 return EOK;
195}
196
197/** Get Audio Widget Capabilities */
198static errno_t hda_get_aw_caps(hda_codec_t *codec, int node,
199 hda_awidget_type_t *type, uint32_t *caps)
200{
201 errno_t rc;
202 uint32_t resp;
203
204 rc = hda_get_parameter(codec, node, hda_aw_caps, &resp);
205 if (rc != EOK)
206 return rc;
207
208 *type = BIT_RANGE_EXTRACT(uint32_t, awc_type_h, awc_type_l, resp);
209 *caps = resp;
210
211 return EOK;
212}
213
214/** Get Pin Capabilities */
215static errno_t hda_get_pin_caps(hda_codec_t *codec, int node, uint32_t *caps)
216{
217 return hda_get_parameter(codec, node, hda_pin_caps, caps);
218}
219
220/** Get Power State */
221static errno_t hda_get_power_state(hda_codec_t *codec, int node, uint32_t *pstate)
222{
223 return hda_ccmd(codec, node, hda_power_state_get, 0, pstate);
224}
225
226/** Get Configuration Default */
227static errno_t hda_get_cfg_def(hda_codec_t *codec, int node, uint32_t *cfgdef)
228{
229 return hda_ccmd(codec, node, hda_cfg_def_get, 0, cfgdef);
230}
231
232static errno_t hda_get_conn_sel(hda_codec_t *codec, int node, uint32_t *conn)
233{
234 return hda_ccmd(codec, node, hda_conn_sel_get, 0, conn);
235}
236
237/** Get Amplifier Gain / Mute */
238static errno_t hda_get_amp_gain_mute(hda_codec_t *codec, int node, uint16_t payload,
239 uint32_t *resp)
240{
241 ddf_msg(LVL_DEBUG2, "hda_get_amp_gain_mute(codec, %d, %x)",
242 node, payload);
243 errno_t rc = hda_ccmd(codec, node, hda_amp_gain_mute_get, payload, resp);
244 ddf_msg(LVL_DEBUG2, "hda_get_amp_gain_mute(codec, %d, %x, resp=%x)",
245 node, payload, *resp);
246 return rc;
247}
248
249/** Get GP I/O Count */
250static errno_t hda_get_gpio_cnt(hda_codec_t *codec, int node, uint32_t *resp)
251{
252 return hda_get_parameter(codec, node, hda_gpio_cnt, resp);
253}
254
255static errno_t hda_set_amp_gain_mute(hda_codec_t *codec, int node, uint16_t payload)
256{
257 ddf_msg(LVL_DEBUG2, "hda_set_amp_gain_mute(codec, %d, %x)",
258 node, payload);
259 return hda_ccmd(codec, node, hda_amp_gain_mute_set, payload, NULL);
260}
261
262static errno_t hda_set_out_amp_max(hda_codec_t *codec, uint8_t aw)
263{
264 uint32_t ampcaps;
265 uint32_t gmleft, gmright;
266 uint32_t offset;
267 errno_t rc;
268
269 rc = hda_get_parameter(codec, aw,
270 hda_out_amp_caps, &ampcaps);
271 if (rc != EOK)
272 goto error;
273
274 offset = ampcaps & 0x7f;
275 ddf_msg(LVL_DEBUG, "out amp caps 0x%x (offset=0x%x)",
276 ampcaps, offset);
277
278 rc = hda_set_amp_gain_mute(codec, aw, 0xb000 + offset);
279 if (rc != EOK)
280 goto error;
281
282 rc = hda_get_amp_gain_mute(codec, aw, 0x8000, &gmleft);
283 if (rc != EOK)
284 goto error;
285
286 rc = hda_get_amp_gain_mute(codec, aw, 0xa000, &gmright);
287 if (rc != EOK)
288 goto error;
289
290 ddf_msg(LVL_DEBUG, "gain/mute: L:0x%x R:0x%x", gmleft, gmright);
291
292 return EOK;
293error:
294 return rc;
295}
296
297static errno_t hda_set_in_amp_max(hda_codec_t *codec, uint8_t aw)
298{
299 uint32_t ampcaps;
300 uint32_t gmleft, gmright;
301 uint32_t offset;
302 int i;
303 errno_t rc;
304
305 rc = hda_get_parameter(codec, aw,
306 hda_out_amp_caps, &ampcaps);
307 if (rc != EOK)
308 goto error;
309
310 offset = ampcaps & 0x7f;
311 ddf_msg(LVL_DEBUG, "in amp caps 0x%x (offset=0x%x)", ampcaps, offset);
312
313 for (i = 0; i < 15; i++) {
314 rc = hda_set_amp_gain_mute(codec, aw, 0x7000 + (i << 8) + offset);
315 if (rc != EOK)
316 goto error;
317
318 rc = hda_get_amp_gain_mute(codec, aw, 0x0000 + i, &gmleft);
319 if (rc != EOK)
320 goto error;
321
322 rc = hda_get_amp_gain_mute(codec, aw, 0x2000 + i, &gmright);
323 if (rc != EOK)
324 goto error;
325
326 ddf_msg(LVL_DEBUG, "in:%d gain/mute: L:0x%x R:0x%x",
327 i, gmleft, gmright);
328 }
329
330 return EOK;
331error:
332 return rc;
333}
334
335static errno_t hda_clist_dump(hda_codec_t *codec, uint8_t aw)
336{
337 errno_t rc;
338 bool longform;
339 int len;
340 uint32_t resp;
341 uint32_t mask;
342 uint32_t cidx;
343 int shift;
344 int epresp;
345 int i, j;
346
347 ddf_msg(LVL_DEBUG, "Connections for widget %d:", aw);
348
349 rc = hda_get_clist_len(codec, aw, &longform, &len);
350 if (rc != EOK) {
351 ddf_msg(LVL_ERROR, "Failed getting connection list length.");
352 return rc;
353 }
354
355 if (len > 1) {
356 rc = hda_get_conn_sel(codec, aw, &cidx);
357 if (rc != EOK) {
358 ddf_msg(LVL_ERROR, "Failed getting connection select");
359 return rc;
360 }
361 } else {
362 cidx = 0;
363 }
364
365 ddf_msg(LVL_DEBUG2, "longform:%d len:%d", longform, len);
366
367 if (longform) {
368 epresp = 2;
369 mask = 0xffff;
370 shift = 16;
371 } else {
372 epresp = 4;
373 mask = 0xff;
374 shift = 8;
375 }
376
377 i = 0;
378 while (i < len) {
379 rc = hda_get_clist_entry(codec, aw, i, &resp);
380 if (rc != EOK) {
381 ddf_msg(LVL_ERROR, "Failed getting connection list entry.");
382 return rc;
383 }
384
385 for (j = 0; j < epresp && i < len; j++) {
386 ddf_msg(LVL_DEBUG, "<- %d%s", resp & mask,
387 (int)cidx == i ? " *** current *** " : "");
388 resp = resp >> shift;
389 ++i;
390 }
391
392 }
393
394 return rc;
395}
396
397static errno_t hda_pin_init(hda_codec_t *codec, uint8_t aw)
398{
399 errno_t rc;
400 uint32_t cfgdef;
401 uint32_t pcaps;
402 uint32_t eapd;
403 uint8_t pctl;
404
405 rc = hda_get_cfg_def(codec, aw, &cfgdef);
406 if (rc != EOK)
407 goto error;
408 ddf_msg(LVL_DEBUG, "aw %d: PIN cdfgef=0x%x",
409 aw, cfgdef);
410
411 rc = hda_get_pin_caps(codec, aw, &pcaps);
412 if (rc != EOK)
413 goto error;
414 ddf_msg(LVL_DEBUG, "aw %d : PIN caps=0x%x",
415 aw, pcaps);
416
417 if ((pcaps & BIT_V(uint32_t, pwc_eapd)) != 0) {
418 rc = hda_get_eapd_btl_enable(codec, aw, &eapd);
419 if (rc != EOK)
420 goto error;
421
422 ddf_msg(LVL_DEBUG, "PIN %d had EAPD value=0x%x", aw, eapd);
423
424 rc = hda_set_eapd_btl_enable(codec, aw, eapd | 2);
425 if (rc != EOK)
426 goto error;
427
428 rc = hda_get_eapd_btl_enable(codec, aw, &eapd);
429 if (rc != EOK)
430 goto error;
431
432 ddf_msg(LVL_DEBUG, "PIN %d now has EAPD value=0x%x", aw, eapd);
433 }
434
435 pctl = 0;
436 if ((pcaps & BIT_V(uint32_t, pwc_output)) != 0) {
437 ddf_msg(LVL_DEBUG, "PIN %d will enable output", aw);
438 pctl = pctl | BIT_V(uint8_t, pctl_out_enable);
439 }
440
441 if ((pcaps & BIT_V(uint32_t, pwc_input)) != 0) {
442 ddf_msg(LVL_DEBUG, "PIN %d will enable input", aw);
443 pctl = pctl | BIT_V(uint8_t, pctl_in_enable);
444 }
445
446 if ((pcaps & BIT_V(uint32_t, pwc_hpd)) != 0) {
447 ddf_msg(LVL_DEBUG, "PIN %d will enable headphone drive", aw);
448 pctl = pctl | BIT_V(uint8_t, pctl_hpd_enable);
449 }
450
451#if 0
452 if ((pcaps & BIT_V(uint32_t, pwc_input)) != 0) {
453 ddf_msg(LVL_DEBUG, "PIN %d will enable input");
454 pctl = pctl | BIT_V(uint8_t, pctl_input_enable);
455 }
456#endif
457 ddf_msg(LVL_DEBUG, "Setting PIN %d ctl to 0x%x", aw, pctl);
458 rc = hda_set_pin_ctl(codec, aw, pctl);
459 if (rc != EOK)
460 goto error;
461
462 pctl = 0;
463 rc = hda_get_pin_ctl(codec, aw, &pctl);
464 if (rc != EOK)
465 goto error;
466
467 ddf_msg(LVL_DEBUG, "PIN %d ctl reads as 0x%x", aw, pctl);
468
469 return EOK;
470error:
471 return rc;
472}
473
474/** Init power-control in wiget capable of doing so. */
475static errno_t hda_power_ctl_init(hda_codec_t *codec, uint8_t aw)
476{
477 errno_t rc;
478 uint32_t pwrstate;
479
480 ddf_msg(LVL_DEBUG, "aw %d is power control-capable", aw);
481
482 rc = hda_get_power_state(codec, aw, &pwrstate);
483 if (rc != EOK)
484 goto error;
485 ddf_msg(LVL_DEBUG, "aw %d: power state = 0x%x", aw, pwrstate);
486
487 return EOK;
488error:
489 return rc;
490}
491
492hda_codec_t *hda_codec_init(hda_t *hda, uint8_t address)
493{
494 hda_codec_t *codec;
495 errno_t rc;
496 int sfg, nfg;
497 int saw, naw;
498 int fg, aw;
499 bool unsol;
500 hda_fgrp_type_t grptype;
501 hda_awidget_type_t awtype;
502 uint32_t awcaps;
503 uint32_t rates;
504 uint32_t formats;
505 uint32_t gpio;
506
507 codec = calloc(1, sizeof(hda_codec_t));
508 if (codec == NULL)
509 return NULL;
510
511 codec->hda = hda;
512 codec->address = address;
513 codec->in_aw = -1;
514 codec->out_aw = -1;
515
516 rc = hda_get_subnc(codec, 0, &sfg, &nfg);
517 if (rc != EOK)
518 goto error;
519
520 ddf_msg(LVL_DEBUG, "hda_get_subnc -> %s", str_error_name(rc));
521 ddf_msg(LVL_DEBUG, "sfg=%d nfg=%d", sfg, nfg);
522
523 for (fg = sfg; fg < sfg + nfg; fg++) {
524 ddf_msg(LVL_DEBUG, "Enumerate FG %d", fg);
525
526 rc = hda_get_fgrp_type(codec, fg, &unsol, &grptype);
527 if (rc != EOK)
528 goto error;
529
530 ddf_msg(LVL_DEBUG, "hda_get_fgrp_type -> %s", str_error_name(rc));
531 ddf_msg(LVL_DEBUG, "unsol: %d, grptype: %d", unsol, grptype);
532
533 rc = hda_get_gpio_cnt(codec, fg, &gpio);
534 if (rc != EOK)
535 goto error;
536
537 ddf_msg(LVL_DEBUG, "GPIO: wake=%d unsol=%d gpis=%d gpos=%d gpios=%d",
538 (gpio & BIT_V(uint32_t, 31)) != 0,
539 (gpio & BIT_V(uint32_t, 30)) != 0,
540 BIT_RANGE_EXTRACT(uint32_t, 23, 16, gpio),
541 BIT_RANGE_EXTRACT(uint32_t, 15, 8, gpio),
542 BIT_RANGE_EXTRACT(uint32_t, 7, 0, gpio));
543
544 rc = hda_power_ctl_init(codec, fg);
545 if (rc != EOK)
546 goto error;
547
548 rc = hda_get_subnc(codec, fg, &saw, &naw);
549 if (rc != EOK)
550 goto error;
551
552 ddf_msg(LVL_DEBUG, "hda_get_subnc -> %s", str_error_name(rc));
553 ddf_msg(LVL_DEBUG, "saw=%d baw=%d", saw, naw);
554
555 for (aw = saw; aw < saw + naw; aw++) {
556 rc = hda_get_aw_caps(codec, aw, &awtype, &awcaps);
557 if (rc != EOK)
558 goto error;
559 ddf_msg(LVL_DEBUG, "aw %d: type=0x%x caps=0x%x",
560 aw, awtype, awcaps);
561
562 if ((awcaps & BIT_V(uint32_t, awc_power_cntrl)) != 0) {
563 rc = hda_power_ctl_init(codec, aw);
564 if (rc != EOK)
565 goto error;
566 }
567
568 switch (awtype) {
569 case awt_audio_input:
570 case awt_audio_mixer:
571 case awt_audio_selector:
572 case awt_pin_complex:
573 case awt_power_widget:
574 rc = hda_clist_dump(codec, aw);
575 if (rc != EOK)
576 goto error;
577 break;
578 default:
579 break;
580 }
581
582 if (awtype == awt_pin_complex) {
583 rc = hda_pin_init(codec, aw);
584 if (rc != EOK)
585 goto error;
586 } else if (awtype == awt_audio_output) {
587 rc = hda_get_supp_rates(codec, aw, &rates);
588 if (rc != EOK)
589 goto error;
590
591 rc = hda_get_supp_formats(codec, aw, &formats);
592 if (rc != EOK)
593 goto error;
594
595 if (rates != 0 && formats != 0 &&
596 codec->out_aw < 0) {
597 ddf_msg(LVL_DEBUG, "Selected output "
598 "widget %d\n", aw);
599 codec->out_aw = aw;
600 } else {
601 ddf_msg(LVL_DEBUG, "Ignoring output "
602 "widget %d\n", aw);
603 }
604
605 ddf_msg(LVL_NOTE, "Output widget %d: rates=0x%x formats=0x%x",
606 aw, rates, formats);
607 codec->out_aw_rates = rates;
608 codec->out_aw_formats = formats;
609 } else if (awtype == awt_audio_input) {
610 if (codec->in_aw < 0) {
611 ddf_msg(LVL_DEBUG, "Selected input "
612 "widget %d\n", aw);
613 codec->in_aw = aw;
614 } else {
615 ddf_msg(LVL_DEBUG, "Ignoring input "
616 "widget %d\n", aw);
617 }
618
619 rc = hda_get_supp_rates(codec, aw, &rates);
620 if (rc != EOK)
621 goto error;
622
623 rc = hda_get_supp_formats(codec, aw, &formats);
624 if (rc != EOK)
625 goto error;
626
627 ddf_msg(LVL_DEBUG, "Input widget %d: rates=0x%x formats=0x%x",
628 aw, rates, formats);
629 codec->in_aw_rates = rates;
630 codec->in_aw_formats = formats;
631 }
632
633 if ((awcaps & BIT_V(uint32_t, awc_out_amp_present)) != 0)
634 hda_set_out_amp_max(codec, aw);
635
636 if ((awcaps & BIT_V(uint32_t, awc_in_amp_present)) != 0)
637 hda_set_in_amp_max(codec, aw);
638 }
639 }
640
641 hda_ctl_dump_info(hda->ctl);
642
643 ddf_msg(LVL_DEBUG, "Codec OK");
644 return codec;
645error:
646 free(codec);
647 return NULL;
648}
649
650void hda_codec_fini(hda_codec_t *codec)
651{
652 ddf_msg(LVL_DEBUG, "hda_codec_fini()");
653 free(codec);
654}
655
656errno_t hda_out_converter_setup(hda_codec_t *codec, hda_stream_t *stream)
657{
658 errno_t rc;
659
660 /* Configure converter */
661 ddf_msg(LVL_DEBUG, "Configure output converter format / %d",
662 codec->out_aw);
663 rc = hda_set_converter_fmt(codec, codec->out_aw, stream->fmt);
664 if (rc != EOK)
665 goto error;
666
667 ddf_msg(LVL_DEBUG, "Configure output converter stream, channel");
668 rc = hda_set_converter_ctl(codec, codec->out_aw, stream->sid, 0);
669 if (rc != EOK)
670 goto error;
671
672 return EOK;
673error:
674 return rc;
675}
676
677errno_t hda_in_converter_setup(hda_codec_t *codec, hda_stream_t *stream)
678{
679 errno_t rc;
680
681 /* Configure converter */
682
683 ddf_msg(LVL_DEBUG, "Configure input converter format");
684 rc = hda_set_converter_fmt(codec, codec->in_aw, stream->fmt);
685 if (rc != EOK)
686 goto error;
687
688 ddf_msg(LVL_DEBUG, "Configure input converter stream, channel");
689 rc = hda_set_converter_ctl(codec, codec->in_aw, stream->sid, 0);
690 if (rc != EOK)
691 goto error;
692
693 return EOK;
694error:
695 return rc;
696}
697
698/** @}
699 */
Note: See TracBrowser for help on using the repository browser.