Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.sbin/bhyve/hda_codec.c
103554 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2016 Alex Teaca <[email protected]>
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
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.
15
*
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
26
* SUCH DAMAGE.
27
*
28
*/
29
30
#include <sys/cdefs.h>
31
#include <pthread.h>
32
#include <pthread_np.h>
33
#include <unistd.h>
34
35
#include "pci_hda.h"
36
#include "audio.h"
37
38
/*
39
* HDA Codec defines
40
*/
41
#define INTEL_VENDORID 0x8086
42
43
#define HDA_CODEC_SUBSYSTEM_ID ((INTEL_VENDORID << 16) | 0x01)
44
#define HDA_CODEC_ROOT_NID 0x00
45
#define HDA_CODEC_FG_NID 0x01
46
#define HDA_CODEC_AUDIO_OUTPUT_NID 0x02
47
#define HDA_CODEC_PIN_OUTPUT_NID 0x03
48
#define HDA_CODEC_AUDIO_INPUT_NID 0x04
49
#define HDA_CODEC_PIN_INPUT_NID 0x05
50
51
#define HDA_CODEC_STREAMS_COUNT 0x02
52
#define HDA_CODEC_STREAM_OUTPUT 0x00
53
#define HDA_CODEC_STREAM_INPUT 0x01
54
55
#define HDA_CODEC_PARAMS_COUNT 0x14
56
#define HDA_CODEC_CONN_LIST_COUNT 0x01
57
#define HDA_CODEC_RESPONSE_EX_UNSOL 0x10
58
#define HDA_CODEC_RESPONSE_EX_SOL 0x00
59
#define HDA_CODEC_AMP_NUMSTEPS 0x4a
60
61
#define HDA_CODEC_SUPP_STREAM_FORMATS_PCM \
62
(1 << HDA_PARAM_SUPP_STREAM_FORMATS_PCM_SHIFT)
63
64
#define HDA_CODEC_FMT_BASE_MASK (0x01 << 14)
65
66
#define HDA_CODEC_FMT_MULT_MASK (0x07 << 11)
67
#define HDA_CODEC_FMT_MULT_2 (0x01 << 11)
68
#define HDA_CODEC_FMT_MULT_3 (0x02 << 11)
69
#define HDA_CODEC_FMT_MULT_4 (0x03 << 11)
70
71
#define HDA_CODEC_FMT_DIV_MASK 0x07
72
#define HDA_CODEC_FMT_DIV_SHIFT 8
73
74
#define HDA_CODEC_FMT_BITS_MASK (0x07 << 4)
75
#define HDA_CODEC_FMT_BITS_8 (0x00 << 4)
76
#define HDA_CODEC_FMT_BITS_16 (0x01 << 4)
77
#define HDA_CODEC_FMT_BITS_24 (0x03 << 4)
78
#define HDA_CODEC_FMT_BITS_32 (0x04 << 4)
79
80
#define HDA_CODEC_FMT_CHAN_MASK (0x0f << 0)
81
82
#define HDA_CODEC_AUDIO_WCAP_OUTPUT \
83
(0x00 << HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
84
#define HDA_CODEC_AUDIO_WCAP_INPUT \
85
(0x01 << HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
86
#define HDA_CODEC_AUDIO_WCAP_PIN \
87
(0x04 << HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
88
#define HDA_CODEC_AUDIO_WCAP_CONN_LIST \
89
(1 << HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_SHIFT)
90
#define HDA_CODEC_AUDIO_WCAP_FORMAT_OVR \
91
(1 << HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR_SHIFT)
92
#define HDA_CODEC_AUDIO_WCAP_AMP_OVR \
93
(1 << HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR_SHIFT)
94
#define HDA_CODEC_AUDIO_WCAP_OUT_AMP \
95
(1 << HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP_SHIFT)
96
#define HDA_CODEC_AUDIO_WCAP_IN_AMP \
97
(1 << HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP_SHIFT)
98
#define HDA_CODEC_AUDIO_WCAP_STEREO \
99
(1 << HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_SHIFT)
100
101
#define HDA_CODEC_PIN_CAP_OUTPUT \
102
(1 << HDA_PARAM_PIN_CAP_OUTPUT_CAP_SHIFT)
103
#define HDA_CODEC_PIN_CAP_INPUT \
104
(1 << HDA_PARAM_PIN_CAP_INPUT_CAP_SHIFT)
105
#define HDA_CODEC_PIN_CAP_PRESENCE_DETECT \
106
(1 << HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP_SHIFT)
107
108
#define HDA_CODEC_OUTPUT_AMP_CAP_MUTE_CAP \
109
(1 << HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP_SHIFT)
110
#define HDA_CODEC_OUTPUT_AMP_CAP_STEPSIZE \
111
(0x03 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT)
112
#define HDA_CODEC_OUTPUT_AMP_CAP_NUMSTEPS \
113
(HDA_CODEC_AMP_NUMSTEPS << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT)
114
#define HDA_CODEC_OUTPUT_AMP_CAP_OFFSET \
115
(HDA_CODEC_AMP_NUMSTEPS << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT)
116
117
#define HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE 0x80
118
#define HDA_CODEC_SET_AMP_GAIN_MUTE_GAIN_MASK 0x7f
119
120
#define HDA_CODEC_PIN_SENSE_PRESENCE_PLUGGED (1 << 31)
121
#define HDA_CODEC_PIN_WIDGET_CTRL_OUT_ENABLE \
122
(1 << HDA_CMD_GET_PIN_WIDGET_CTRL_OUT_ENABLE_SHIFT)
123
#define HDA_CODEC_PIN_WIDGET_CTRL_IN_ENABLE \
124
(1 << HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE_SHIFT)
125
126
#define HDA_CONFIG_DEFAULTCONF_COLOR_BLACK \
127
(0x01 << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT)
128
#define HDA_CONFIG_DEFAULTCONF_COLOR_RED \
129
(0x05 << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT)
130
131
#define HDA_CODEC_BUF_SIZE HDA_FIFO_SIZE
132
133
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
134
135
136
/*
137
* HDA Audio Context data structures
138
*/
139
140
typedef void (*transfer_func_t)(void *arg);
141
typedef int (*setup_func_t)(void *arg);
142
143
struct hda_audio_ctxt {
144
char name[64];
145
uint8_t run;
146
uint8_t started;
147
void *priv;
148
pthread_t tid;
149
pthread_mutex_t mtx;
150
pthread_cond_t cond;
151
setup_func_t do_setup;
152
transfer_func_t do_transfer;
153
};
154
155
/*
156
* HDA Audio Context module function declarations
157
*/
158
159
static void *hda_audio_ctxt_thr(void *arg);
160
static int hda_audio_ctxt_init(struct hda_audio_ctxt *actx, const char *tname,
161
transfer_func_t do_transfer, setup_func_t do_setup, void *priv);
162
static int hda_audio_ctxt_start(struct hda_audio_ctxt *actx);
163
static int hda_audio_ctxt_stop(struct hda_audio_ctxt *actx);
164
165
/*
166
* HDA Codec data structures
167
*/
168
169
struct hda_codec_softc;
170
171
typedef uint32_t (*verb_func_t)(struct hda_codec_softc *sc, uint16_t verb,
172
uint16_t payload);
173
174
struct hda_codec_stream {
175
uint8_t buf[HDA_CODEC_BUF_SIZE];
176
uint8_t channel;
177
uint16_t fmt;
178
uint8_t stream;
179
180
uint8_t left_gain;
181
uint8_t right_gain;
182
uint8_t left_mute;
183
uint8_t right_mute;
184
185
struct audio *aud;
186
struct hda_audio_ctxt actx;
187
};
188
189
struct hda_codec_softc {
190
uint32_t no_nodes;
191
uint32_t subsystem_id;
192
const uint32_t (*get_parameters)[HDA_CODEC_PARAMS_COUNT];
193
const uint8_t (*conn_list)[HDA_CODEC_CONN_LIST_COUNT];
194
const uint32_t *conf_default;
195
const uint8_t *pin_ctrl_default;
196
const verb_func_t *verb_handlers;
197
198
struct hda_codec_inst *hci;
199
struct hda_codec_stream streams[HDA_CODEC_STREAMS_COUNT];
200
};
201
202
/*
203
* HDA Codec module function declarations
204
*/
205
static int hda_codec_init(struct hda_codec_inst *hci, const char *play,
206
const char *rec);
207
static int hda_codec_reset(struct hda_codec_inst *hci);
208
static int hda_codec_command(struct hda_codec_inst *hci, uint32_t cmd_data);
209
static int hda_codec_notify(struct hda_codec_inst *hci, uint8_t run,
210
uint8_t stream, uint8_t dir);
211
212
static int hda_codec_parse_format(uint16_t fmt, struct audio_params *params);
213
214
static uint32_t hda_codec_audio_output_nid(struct hda_codec_softc *sc,
215
uint16_t verb, uint16_t payload);
216
static void hda_codec_audio_output_do_transfer(void *arg);
217
static int hda_codec_audio_output_do_setup(void *arg);
218
static uint32_t hda_codec_audio_input_nid(struct hda_codec_softc *sc,
219
uint16_t verb, uint16_t payload);
220
static void hda_codec_audio_input_do_transfer(void *arg);
221
static int hda_codec_audio_input_do_setup(void *arg);
222
223
static uint32_t hda_codec_audio_inout_nid(struct hda_codec_stream *st,
224
uint16_t verb, uint16_t payload);
225
226
/*
227
* HDA Codec global data
228
*/
229
230
#define HDA_CODEC_ROOT_DESC \
231
[HDA_CODEC_ROOT_NID] = { \
232
[HDA_PARAM_VENDOR_ID] = INTEL_VENDORID, \
233
[HDA_PARAM_REVISION_ID] = 0xffff, \
234
/* 1 Subnode, StartNid = 1 */ \
235
[HDA_PARAM_SUB_NODE_COUNT] = 0x00010001, \
236
}, \
237
238
#define HDA_CODEC_FG_COMMON_DESC \
239
[HDA_PARAM_FCT_GRP_TYPE] = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO,\
240
/* B8 - B32, 8.0 - 192.0kHz */ \
241
[HDA_PARAM_SUPP_PCM_SIZE_RATE] = (0x1f << 16) | 0x7ff, \
242
[HDA_PARAM_SUPP_STREAM_FORMATS] = HDA_CODEC_SUPP_STREAM_FORMATS_PCM,\
243
[HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
244
[HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
245
[HDA_PARAM_GPIO_COUNT] = 0x00, \
246
247
#define HDA_CODEC_FG_OUTPUT_DESC \
248
[HDA_CODEC_FG_NID] = { \
249
/* 2 Subnodes, StartNid = 2 */ \
250
[HDA_PARAM_SUB_NODE_COUNT] = 0x00020002, \
251
HDA_CODEC_FG_COMMON_DESC \
252
}, \
253
254
#define HDA_CODEC_FG_INPUT_DESC \
255
[HDA_CODEC_FG_NID] = { \
256
/* 2 Subnodes, StartNid = 4 */ \
257
[HDA_PARAM_SUB_NODE_COUNT] = 0x00040002, \
258
HDA_CODEC_FG_COMMON_DESC \
259
}, \
260
261
#define HDA_CODEC_FG_DUPLEX_DESC \
262
[HDA_CODEC_FG_NID] = { \
263
/* 4 Subnodes, StartNid = 2 */ \
264
[HDA_PARAM_SUB_NODE_COUNT] = 0x00020004, \
265
HDA_CODEC_FG_COMMON_DESC \
266
}, \
267
268
#define HDA_CODEC_OUTPUT_DESC \
269
[HDA_CODEC_AUDIO_OUTPUT_NID] = { \
270
[HDA_PARAM_AUDIO_WIDGET_CAP] = \
271
HDA_CODEC_AUDIO_WCAP_OUTPUT | \
272
HDA_CODEC_AUDIO_WCAP_FORMAT_OVR | \
273
HDA_CODEC_AUDIO_WCAP_AMP_OVR | \
274
HDA_CODEC_AUDIO_WCAP_OUT_AMP | \
275
HDA_CODEC_AUDIO_WCAP_STEREO, \
276
/* B16, 16.0 - 192.0kHz */ \
277
[HDA_PARAM_SUPP_PCM_SIZE_RATE] = (0x02 << 16) | 0x7fc, \
278
[HDA_PARAM_SUPP_STREAM_FORMATS] = \
279
HDA_CODEC_SUPP_STREAM_FORMATS_PCM, \
280
[HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
281
[HDA_PARAM_CONN_LIST_LENGTH] = 0x00, \
282
[HDA_PARAM_OUTPUT_AMP_CAP] = \
283
HDA_CODEC_OUTPUT_AMP_CAP_MUTE_CAP | \
284
HDA_CODEC_OUTPUT_AMP_CAP_STEPSIZE | \
285
HDA_CODEC_OUTPUT_AMP_CAP_NUMSTEPS | \
286
HDA_CODEC_OUTPUT_AMP_CAP_OFFSET, \
287
}, \
288
[HDA_CODEC_PIN_OUTPUT_NID] = { \
289
[HDA_PARAM_AUDIO_WIDGET_CAP] = \
290
HDA_CODEC_AUDIO_WCAP_PIN | \
291
HDA_CODEC_AUDIO_WCAP_CONN_LIST | \
292
HDA_CODEC_AUDIO_WCAP_STEREO, \
293
[HDA_PARAM_PIN_CAP] = HDA_CODEC_PIN_CAP_OUTPUT | \
294
HDA_CODEC_PIN_CAP_PRESENCE_DETECT,\
295
[HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
296
[HDA_PARAM_CONN_LIST_LENGTH] = 0x01, \
297
[HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
298
}, \
299
300
#define HDA_CODEC_INPUT_DESC \
301
[HDA_CODEC_AUDIO_INPUT_NID] = { \
302
[HDA_PARAM_AUDIO_WIDGET_CAP] = \
303
HDA_CODEC_AUDIO_WCAP_INPUT | \
304
HDA_CODEC_AUDIO_WCAP_CONN_LIST | \
305
HDA_CODEC_AUDIO_WCAP_FORMAT_OVR | \
306
HDA_CODEC_AUDIO_WCAP_AMP_OVR | \
307
HDA_CODEC_AUDIO_WCAP_IN_AMP | \
308
HDA_CODEC_AUDIO_WCAP_STEREO, \
309
/* B16, 16.0 - 192.0kHz */ \
310
[HDA_PARAM_SUPP_PCM_SIZE_RATE] = (0x02 << 16) | 0x7fc, \
311
[HDA_PARAM_SUPP_STREAM_FORMATS] = \
312
HDA_CODEC_SUPP_STREAM_FORMATS_PCM, \
313
[HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
314
[HDA_PARAM_CONN_LIST_LENGTH] = 0x01, \
315
[HDA_PARAM_INPUT_AMP_CAP] = \
316
HDA_CODEC_OUTPUT_AMP_CAP_MUTE_CAP | \
317
HDA_CODEC_OUTPUT_AMP_CAP_STEPSIZE | \
318
HDA_CODEC_OUTPUT_AMP_CAP_NUMSTEPS | \
319
HDA_CODEC_OUTPUT_AMP_CAP_OFFSET, \
320
}, \
321
[HDA_CODEC_PIN_INPUT_NID] = { \
322
[HDA_PARAM_AUDIO_WIDGET_CAP] = \
323
HDA_CODEC_AUDIO_WCAP_PIN | \
324
HDA_CODEC_AUDIO_WCAP_STEREO, \
325
[HDA_PARAM_PIN_CAP] = HDA_CODEC_PIN_CAP_INPUT | \
326
HDA_CODEC_PIN_CAP_PRESENCE_DETECT, \
327
[HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
328
[HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
329
}, \
330
331
static const uint32_t
332
hda_codec_output_parameters[][HDA_CODEC_PARAMS_COUNT] = {
333
HDA_CODEC_ROOT_DESC
334
HDA_CODEC_FG_OUTPUT_DESC
335
HDA_CODEC_OUTPUT_DESC
336
};
337
338
static const uint32_t
339
hda_codec_input_parameters[][HDA_CODEC_PARAMS_COUNT] = {
340
HDA_CODEC_ROOT_DESC
341
HDA_CODEC_FG_INPUT_DESC
342
HDA_CODEC_INPUT_DESC
343
};
344
345
static const uint32_t
346
hda_codec_duplex_parameters[][HDA_CODEC_PARAMS_COUNT] = {
347
HDA_CODEC_ROOT_DESC
348
HDA_CODEC_FG_DUPLEX_DESC
349
HDA_CODEC_OUTPUT_DESC
350
HDA_CODEC_INPUT_DESC
351
};
352
353
#define HDA_CODEC_NODES_COUNT (ARRAY_SIZE(hda_codec_duplex_parameters))
354
355
static const uint8_t
356
hda_codec_conn_list[HDA_CODEC_NODES_COUNT][HDA_CODEC_CONN_LIST_COUNT] = {
357
[HDA_CODEC_PIN_OUTPUT_NID] = {HDA_CODEC_AUDIO_OUTPUT_NID},
358
[HDA_CODEC_AUDIO_INPUT_NID] = {HDA_CODEC_PIN_INPUT_NID},
359
};
360
361
static const uint32_t
362
hda_codec_conf_default[HDA_CODEC_NODES_COUNT] = {
363
[HDA_CODEC_PIN_OUTPUT_NID] = \
364
HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK |
365
HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT |
366
HDA_CONFIG_DEFAULTCONF_COLOR_BLACK |
367
(0x01 << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT),
368
[HDA_CODEC_PIN_INPUT_NID] = HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK |
369
HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN |
370
HDA_CONFIG_DEFAULTCONF_COLOR_RED |
371
(0x02 << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT),
372
};
373
374
static const uint8_t
375
hda_codec_pin_ctrl_default[HDA_CODEC_NODES_COUNT] = {
376
[HDA_CODEC_PIN_OUTPUT_NID] = HDA_CODEC_PIN_WIDGET_CTRL_OUT_ENABLE,
377
[HDA_CODEC_PIN_INPUT_NID] = HDA_CODEC_PIN_WIDGET_CTRL_IN_ENABLE,
378
};
379
380
static const
381
verb_func_t hda_codec_verb_handlers[HDA_CODEC_NODES_COUNT] = {
382
[HDA_CODEC_AUDIO_OUTPUT_NID] = hda_codec_audio_output_nid,
383
[HDA_CODEC_AUDIO_INPUT_NID] = hda_codec_audio_input_nid,
384
};
385
386
/*
387
* HDA Codec module function definitions
388
*/
389
390
static int
391
hda_codec_init(struct hda_codec_inst *hci, const char *play,
392
const char *rec)
393
{
394
struct hda_codec_softc *sc = NULL;
395
struct hda_codec_stream *st = NULL;
396
int err;
397
398
if (!(play || rec))
399
return (-1);
400
401
sc = calloc(1, sizeof(*sc));
402
if (!sc)
403
return (-1);
404
405
if (play && rec)
406
sc->get_parameters = hda_codec_duplex_parameters;
407
else {
408
if (play)
409
sc->get_parameters = hda_codec_output_parameters;
410
else
411
sc->get_parameters = hda_codec_input_parameters;
412
}
413
sc->subsystem_id = HDA_CODEC_SUBSYSTEM_ID;
414
sc->no_nodes = HDA_CODEC_NODES_COUNT;
415
sc->conn_list = hda_codec_conn_list;
416
sc->conf_default = hda_codec_conf_default;
417
sc->pin_ctrl_default = hda_codec_pin_ctrl_default;
418
sc->verb_handlers = hda_codec_verb_handlers;
419
DPRINTF("HDA Codec nodes: %d", sc->no_nodes);
420
421
/*
422
* Initialize the Audio Output stream
423
*/
424
if (play) {
425
st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
426
427
err = hda_audio_ctxt_init(&st->actx, "hda-audio-output",
428
hda_codec_audio_output_do_transfer,
429
hda_codec_audio_output_do_setup, sc);
430
assert(!err);
431
432
st->aud = audio_init(play, 1);
433
if (!st->aud) {
434
DPRINTF("Fail to init the output audio player");
435
return (-1);
436
}
437
}
438
439
/*
440
* Initialize the Audio Input stream
441
*/
442
if (rec) {
443
st = &sc->streams[HDA_CODEC_STREAM_INPUT];
444
445
err = hda_audio_ctxt_init(&st->actx, "hda-audio-input",
446
hda_codec_audio_input_do_transfer,
447
hda_codec_audio_input_do_setup, sc);
448
assert(!err);
449
450
st->aud = audio_init(rec, 0);
451
if (!st->aud) {
452
DPRINTF("Fail to init the input audio player");
453
return (-1);
454
}
455
}
456
457
sc->hci = hci;
458
hci->priv = sc;
459
460
return (0);
461
}
462
463
static int
464
hda_codec_reset(struct hda_codec_inst *hci)
465
{
466
const struct hda_ops *hops = NULL;
467
struct hda_codec_softc *sc = NULL;
468
struct hda_codec_stream *st = NULL;
469
int i;
470
471
assert(hci);
472
473
hops = hci->hops;
474
assert(hops);
475
476
sc = (struct hda_codec_softc *)hci->priv;
477
assert(sc);
478
479
for (i = 0; i < HDA_CODEC_STREAMS_COUNT; i++) {
480
st = &sc->streams[i];
481
st->left_gain = HDA_CODEC_AMP_NUMSTEPS;
482
st->right_gain = HDA_CODEC_AMP_NUMSTEPS;
483
st->left_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE;
484
st->right_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE;
485
}
486
487
DPRINTF("cad: 0x%x", hci->cad);
488
489
if (!hops->signal) {
490
DPRINTF("The controller ops does not implement \
491
the signal function");
492
return (-1);
493
}
494
495
return (hops->signal(hci));
496
}
497
498
static int
499
hda_codec_command(struct hda_codec_inst *hci, uint32_t cmd_data)
500
{
501
const struct hda_ops *hops = NULL;
502
struct hda_codec_softc *sc = NULL;
503
uint8_t cad = 0, nid = 0;
504
uint16_t verb = 0, payload = 0;
505
uint32_t res = 0;
506
507
/* 4 bits */
508
cad = (cmd_data >> HDA_CMD_CAD_SHIFT) & 0x0f;
509
/* 8 bits */
510
nid = (cmd_data >> HDA_CMD_NID_SHIFT) & 0xff;
511
512
if ((cmd_data & 0x70000) == 0x70000) {
513
/* 12 bits */
514
verb = (cmd_data >> HDA_CMD_VERB_12BIT_SHIFT) & 0x0fff;
515
/* 8 bits */
516
payload = cmd_data & 0xff;
517
} else {
518
/* 4 bits */
519
verb = (cmd_data >> HDA_CMD_VERB_4BIT_SHIFT) & 0x0f;
520
/* 16 bits */
521
payload = cmd_data & 0xffff;
522
}
523
524
assert(hci);
525
526
hops = hci->hops;
527
assert(hops);
528
529
sc = (struct hda_codec_softc *)hci->priv;
530
assert(sc);
531
532
if (cad != hci->cad || nid >= sc->no_nodes) {
533
DPRINTF("Invalid command data");
534
return (-1);
535
}
536
537
if (!hops->response) {
538
DPRINTF("The controller ops does not implement \
539
the response function");
540
return (-1);
541
}
542
543
switch (verb) {
544
case HDA_CMD_VERB_GET_PARAMETER:
545
if (payload < HDA_CODEC_PARAMS_COUNT)
546
res = sc->get_parameters[nid][payload];
547
break;
548
case HDA_CMD_VERB_GET_CONN_LIST_ENTRY:
549
res = sc->conn_list[nid][0];
550
break;
551
case HDA_CMD_VERB_GET_PIN_WIDGET_CTRL:
552
res = sc->pin_ctrl_default[nid];
553
break;
554
case HDA_CMD_VERB_GET_PIN_SENSE:
555
res = HDA_CODEC_PIN_SENSE_PRESENCE_PLUGGED;
556
break;
557
case HDA_CMD_VERB_GET_CONFIGURATION_DEFAULT:
558
res = sc->conf_default[nid];
559
break;
560
case HDA_CMD_VERB_GET_SUBSYSTEM_ID:
561
res = sc->subsystem_id;
562
break;
563
default:
564
assert(sc->verb_handlers);
565
if (sc->verb_handlers[nid])
566
res = sc->verb_handlers[nid](sc, verb, payload);
567
else
568
DPRINTF("Unknown VERB: 0x%x", verb);
569
break;
570
}
571
572
DPRINTF("cad: 0x%x nid: 0x%x verb: 0x%x payload: 0x%x response: 0x%x",
573
cad, nid, verb, payload, res);
574
575
return (hops->response(hci, res, HDA_CODEC_RESPONSE_EX_SOL));
576
}
577
578
static int
579
hda_codec_notify(struct hda_codec_inst *hci, uint8_t run,
580
uint8_t stream, uint8_t dir)
581
{
582
struct hda_codec_softc *sc = NULL;
583
struct hda_codec_stream *st = NULL;
584
struct hda_audio_ctxt *actx = NULL;
585
int i;
586
int err;
587
588
assert(hci);
589
assert(stream);
590
591
sc = (struct hda_codec_softc *)hci->priv;
592
assert(sc);
593
594
i = dir ? HDA_CODEC_STREAM_OUTPUT : HDA_CODEC_STREAM_INPUT;
595
st = &sc->streams[i];
596
597
DPRINTF("run: %d, stream: 0x%x, st->stream: 0x%x dir: %d",
598
run, stream, st->stream, dir);
599
600
if (stream != st->stream) {
601
DPRINTF("Stream not found");
602
return (0);
603
}
604
605
actx = &st->actx;
606
607
if (run)
608
err = hda_audio_ctxt_start(actx);
609
else
610
err = hda_audio_ctxt_stop(actx);
611
612
return (err);
613
}
614
615
static int
616
hda_codec_parse_format(uint16_t fmt, struct audio_params *params)
617
{
618
uint8_t div = 0;
619
620
assert(params);
621
622
/* Compute the Sample Rate */
623
params->rate = (fmt & HDA_CODEC_FMT_BASE_MASK) ? 44100 : 48000;
624
625
switch (fmt & HDA_CODEC_FMT_MULT_MASK) {
626
case HDA_CODEC_FMT_MULT_2:
627
params->rate *= 2;
628
break;
629
case HDA_CODEC_FMT_MULT_3:
630
params->rate *= 3;
631
break;
632
case HDA_CODEC_FMT_MULT_4:
633
params->rate *= 4;
634
break;
635
}
636
637
div = (fmt >> HDA_CODEC_FMT_DIV_SHIFT) & HDA_CODEC_FMT_DIV_MASK;
638
params->rate /= (div + 1);
639
640
/* Compute the Bits per Sample */
641
switch (fmt & HDA_CODEC_FMT_BITS_MASK) {
642
case HDA_CODEC_FMT_BITS_8:
643
params->format = AFMT_U8;
644
break;
645
case HDA_CODEC_FMT_BITS_16:
646
params->format = AFMT_S16_LE;
647
break;
648
case HDA_CODEC_FMT_BITS_24:
649
params->format = AFMT_S24_LE;
650
break;
651
case HDA_CODEC_FMT_BITS_32:
652
params->format = AFMT_S32_LE;
653
break;
654
default:
655
DPRINTF("Unknown format bits: 0x%x",
656
fmt & HDA_CODEC_FMT_BITS_MASK);
657
return (-1);
658
}
659
660
/* Compute the Number of Channels */
661
params->channels = (fmt & HDA_CODEC_FMT_CHAN_MASK) + 1;
662
663
return (0);
664
}
665
666
static uint32_t
667
hda_codec_audio_output_nid(struct hda_codec_softc *sc, uint16_t verb,
668
uint16_t payload)
669
{
670
struct hda_codec_stream *st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
671
int res;
672
673
res = hda_codec_audio_inout_nid(st, verb, payload);
674
675
return (res);
676
}
677
678
static void
679
hda_codec_audio_output_do_transfer(void *arg)
680
{
681
const struct hda_ops *hops = NULL;
682
struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
683
struct hda_codec_inst *hci = NULL;
684
struct hda_codec_stream *st = NULL;
685
struct audio *aud = NULL;
686
int err;
687
688
hci = sc->hci;
689
assert(hci);
690
691
hops = hci->hops;
692
assert(hops);
693
694
st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
695
aud = st->aud;
696
697
err = hops->transfer(hci, st->stream, 1, st->buf, sizeof(st->buf));
698
if (err)
699
return;
700
701
err = audio_playback(aud, st->buf, sizeof(st->buf));
702
assert(!err);
703
}
704
705
static int
706
hda_codec_audio_output_do_setup(void *arg)
707
{
708
struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
709
struct hda_codec_stream *st = NULL;
710
struct audio *aud = NULL;
711
struct audio_params params;
712
int err;
713
714
st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
715
aud = st->aud;
716
717
err = hda_codec_parse_format(st->fmt, &params);
718
if (err)
719
return (-1);
720
721
DPRINTF("rate: %d, channels: %d, format: 0x%x",
722
params.rate, params.channels, params.format);
723
724
return (audio_set_params(aud, &params));
725
}
726
727
static uint32_t
728
hda_codec_audio_input_nid(struct hda_codec_softc *sc, uint16_t verb,
729
uint16_t payload)
730
{
731
struct hda_codec_stream *st = &sc->streams[HDA_CODEC_STREAM_INPUT];
732
int res;
733
734
res = hda_codec_audio_inout_nid(st, verb, payload);
735
736
return (res);
737
}
738
739
static void
740
hda_codec_audio_input_do_transfer(void *arg)
741
{
742
const struct hda_ops *hops = NULL;
743
struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
744
struct hda_codec_inst *hci = NULL;
745
struct hda_codec_stream *st = NULL;
746
struct audio *aud = NULL;
747
int err;
748
749
hci = sc->hci;
750
assert(hci);
751
752
hops = hci->hops;
753
assert(hops);
754
755
st = &sc->streams[HDA_CODEC_STREAM_INPUT];
756
aud = st->aud;
757
758
err = audio_record(aud, st->buf, sizeof(st->buf));
759
assert(!err);
760
761
hops->transfer(hci, st->stream, 0, st->buf, sizeof(st->buf));
762
}
763
764
static int
765
hda_codec_audio_input_do_setup(void *arg)
766
{
767
struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
768
struct hda_codec_stream *st = NULL;
769
struct audio *aud = NULL;
770
struct audio_params params;
771
int err;
772
773
st = &sc->streams[HDA_CODEC_STREAM_INPUT];
774
aud = st->aud;
775
776
err = hda_codec_parse_format(st->fmt, &params);
777
if (err)
778
return (-1);
779
780
DPRINTF("rate: %d, channels: %d, format: 0x%x",
781
params.rate, params.channels, params.format);
782
783
return (audio_set_params(aud, &params));
784
}
785
786
static uint32_t
787
hda_codec_audio_inout_nid(struct hda_codec_stream *st, uint16_t verb,
788
uint16_t payload)
789
{
790
uint32_t res = 0;
791
uint8_t mute = 0;
792
uint8_t gain = 0;
793
794
DPRINTF("%s verb: 0x%x, payload, 0x%x", st->actx.name, verb, payload);
795
796
switch (verb) {
797
case HDA_CMD_VERB_GET_CONV_FMT:
798
res = st->fmt;
799
break;
800
case HDA_CMD_VERB_SET_CONV_FMT:
801
st->fmt = payload;
802
break;
803
case HDA_CMD_VERB_GET_AMP_GAIN_MUTE:
804
if (payload & HDA_CMD_GET_AMP_GAIN_MUTE_LEFT) {
805
res = st->left_gain | st->left_mute;
806
DPRINTF("GET_AMP_GAIN_MUTE_LEFT: 0x%x", res);
807
} else {
808
res = st->right_gain | st->right_mute;
809
DPRINTF("GET_AMP_GAIN_MUTE_RIGHT: 0x%x", res);
810
}
811
break;
812
case HDA_CMD_VERB_SET_AMP_GAIN_MUTE:
813
mute = payload & HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE;
814
gain = payload & HDA_CODEC_SET_AMP_GAIN_MUTE_GAIN_MASK;
815
816
if (payload & HDA_CMD_SET_AMP_GAIN_MUTE_LEFT) {
817
st->left_mute = mute;
818
st->left_gain = gain;
819
DPRINTF("SET_AMP_GAIN_MUTE_LEFT: \
820
mute: 0x%x gain: 0x%x", mute, gain);
821
}
822
823
if (payload & HDA_CMD_SET_AMP_GAIN_MUTE_RIGHT) {
824
st->right_mute = mute;
825
st->right_gain = gain;
826
DPRINTF("SET_AMP_GAIN_MUTE_RIGHT: \
827
mute: 0x%x gain: 0x%x", mute, gain);
828
}
829
break;
830
case HDA_CMD_VERB_GET_CONV_STREAM_CHAN:
831
res = (st->stream << 4) | st->channel;
832
break;
833
case HDA_CMD_VERB_SET_CONV_STREAM_CHAN:
834
st->channel = payload & 0x0f;
835
st->stream = (payload >> 4) & 0x0f;
836
DPRINTF("st->channel: 0x%x st->stream: 0x%x",
837
st->channel, st->stream);
838
if (!st->stream)
839
hda_audio_ctxt_stop(&st->actx);
840
break;
841
default:
842
DPRINTF("Unknown VERB: 0x%x", verb);
843
break;
844
}
845
846
return (res);
847
}
848
849
static const struct hda_codec_class hda_codec = {
850
.name = "hda_codec",
851
.init = hda_codec_init,
852
.reset = hda_codec_reset,
853
.command = hda_codec_command,
854
.notify = hda_codec_notify,
855
};
856
HDA_EMUL_SET(hda_codec);
857
858
/*
859
* HDA Audio Context module function definitions
860
*/
861
862
static void *
863
hda_audio_ctxt_thr(void *arg)
864
{
865
struct hda_audio_ctxt *actx = arg;
866
867
DPRINTF("Start Thread: %s", actx->name);
868
869
pthread_mutex_lock(&actx->mtx);
870
while (1) {
871
while (!actx->run)
872
pthread_cond_wait(&actx->cond, &actx->mtx);
873
874
actx->do_transfer(actx->priv);
875
}
876
pthread_mutex_unlock(&actx->mtx);
877
878
pthread_exit(NULL);
879
return (NULL);
880
}
881
882
static int
883
hda_audio_ctxt_init(struct hda_audio_ctxt *actx, const char *tname,
884
transfer_func_t do_transfer, setup_func_t do_setup, void *priv)
885
{
886
int err;
887
888
assert(actx);
889
assert(tname);
890
assert(do_transfer);
891
assert(do_setup);
892
assert(priv);
893
894
memset(actx, 0, sizeof(*actx));
895
896
actx->run = 0;
897
actx->do_transfer = do_transfer;
898
actx->do_setup = do_setup;
899
actx->priv = priv;
900
if (strlen(tname) < sizeof(actx->name))
901
memcpy(actx->name, tname, strlen(tname) + 1);
902
else
903
strcpy(actx->name, "unknown");
904
905
err = pthread_mutex_init(&actx->mtx, NULL);
906
assert(!err);
907
908
err = pthread_cond_init(&actx->cond, NULL);
909
assert(!err);
910
911
err = pthread_create(&actx->tid, NULL, hda_audio_ctxt_thr, actx);
912
assert(!err);
913
914
pthread_set_name_np(actx->tid, tname);
915
916
actx->started = 1;
917
918
return (0);
919
}
920
921
static int
922
hda_audio_ctxt_start(struct hda_audio_ctxt *actx)
923
{
924
int err = 0;
925
926
assert(actx);
927
assert(actx->started);
928
929
/* The stream is supposed to be stopped */
930
if (actx->run)
931
return (-1);
932
933
pthread_mutex_lock(&actx->mtx);
934
err = (* actx->do_setup)(actx->priv);
935
if (!err) {
936
actx->run = 1;
937
pthread_cond_signal(&actx->cond);
938
}
939
pthread_mutex_unlock(&actx->mtx);
940
941
return (err);
942
}
943
944
static int
945
hda_audio_ctxt_stop(struct hda_audio_ctxt *actx)
946
{
947
actx->run = 0;
948
return (0);
949
}
950
951