2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2016 Alex Teaca <iateaca@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
34 #include <pthread_np.h>
43 #define INTEL_VENDORID 0x8086
45 #define HDA_CODEC_SUBSYSTEM_ID ((INTEL_VENDORID << 16) | 0x01)
46 #define HDA_CODEC_ROOT_NID 0x00
47 #define HDA_CODEC_FG_NID 0x01
48 #define HDA_CODEC_AUDIO_OUTPUT_NID 0x02
49 #define HDA_CODEC_PIN_OUTPUT_NID 0x03
50 #define HDA_CODEC_AUDIO_INPUT_NID 0x04
51 #define HDA_CODEC_PIN_INPUT_NID 0x05
53 #define HDA_CODEC_STREAMS_COUNT 0x02
54 #define HDA_CODEC_STREAM_OUTPUT 0x00
55 #define HDA_CODEC_STREAM_INPUT 0x01
57 #define HDA_CODEC_PARAMS_COUNT 0x14
58 #define HDA_CODEC_CONN_LIST_COUNT 0x01
59 #define HDA_CODEC_RESPONSE_EX_UNSOL 0x10
60 #define HDA_CODEC_RESPONSE_EX_SOL 0x00
61 #define HDA_CODEC_AMP_NUMSTEPS 0x4a
63 #define HDA_CODEC_SUPP_STREAM_FORMATS_PCM \
64 (1 << HDA_PARAM_SUPP_STREAM_FORMATS_PCM_SHIFT)
66 #define HDA_CODEC_FMT_BASE_MASK (0x01 << 14)
68 #define HDA_CODEC_FMT_MULT_MASK (0x07 << 11)
69 #define HDA_CODEC_FMT_MULT_2 (0x01 << 11)
70 #define HDA_CODEC_FMT_MULT_3 (0x02 << 11)
71 #define HDA_CODEC_FMT_MULT_4 (0x03 << 11)
73 #define HDA_CODEC_FMT_DIV_MASK 0x07
74 #define HDA_CODEC_FMT_DIV_SHIFT 8
76 #define HDA_CODEC_FMT_BITS_MASK (0x07 << 4)
77 #define HDA_CODEC_FMT_BITS_8 (0x00 << 4)
78 #define HDA_CODEC_FMT_BITS_16 (0x01 << 4)
79 #define HDA_CODEC_FMT_BITS_24 (0x03 << 4)
80 #define HDA_CODEC_FMT_BITS_32 (0x04 << 4)
82 #define HDA_CODEC_FMT_CHAN_MASK (0x0f << 0)
84 #define HDA_CODEC_AUDIO_WCAP_OUTPUT \
85 (0x00 << HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
86 #define HDA_CODEC_AUDIO_WCAP_INPUT \
87 (0x01 << HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
88 #define HDA_CODEC_AUDIO_WCAP_PIN \
89 (0x04 << HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
90 #define HDA_CODEC_AUDIO_WCAP_CONN_LIST \
91 (1 << HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_SHIFT)
92 #define HDA_CODEC_AUDIO_WCAP_FORMAT_OVR \
93 (1 << HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR_SHIFT)
94 #define HDA_CODEC_AUDIO_WCAP_AMP_OVR \
95 (1 << HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR_SHIFT)
96 #define HDA_CODEC_AUDIO_WCAP_OUT_AMP \
97 (1 << HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP_SHIFT)
98 #define HDA_CODEC_AUDIO_WCAP_IN_AMP \
99 (1 << HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP_SHIFT)
100 #define HDA_CODEC_AUDIO_WCAP_STEREO \
101 (1 << HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_SHIFT)
103 #define HDA_CODEC_PIN_CAP_OUTPUT \
104 (1 << HDA_PARAM_PIN_CAP_OUTPUT_CAP_SHIFT)
105 #define HDA_CODEC_PIN_CAP_INPUT \
106 (1 << HDA_PARAM_PIN_CAP_INPUT_CAP_SHIFT)
107 #define HDA_CODEC_PIN_CAP_PRESENCE_DETECT \
108 (1 << HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP_SHIFT)
110 #define HDA_CODEC_OUTPUT_AMP_CAP_MUTE_CAP \
111 (1 << HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP_SHIFT)
112 #define HDA_CODEC_OUTPUT_AMP_CAP_STEPSIZE \
113 (0x03 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT)
114 #define HDA_CODEC_OUTPUT_AMP_CAP_NUMSTEPS \
115 (HDA_CODEC_AMP_NUMSTEPS << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT)
116 #define HDA_CODEC_OUTPUT_AMP_CAP_OFFSET \
117 (HDA_CODEC_AMP_NUMSTEPS << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT)
119 #define HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE 0x80
120 #define HDA_CODEC_SET_AMP_GAIN_MUTE_GAIN_MASK 0x7f
122 #define HDA_CODEC_PIN_SENSE_PRESENCE_PLUGGED (1 << 31)
123 #define HDA_CODEC_PIN_WIDGET_CTRL_OUT_ENABLE \
124 (1 << HDA_CMD_GET_PIN_WIDGET_CTRL_OUT_ENABLE_SHIFT)
125 #define HDA_CODEC_PIN_WIDGET_CTRL_IN_ENABLE \
126 (1 << HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE_SHIFT)
128 #define HDA_CONFIG_DEFAULTCONF_COLOR_BLACK \
129 (0x01 << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT)
130 #define HDA_CONFIG_DEFAULTCONF_COLOR_RED \
131 (0x05 << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT)
133 #define HDA_CODEC_BUF_SIZE HDA_FIFO_SIZE
135 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
139 * HDA Audio Context data structures
142 typedef void (*transfer_func_t
)(void *arg
);
143 typedef int (*setup_func_t
)(void *arg
);
145 struct hda_audio_ctxt
{
153 setup_func_t do_setup
;
154 transfer_func_t do_transfer
;
158 * HDA Audio Context module function declarations
161 static void *hda_audio_ctxt_thr(void *arg
);
162 static int hda_audio_ctxt_init(struct hda_audio_ctxt
*actx
, const char *tname
,
163 transfer_func_t do_transfer
, setup_func_t do_setup
, void *priv
);
164 static int hda_audio_ctxt_start(struct hda_audio_ctxt
*actx
);
165 static int hda_audio_ctxt_stop(struct hda_audio_ctxt
*actx
);
168 * HDA Codec data structures
171 struct hda_codec_softc
;
173 typedef uint32_t (*verb_func_t
)(struct hda_codec_softc
*sc
, uint16_t verb
,
176 struct hda_codec_stream
{
177 uint8_t buf
[HDA_CODEC_BUF_SIZE
];
188 struct hda_audio_ctxt actx
;
191 struct hda_codec_softc
{
193 uint32_t subsystem_id
;
194 const uint32_t (*get_parameters
)[HDA_CODEC_PARAMS_COUNT
];
195 const uint8_t (*conn_list
)[HDA_CODEC_CONN_LIST_COUNT
];
196 const uint32_t *conf_default
;
197 const uint8_t *pin_ctrl_default
;
198 const verb_func_t
*verb_handlers
;
200 struct hda_codec_inst
*hci
;
201 struct hda_codec_stream streams
[HDA_CODEC_STREAMS_COUNT
];
205 * HDA Codec module function declarations
207 static int hda_codec_init(struct hda_codec_inst
*hci
, const char *play
,
209 static int hda_codec_reset(struct hda_codec_inst
*hci
);
210 static int hda_codec_command(struct hda_codec_inst
*hci
, uint32_t cmd_data
);
211 static int hda_codec_notify(struct hda_codec_inst
*hci
, uint8_t run
,
212 uint8_t stream
, uint8_t dir
);
214 static int hda_codec_parse_format(uint16_t fmt
, struct audio_params
*params
);
216 static uint32_t hda_codec_audio_output_nid(struct hda_codec_softc
*sc
,
217 uint16_t verb
, uint16_t payload
);
218 static void hda_codec_audio_output_do_transfer(void *arg
);
219 static int hda_codec_audio_output_do_setup(void *arg
);
220 static uint32_t hda_codec_audio_input_nid(struct hda_codec_softc
*sc
,
221 uint16_t verb
, uint16_t payload
);
222 static void hda_codec_audio_input_do_transfer(void *arg
);
223 static int hda_codec_audio_input_do_setup(void *arg
);
225 static uint32_t hda_codec_audio_inout_nid(struct hda_codec_stream
*st
,
226 uint16_t verb
, uint16_t payload
);
229 * HDA Codec global data
232 #define HDA_CODEC_ROOT_DESC \
233 [HDA_CODEC_ROOT_NID] = { \
234 [HDA_PARAM_VENDOR_ID] = INTEL_VENDORID, \
235 [HDA_PARAM_REVISION_ID] = 0xffff, \
236 /* 1 Subnode, StartNid = 1 */ \
237 [HDA_PARAM_SUB_NODE_COUNT] = 0x00010001, \
240 #define HDA_CODEC_FG_COMMON_DESC \
241 [HDA_PARAM_FCT_GRP_TYPE] = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO,\
242 /* B8 - B32, 8.0 - 192.0kHz */ \
243 [HDA_PARAM_SUPP_PCM_SIZE_RATE] = (0x1f << 16) | 0x7ff, \
244 [HDA_PARAM_SUPP_STREAM_FORMATS] = HDA_CODEC_SUPP_STREAM_FORMATS_PCM,\
245 [HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
246 [HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
247 [HDA_PARAM_GPIO_COUNT] = 0x00, \
249 #define HDA_CODEC_FG_OUTPUT_DESC \
250 [HDA_CODEC_FG_NID] = { \
251 /* 2 Subnodes, StartNid = 2 */ \
252 [HDA_PARAM_SUB_NODE_COUNT] = 0x00020002, \
253 HDA_CODEC_FG_COMMON_DESC \
256 #define HDA_CODEC_FG_INPUT_DESC \
257 [HDA_CODEC_FG_NID] = { \
258 /* 2 Subnodes, StartNid = 4 */ \
259 [HDA_PARAM_SUB_NODE_COUNT] = 0x00040002, \
260 HDA_CODEC_FG_COMMON_DESC \
263 #define HDA_CODEC_FG_DUPLEX_DESC \
264 [HDA_CODEC_FG_NID] = { \
265 /* 4 Subnodes, StartNid = 2 */ \
266 [HDA_PARAM_SUB_NODE_COUNT] = 0x00020004, \
267 HDA_CODEC_FG_COMMON_DESC \
270 #define HDA_CODEC_OUTPUT_DESC \
271 [HDA_CODEC_AUDIO_OUTPUT_NID] = { \
272 [HDA_PARAM_AUDIO_WIDGET_CAP] = \
273 HDA_CODEC_AUDIO_WCAP_OUTPUT | \
274 HDA_CODEC_AUDIO_WCAP_FORMAT_OVR | \
275 HDA_CODEC_AUDIO_WCAP_AMP_OVR | \
276 HDA_CODEC_AUDIO_WCAP_OUT_AMP | \
277 HDA_CODEC_AUDIO_WCAP_STEREO, \
278 /* B16, 16.0 - 192.0kHz */ \
279 [HDA_PARAM_SUPP_PCM_SIZE_RATE] = (0x02 << 16) | 0x7fc, \
280 [HDA_PARAM_SUPP_STREAM_FORMATS] = \
281 HDA_CODEC_SUPP_STREAM_FORMATS_PCM, \
282 [HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
283 [HDA_PARAM_CONN_LIST_LENGTH] = 0x00, \
284 [HDA_PARAM_OUTPUT_AMP_CAP] = \
285 HDA_CODEC_OUTPUT_AMP_CAP_MUTE_CAP | \
286 HDA_CODEC_OUTPUT_AMP_CAP_STEPSIZE | \
287 HDA_CODEC_OUTPUT_AMP_CAP_NUMSTEPS | \
288 HDA_CODEC_OUTPUT_AMP_CAP_OFFSET, \
290 [HDA_CODEC_PIN_OUTPUT_NID] = { \
291 [HDA_PARAM_AUDIO_WIDGET_CAP] = \
292 HDA_CODEC_AUDIO_WCAP_PIN | \
293 HDA_CODEC_AUDIO_WCAP_CONN_LIST | \
294 HDA_CODEC_AUDIO_WCAP_STEREO, \
295 [HDA_PARAM_PIN_CAP] = HDA_CODEC_PIN_CAP_OUTPUT | \
296 HDA_CODEC_PIN_CAP_PRESENCE_DETECT,\
297 [HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
298 [HDA_PARAM_CONN_LIST_LENGTH] = 0x01, \
299 [HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
302 #define HDA_CODEC_INPUT_DESC \
303 [HDA_CODEC_AUDIO_INPUT_NID] = { \
304 [HDA_PARAM_AUDIO_WIDGET_CAP] = \
305 HDA_CODEC_AUDIO_WCAP_INPUT | \
306 HDA_CODEC_AUDIO_WCAP_CONN_LIST | \
307 HDA_CODEC_AUDIO_WCAP_FORMAT_OVR | \
308 HDA_CODEC_AUDIO_WCAP_AMP_OVR | \
309 HDA_CODEC_AUDIO_WCAP_IN_AMP | \
310 HDA_CODEC_AUDIO_WCAP_STEREO, \
311 /* B16, 16.0 - 192.0kHz */ \
312 [HDA_PARAM_SUPP_PCM_SIZE_RATE] = (0x02 << 16) | 0x7fc, \
313 [HDA_PARAM_SUPP_STREAM_FORMATS] = \
314 HDA_CODEC_SUPP_STREAM_FORMATS_PCM, \
315 [HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
316 [HDA_PARAM_CONN_LIST_LENGTH] = 0x01, \
317 [HDA_PARAM_INPUT_AMP_CAP] = \
318 HDA_CODEC_OUTPUT_AMP_CAP_MUTE_CAP | \
319 HDA_CODEC_OUTPUT_AMP_CAP_STEPSIZE | \
320 HDA_CODEC_OUTPUT_AMP_CAP_NUMSTEPS | \
321 HDA_CODEC_OUTPUT_AMP_CAP_OFFSET, \
323 [HDA_CODEC_PIN_INPUT_NID] = { \
324 [HDA_PARAM_AUDIO_WIDGET_CAP] = \
325 HDA_CODEC_AUDIO_WCAP_PIN | \
326 HDA_CODEC_AUDIO_WCAP_STEREO, \
327 [HDA_PARAM_PIN_CAP] = HDA_CODEC_PIN_CAP_INPUT | \
328 HDA_CODEC_PIN_CAP_PRESENCE_DETECT, \
329 [HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
330 [HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
333 static const uint32_t
334 hda_codec_output_parameters
[][HDA_CODEC_PARAMS_COUNT
] = {
336 HDA_CODEC_FG_OUTPUT_DESC
337 HDA_CODEC_OUTPUT_DESC
340 static const uint32_t
341 hda_codec_input_parameters
[][HDA_CODEC_PARAMS_COUNT
] = {
343 HDA_CODEC_FG_INPUT_DESC
347 static const uint32_t
348 hda_codec_duplex_parameters
[][HDA_CODEC_PARAMS_COUNT
] = {
350 HDA_CODEC_FG_DUPLEX_DESC
351 HDA_CODEC_OUTPUT_DESC
355 #define HDA_CODEC_NODES_COUNT (ARRAY_SIZE(hda_codec_duplex_parameters))
358 hda_codec_conn_list
[HDA_CODEC_NODES_COUNT
][HDA_CODEC_CONN_LIST_COUNT
] = {
359 [HDA_CODEC_PIN_OUTPUT_NID
] = {HDA_CODEC_AUDIO_OUTPUT_NID
},
360 [HDA_CODEC_AUDIO_INPUT_NID
] = {HDA_CODEC_PIN_INPUT_NID
},
363 static const uint32_t
364 hda_codec_conf_default
[HDA_CODEC_NODES_COUNT
] = {
365 [HDA_CODEC_PIN_OUTPUT_NID
] = \
366 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK
|
367 HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT
|
368 HDA_CONFIG_DEFAULTCONF_COLOR_BLACK
|
369 (0x01 << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT
),
370 [HDA_CODEC_PIN_INPUT_NID
] = HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK
|
371 HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN
|
372 HDA_CONFIG_DEFAULTCONF_COLOR_RED
|
373 (0x02 << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT
),
377 hda_codec_pin_ctrl_default
[HDA_CODEC_NODES_COUNT
] = {
378 [HDA_CODEC_PIN_OUTPUT_NID
] = HDA_CODEC_PIN_WIDGET_CTRL_OUT_ENABLE
,
379 [HDA_CODEC_PIN_INPUT_NID
] = HDA_CODEC_PIN_WIDGET_CTRL_IN_ENABLE
,
383 verb_func_t hda_codec_verb_handlers
[HDA_CODEC_NODES_COUNT
] = {
384 [HDA_CODEC_AUDIO_OUTPUT_NID
] = hda_codec_audio_output_nid
,
385 [HDA_CODEC_AUDIO_INPUT_NID
] = hda_codec_audio_input_nid
,
389 * HDA Codec module function definitions
393 hda_codec_init(struct hda_codec_inst
*hci
, const char *play
,
396 struct hda_codec_softc
*sc
= NULL
;
397 struct hda_codec_stream
*st
= NULL
;
403 sc
= calloc(1, sizeof(*sc
));
408 sc
->get_parameters
= hda_codec_duplex_parameters
;
411 sc
->get_parameters
= hda_codec_output_parameters
;
413 sc
->get_parameters
= hda_codec_input_parameters
;
415 sc
->subsystem_id
= HDA_CODEC_SUBSYSTEM_ID
;
416 sc
->no_nodes
= HDA_CODEC_NODES_COUNT
;
417 sc
->conn_list
= hda_codec_conn_list
;
418 sc
->conf_default
= hda_codec_conf_default
;
419 sc
->pin_ctrl_default
= hda_codec_pin_ctrl_default
;
420 sc
->verb_handlers
= hda_codec_verb_handlers
;
421 DPRINTF("HDA Codec nodes: %d", sc
->no_nodes
);
424 * Initialize the Audio Output stream
427 st
= &sc
->streams
[HDA_CODEC_STREAM_OUTPUT
];
429 err
= hda_audio_ctxt_init(&st
->actx
, "hda-audio-output",
430 hda_codec_audio_output_do_transfer
,
431 hda_codec_audio_output_do_setup
, sc
);
434 st
->aud
= audio_init(play
, 1);
436 DPRINTF("Fail to init the output audio player");
442 * Initialize the Audio Input stream
445 st
= &sc
->streams
[HDA_CODEC_STREAM_INPUT
];
447 err
= hda_audio_ctxt_init(&st
->actx
, "hda-audio-input",
448 hda_codec_audio_input_do_transfer
,
449 hda_codec_audio_input_do_setup
, sc
);
452 st
->aud
= audio_init(rec
, 0);
454 DPRINTF("Fail to init the input audio player");
466 hda_codec_reset(struct hda_codec_inst
*hci
)
468 const struct hda_ops
*hops
= NULL
;
469 struct hda_codec_softc
*sc
= NULL
;
470 struct hda_codec_stream
*st
= NULL
;
478 sc
= (struct hda_codec_softc
*)hci
->priv
;
481 for (i
= 0; i
< HDA_CODEC_STREAMS_COUNT
; i
++) {
482 st
= &sc
->streams
[i
];
483 st
->left_gain
= HDA_CODEC_AMP_NUMSTEPS
;
484 st
->right_gain
= HDA_CODEC_AMP_NUMSTEPS
;
485 st
->left_mute
= HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE
;
486 st
->right_mute
= HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE
;
489 DPRINTF("cad: 0x%x", hci
->cad
);
492 DPRINTF("The controller ops does not implement \
493 the signal function");
497 return (hops
->signal(hci
));
501 hda_codec_command(struct hda_codec_inst
*hci
, uint32_t cmd_data
)
503 const struct hda_ops
*hops
= NULL
;
504 struct hda_codec_softc
*sc
= NULL
;
505 uint8_t cad
= 0, nid
= 0;
506 uint16_t verb
= 0, payload
= 0;
510 cad
= (cmd_data
>> HDA_CMD_CAD_SHIFT
) & 0x0f;
512 nid
= (cmd_data
>> HDA_CMD_NID_SHIFT
) & 0xff;
514 if ((cmd_data
& 0x70000) == 0x70000) {
516 verb
= (cmd_data
>> HDA_CMD_VERB_12BIT_SHIFT
) & 0x0fff;
518 payload
= cmd_data
& 0xff;
521 verb
= (cmd_data
>> HDA_CMD_VERB_4BIT_SHIFT
) & 0x0f;
523 payload
= cmd_data
& 0xffff;
526 assert(cad
== hci
->cad
);
532 sc
= (struct hda_codec_softc
*)hci
->priv
;
535 assert(nid
< sc
->no_nodes
);
537 if (!hops
->response
) {
538 DPRINTF("The controller ops does not implement \
539 the response function");
544 case HDA_CMD_VERB_GET_PARAMETER
:
545 res
= sc
->get_parameters
[nid
][payload
];
547 case HDA_CMD_VERB_GET_CONN_LIST_ENTRY
:
548 res
= sc
->conn_list
[nid
][0];
550 case HDA_CMD_VERB_GET_PIN_WIDGET_CTRL
:
551 res
= sc
->pin_ctrl_default
[nid
];
553 case HDA_CMD_VERB_GET_PIN_SENSE
:
554 res
= HDA_CODEC_PIN_SENSE_PRESENCE_PLUGGED
;
556 case HDA_CMD_VERB_GET_CONFIGURATION_DEFAULT
:
557 res
= sc
->conf_default
[nid
];
559 case HDA_CMD_VERB_GET_SUBSYSTEM_ID
:
560 res
= sc
->subsystem_id
;
563 assert(sc
->verb_handlers
);
564 if (sc
->verb_handlers
[nid
])
565 res
= sc
->verb_handlers
[nid
](sc
, verb
, payload
);
567 DPRINTF("Unknown VERB: 0x%x", verb
);
571 DPRINTF("cad: 0x%x nid: 0x%x verb: 0x%x payload: 0x%x response: 0x%x",
572 cad
, nid
, verb
, payload
, res
);
574 return (hops
->response(hci
, res
, HDA_CODEC_RESPONSE_EX_SOL
));
578 hda_codec_notify(struct hda_codec_inst
*hci
, uint8_t run
,
579 uint8_t stream
, uint8_t dir
)
581 struct hda_codec_softc
*sc
= NULL
;
582 struct hda_codec_stream
*st
= NULL
;
583 struct hda_audio_ctxt
*actx
= NULL
;
590 sc
= (struct hda_codec_softc
*)hci
->priv
;
593 i
= dir
? HDA_CODEC_STREAM_OUTPUT
: HDA_CODEC_STREAM_INPUT
;
594 st
= &sc
->streams
[i
];
596 DPRINTF("run: %d, stream: 0x%x, st->stream: 0x%x dir: %d",
597 run
, stream
, st
->stream
, dir
);
599 if (stream
!= st
->stream
) {
600 DPRINTF("Stream not found");
607 err
= hda_audio_ctxt_start(actx
);
609 err
= hda_audio_ctxt_stop(actx
);
615 hda_codec_parse_format(uint16_t fmt
, struct audio_params
*params
)
621 /* Compute the Sample Rate */
622 params
->rate
= (fmt
& HDA_CODEC_FMT_BASE_MASK
) ? 44100 : 48000;
624 switch (fmt
& HDA_CODEC_FMT_MULT_MASK
) {
625 case HDA_CODEC_FMT_MULT_2
:
628 case HDA_CODEC_FMT_MULT_3
:
631 case HDA_CODEC_FMT_MULT_4
:
636 div
= (fmt
>> HDA_CODEC_FMT_DIV_SHIFT
) & HDA_CODEC_FMT_DIV_MASK
;
637 params
->rate
/= (div
+ 1);
639 /* Compute the Bits per Sample */
640 switch (fmt
& HDA_CODEC_FMT_BITS_MASK
) {
641 case HDA_CODEC_FMT_BITS_8
:
642 params
->format
= AFMT_U8
;
644 case HDA_CODEC_FMT_BITS_16
:
645 params
->format
= AFMT_S16_LE
;
647 case HDA_CODEC_FMT_BITS_24
:
648 params
->format
= AFMT_S24_LE
;
650 case HDA_CODEC_FMT_BITS_32
:
651 params
->format
= AFMT_S32_LE
;
654 DPRINTF("Unknown format bits: 0x%x",
655 fmt
& HDA_CODEC_FMT_BITS_MASK
);
659 /* Compute the Number of Channels */
660 params
->channels
= (fmt
& HDA_CODEC_FMT_CHAN_MASK
) + 1;
666 hda_codec_audio_output_nid(struct hda_codec_softc
*sc
, uint16_t verb
,
669 struct hda_codec_stream
*st
= &sc
->streams
[HDA_CODEC_STREAM_OUTPUT
];
672 res
= hda_codec_audio_inout_nid(st
, verb
, payload
);
678 hda_codec_audio_output_do_transfer(void *arg
)
680 const struct hda_ops
*hops
= NULL
;
681 struct hda_codec_softc
*sc
= (struct hda_codec_softc
*)arg
;
682 struct hda_codec_inst
*hci
= NULL
;
683 struct hda_codec_stream
*st
= NULL
;
684 struct audio
*aud
= NULL
;
693 st
= &sc
->streams
[HDA_CODEC_STREAM_OUTPUT
];
696 err
= hops
->transfer(hci
, st
->stream
, 1, st
->buf
, sizeof(st
->buf
));
700 err
= audio_playback(aud
, st
->buf
, sizeof(st
->buf
));
705 hda_codec_audio_output_do_setup(void *arg
)
707 struct hda_codec_softc
*sc
= (struct hda_codec_softc
*)arg
;
708 struct hda_codec_stream
*st
= NULL
;
709 struct audio
*aud
= NULL
;
710 struct audio_params params
;
713 st
= &sc
->streams
[HDA_CODEC_STREAM_OUTPUT
];
716 err
= hda_codec_parse_format(st
->fmt
, ¶ms
);
720 DPRINTF("rate: %d, channels: %d, format: 0x%x",
721 params
.rate
, params
.channels
, params
.format
);
723 return (audio_set_params(aud
, ¶ms
));
727 hda_codec_audio_input_nid(struct hda_codec_softc
*sc
, uint16_t verb
,
730 struct hda_codec_stream
*st
= &sc
->streams
[HDA_CODEC_STREAM_INPUT
];
733 res
= hda_codec_audio_inout_nid(st
, verb
, payload
);
739 hda_codec_audio_input_do_transfer(void *arg
)
741 const struct hda_ops
*hops
= NULL
;
742 struct hda_codec_softc
*sc
= (struct hda_codec_softc
*)arg
;
743 struct hda_codec_inst
*hci
= NULL
;
744 struct hda_codec_stream
*st
= NULL
;
745 struct audio
*aud
= NULL
;
754 st
= &sc
->streams
[HDA_CODEC_STREAM_INPUT
];
757 err
= audio_record(aud
, st
->buf
, sizeof(st
->buf
));
760 hops
->transfer(hci
, st
->stream
, 0, st
->buf
, sizeof(st
->buf
));
764 hda_codec_audio_input_do_setup(void *arg
)
766 struct hda_codec_softc
*sc
= (struct hda_codec_softc
*)arg
;
767 struct hda_codec_stream
*st
= NULL
;
768 struct audio
*aud
= NULL
;
769 struct audio_params params
;
772 st
= &sc
->streams
[HDA_CODEC_STREAM_INPUT
];
775 err
= hda_codec_parse_format(st
->fmt
, ¶ms
);
779 DPRINTF("rate: %d, channels: %d, format: 0x%x",
780 params
.rate
, params
.channels
, params
.format
);
782 return (audio_set_params(aud
, ¶ms
));
786 hda_codec_audio_inout_nid(struct hda_codec_stream
*st
, uint16_t verb
,
793 DPRINTF("%s verb: 0x%x, payload, 0x%x", st
->actx
.name
, verb
, payload
);
796 case HDA_CMD_VERB_GET_CONV_FMT
:
799 case HDA_CMD_VERB_SET_CONV_FMT
:
802 case HDA_CMD_VERB_GET_AMP_GAIN_MUTE
:
803 if (payload
& HDA_CMD_GET_AMP_GAIN_MUTE_LEFT
) {
804 res
= st
->left_gain
| st
->left_mute
;
805 DPRINTF("GET_AMP_GAIN_MUTE_LEFT: 0x%x", res
);
807 res
= st
->right_gain
| st
->right_mute
;
808 DPRINTF("GET_AMP_GAIN_MUTE_RIGHT: 0x%x", res
);
811 case HDA_CMD_VERB_SET_AMP_GAIN_MUTE
:
812 mute
= payload
& HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE
;
813 gain
= payload
& HDA_CODEC_SET_AMP_GAIN_MUTE_GAIN_MASK
;
815 if (payload
& HDA_CMD_SET_AMP_GAIN_MUTE_LEFT
) {
816 st
->left_mute
= mute
;
817 st
->left_gain
= gain
;
818 DPRINTF("SET_AMP_GAIN_MUTE_LEFT: \
819 mute: 0x%x gain: 0x%x", mute
, gain
);
822 if (payload
& HDA_CMD_SET_AMP_GAIN_MUTE_RIGHT
) {
823 st
->right_mute
= mute
;
824 st
->right_gain
= gain
;
825 DPRINTF("SET_AMP_GAIN_MUTE_RIGHT: \
826 mute: 0x%x gain: 0x%x", mute
, gain
);
829 case HDA_CMD_VERB_GET_CONV_STREAM_CHAN
:
830 res
= (st
->stream
<< 4) | st
->channel
;
832 case HDA_CMD_VERB_SET_CONV_STREAM_CHAN
:
833 st
->channel
= payload
& 0x0f;
834 st
->stream
= (payload
>> 4) & 0x0f;
835 DPRINTF("st->channel: 0x%x st->stream: 0x%x",
836 st
->channel
, st
->stream
);
838 hda_audio_ctxt_stop(&st
->actx
);
841 DPRINTF("Unknown VERB: 0x%x", verb
);
848 static const struct hda_codec_class hda_codec
= {
850 .init
= hda_codec_init
,
851 .reset
= hda_codec_reset
,
852 .command
= hda_codec_command
,
853 .notify
= hda_codec_notify
,
855 HDA_EMUL_SET(hda_codec
);
858 * HDA Audio Context module function definitions
862 hda_audio_ctxt_thr(void *arg
)
864 struct hda_audio_ctxt
*actx
= arg
;
866 DPRINTF("Start Thread: %s", actx
->name
);
868 pthread_mutex_lock(&actx
->mtx
);
871 pthread_cond_wait(&actx
->cond
, &actx
->mtx
);
873 actx
->do_transfer(actx
->priv
);
875 pthread_mutex_unlock(&actx
->mtx
);
882 hda_audio_ctxt_init(struct hda_audio_ctxt
*actx
, const char *tname
,
883 transfer_func_t do_transfer
, setup_func_t do_setup
, void *priv
)
893 memset(actx
, 0, sizeof(*actx
));
896 actx
->do_transfer
= do_transfer
;
897 actx
->do_setup
= do_setup
;
899 if (strlen(tname
) < sizeof(actx
->name
))
900 memcpy(actx
->name
, tname
, strlen(tname
) + 1);
902 strcpy(actx
->name
, "unknown");
904 err
= pthread_mutex_init(&actx
->mtx
, NULL
);
907 err
= pthread_cond_init(&actx
->cond
, NULL
);
910 err
= pthread_create(&actx
->tid
, NULL
, hda_audio_ctxt_thr
, actx
);
913 pthread_set_name_np(actx
->tid
, tname
);
921 hda_audio_ctxt_start(struct hda_audio_ctxt
*actx
)
926 assert(actx
->started
);
928 /* The stream is supposed to be stopped */
932 pthread_mutex_lock(&actx
->mtx
);
933 err
= (* actx
->do_setup
)(actx
->priv
);
936 pthread_cond_signal(&actx
->cond
);
938 pthread_mutex_unlock(&actx
->mtx
);
944 hda_audio_ctxt_stop(struct hda_audio_ctxt
*actx
)