source: mainline/uspace/drv/audio/hdaudio/codec.c@ 17d34a8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 17d34a8 was 5a6cc679, checked in by Jenda <jenda.jzqk73@…>, 8 years ago

Merge commit '50f19b7ee8e94570b5c63896736c4eb49cfa18db' into forwardport

Not all ints are converted to errno_t in xhci tree yet, however it compiles and works :)

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