xref: /illumos-kvm-cmd/hw/hda-audio.c (revision 68396ea9)
1 /*
2  * Copyright (C) 2010 Red Hat, Inc.
3  *
4  * written by Gerd Hoffmann <kraxel@redhat.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 or
9  * (at your option) version 3 of the License.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "hw.h"
21 #include "pci.h"
22 #include "intel-hda.h"
23 #include "intel-hda-defs.h"
24 #include "audio/audio.h"
25 
26 /* -------------------------------------------------------------------------- */
27 
28 typedef struct desc_param {
29     uint32_t id;
30     uint32_t val;
31 } desc_param;
32 
33 typedef struct desc_node {
34     uint32_t nid;
35     const char *name;
36     const desc_param *params;
37     uint32_t nparams;
38     uint32_t config;
39     uint32_t pinctl;
40     uint32_t *conn;
41     uint32_t stindex;
42 } desc_node;
43 
44 typedef struct desc_codec {
45     const char *name;
46     uint32_t iid;
47     const desc_node *nodes;
48     uint32_t nnodes;
49 } desc_codec;
50 
hda_codec_find_param(const desc_node * node,uint32_t id)51 static const desc_param* hda_codec_find_param(const desc_node *node, uint32_t id)
52 {
53     int i;
54 
55     for (i = 0; i < node->nparams; i++) {
56         if (node->params[i].id == id) {
57             return &node->params[i];
58         }
59     }
60     return NULL;
61 }
62 
hda_codec_find_node(const desc_codec * codec,uint32_t nid)63 static const desc_node* hda_codec_find_node(const desc_codec *codec, uint32_t nid)
64 {
65     int i;
66 
67     for (i = 0; i < codec->nnodes; i++) {
68         if (codec->nodes[i].nid == nid) {
69             return &codec->nodes[i];
70         }
71     }
72     return NULL;
73 }
74 
hda_codec_parse_fmt(uint32_t format,struct audsettings * as)75 static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
76 {
77     if (format & AC_FMT_TYPE_NON_PCM) {
78         return;
79     }
80 
81     as->freq = (format & AC_FMT_BASE_44K) ? 44100 : 48000;
82 
83     switch ((format & AC_FMT_MULT_MASK) >> AC_FMT_MULT_SHIFT) {
84     case 1: as->freq *= 2; break;
85     case 2: as->freq *= 3; break;
86     case 3: as->freq *= 4; break;
87     }
88 
89     switch ((format & AC_FMT_DIV_MASK) >> AC_FMT_DIV_SHIFT) {
90     case 1: as->freq /= 2; break;
91     case 2: as->freq /= 3; break;
92     case 3: as->freq /= 4; break;
93     case 4: as->freq /= 5; break;
94     case 5: as->freq /= 6; break;
95     case 6: as->freq /= 7; break;
96     case 7: as->freq /= 8; break;
97     }
98 
99     switch (format & AC_FMT_BITS_MASK) {
100     case AC_FMT_BITS_8:  as->fmt = AUD_FMT_S8;  break;
101     case AC_FMT_BITS_16: as->fmt = AUD_FMT_S16; break;
102     case AC_FMT_BITS_32: as->fmt = AUD_FMT_S32; break;
103     }
104 
105     as->nchannels = ((format & AC_FMT_CHAN_MASK) >> AC_FMT_CHAN_SHIFT) + 1;
106 }
107 
108 /* -------------------------------------------------------------------------- */
109 /*
110  * HDA codec descriptions
111  */
112 
113 /* some defines */
114 
115 #define QEMU_HDA_ID_VENDOR  0x1af4
116 #define QEMU_HDA_ID_OUTPUT  ((QEMU_HDA_ID_VENDOR << 16) | 0x10)
117 #define QEMU_HDA_ID_DUPLEX  ((QEMU_HDA_ID_VENDOR << 16) | 0x20)
118 
119 #define QEMU_HDA_PCM_FORMATS (AC_SUPPCM_BITS_16 |       \
120                               0x1fc /* 16 -> 96 kHz */)
121 #define QEMU_HDA_AMP_NONE    (0)
122 #define QEMU_HDA_AMP_STEPS   0x4a
123 
124 #ifdef CONFIG_MIXEMU
125 #define QEMU_HDA_AMP_CAPS                                               \
126     (AC_AMPCAP_MUTE |                                                   \
127      (QEMU_HDA_AMP_STEPS << AC_AMPCAP_OFFSET_SHIFT)    |                \
128      (QEMU_HDA_AMP_STEPS << AC_AMPCAP_NUM_STEPS_SHIFT) |                \
129      (3                  << AC_AMPCAP_STEP_SIZE_SHIFT))
130 #else
131 #define QEMU_HDA_AMP_CAPS    QEMU_HDA_AMP_NONE
132 #endif
133 
134 /* common: audio output widget */
135 static const desc_param common_params_audio_dac[] = {
136     {
137         .id  = AC_PAR_AUDIO_WIDGET_CAP,
138         .val = ((AC_WID_AUD_OUT << AC_WCAP_TYPE_SHIFT) |
139                 AC_WCAP_FORMAT_OVRD |
140                 AC_WCAP_AMP_OVRD |
141                 AC_WCAP_OUT_AMP |
142                 AC_WCAP_STEREO),
143     },{
144         .id  = AC_PAR_PCM,
145         .val = QEMU_HDA_PCM_FORMATS,
146     },{
147         .id  = AC_PAR_STREAM,
148         .val = AC_SUPFMT_PCM,
149     },{
150         .id  = AC_PAR_AMP_IN_CAP,
151         .val = QEMU_HDA_AMP_NONE,
152     },{
153         .id  = AC_PAR_AMP_OUT_CAP,
154         .val = QEMU_HDA_AMP_CAPS,
155     },
156 };
157 
158 /* common: pin widget (line-out) */
159 static const desc_param common_params_audio_lineout[] = {
160     {
161         .id  = AC_PAR_AUDIO_WIDGET_CAP,
162         .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
163                 AC_WCAP_CONN_LIST |
164                 AC_WCAP_STEREO),
165     },{
166         .id  = AC_PAR_PIN_CAP,
167         .val = AC_PINCAP_OUT,
168     },{
169         .id  = AC_PAR_CONNLIST_LEN,
170         .val = 1,
171     },{
172         .id  = AC_PAR_AMP_IN_CAP,
173         .val = QEMU_HDA_AMP_NONE,
174     },{
175         .id  = AC_PAR_AMP_OUT_CAP,
176         .val = QEMU_HDA_AMP_NONE,
177     },
178 };
179 
180 /* output: root node */
181 static const desc_param output_params_root[] = {
182     {
183         .id  = AC_PAR_VENDOR_ID,
184         .val = QEMU_HDA_ID_OUTPUT,
185     },{
186         .id  = AC_PAR_SUBSYSTEM_ID,
187         .val = QEMU_HDA_ID_OUTPUT,
188     },{
189         .id  = AC_PAR_REV_ID,
190         .val = 0x00100101,
191     },{
192         .id  = AC_PAR_NODE_COUNT,
193         .val = 0x00010001,
194     },
195 };
196 
197 /* output: audio function */
198 static const desc_param output_params_audio_func[] = {
199     {
200         .id  = AC_PAR_FUNCTION_TYPE,
201         .val = AC_GRP_AUDIO_FUNCTION,
202     },{
203         .id  = AC_PAR_SUBSYSTEM_ID,
204         .val = QEMU_HDA_ID_OUTPUT,
205     },{
206         .id  = AC_PAR_NODE_COUNT,
207         .val = 0x00020002,
208     },{
209         .id  = AC_PAR_PCM,
210         .val = QEMU_HDA_PCM_FORMATS,
211     },{
212         .id  = AC_PAR_STREAM,
213         .val = AC_SUPFMT_PCM,
214     },{
215         .id  = AC_PAR_AMP_IN_CAP,
216         .val = QEMU_HDA_AMP_NONE,
217     },{
218         .id  = AC_PAR_AMP_OUT_CAP,
219         .val = QEMU_HDA_AMP_NONE,
220     },{
221         .id  = AC_PAR_GPIO_CAP,
222         .val = 0,
223     },{
224         .id  = AC_PAR_AUDIO_FG_CAP,
225         .val = 0x00000808,
226     },{
227         .id  = AC_PAR_POWER_STATE,
228         .val = 0,
229     },
230 };
231 
232 /* output: nodes */
233 static const desc_node output_nodes[] = {
234     {
235         .nid     = AC_NODE_ROOT,
236         .name    = "root",
237         .params  = output_params_root,
238         .nparams = ARRAY_SIZE(output_params_root),
239     },{
240         .nid     = 1,
241         .name    = "func",
242         .params  = output_params_audio_func,
243         .nparams = ARRAY_SIZE(output_params_audio_func),
244     },{
245         .nid     = 2,
246         .name    = "dac",
247         .params  = common_params_audio_dac,
248         .nparams = ARRAY_SIZE(common_params_audio_dac),
249         .stindex = 0,
250     },{
251         .nid     = 3,
252         .name    = "out",
253         .params  = common_params_audio_lineout,
254         .nparams = ARRAY_SIZE(common_params_audio_lineout),
255         .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
256                     (AC_JACK_LINE_OUT     << AC_DEFCFG_DEVICE_SHIFT)    |
257                     (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
258                     (AC_JACK_COLOR_GREEN  << AC_DEFCFG_COLOR_SHIFT)     |
259                     0x10),
260         .pinctl  = AC_PINCTL_OUT_EN,
261         .conn    = (uint32_t[]) { 2 },
262     }
263 };
264 
265 /* output: codec */
266 static const desc_codec output = {
267     .name   = "output",
268     .iid    = QEMU_HDA_ID_OUTPUT,
269     .nodes  = output_nodes,
270     .nnodes = ARRAY_SIZE(output_nodes),
271 };
272 
273 /* duplex: root node */
274 static const desc_param duplex_params_root[] = {
275     {
276         .id  = AC_PAR_VENDOR_ID,
277         .val = QEMU_HDA_ID_DUPLEX,
278     },{
279         .id  = AC_PAR_SUBSYSTEM_ID,
280         .val = QEMU_HDA_ID_DUPLEX,
281     },{
282         .id  = AC_PAR_REV_ID,
283         .val = 0x00100101,
284     },{
285         .id  = AC_PAR_NODE_COUNT,
286         .val = 0x00010001,
287     },
288 };
289 
290 /* duplex: audio input widget */
291 static const desc_param duplex_params_audio_adc[] = {
292     {
293         .id  = AC_PAR_AUDIO_WIDGET_CAP,
294         .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) |
295                 AC_WCAP_CONN_LIST |
296                 AC_WCAP_FORMAT_OVRD |
297                 AC_WCAP_AMP_OVRD |
298                 AC_WCAP_IN_AMP |
299                 AC_WCAP_STEREO),
300     },{
301         .id  = AC_PAR_CONNLIST_LEN,
302         .val = 1,
303     },{
304         .id  = AC_PAR_PCM,
305         .val = QEMU_HDA_PCM_FORMATS,
306     },{
307         .id  = AC_PAR_STREAM,
308         .val = AC_SUPFMT_PCM,
309     },{
310         .id  = AC_PAR_AMP_IN_CAP,
311         .val = QEMU_HDA_AMP_CAPS,
312     },{
313         .id  = AC_PAR_AMP_OUT_CAP,
314         .val = QEMU_HDA_AMP_NONE,
315     },
316 };
317 
318 /* duplex: pin widget (line-in) */
319 static const desc_param duplex_params_audio_linein[] = {
320     {
321         .id  = AC_PAR_AUDIO_WIDGET_CAP,
322         .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
323                 AC_WCAP_STEREO),
324     },{
325         .id  = AC_PAR_PIN_CAP,
326         .val = AC_PINCAP_IN,
327     },{
328         .id  = AC_PAR_AMP_IN_CAP,
329         .val = QEMU_HDA_AMP_NONE,
330     },{
331         .id  = AC_PAR_AMP_OUT_CAP,
332         .val = QEMU_HDA_AMP_NONE,
333     },
334 };
335 
336 /* duplex: audio function */
337 static const desc_param duplex_params_audio_func[] = {
338     {
339         .id  = AC_PAR_FUNCTION_TYPE,
340         .val = AC_GRP_AUDIO_FUNCTION,
341     },{
342         .id  = AC_PAR_SUBSYSTEM_ID,
343         .val = QEMU_HDA_ID_DUPLEX,
344     },{
345         .id  = AC_PAR_NODE_COUNT,
346         .val = 0x00020004,
347     },{
348         .id  = AC_PAR_PCM,
349         .val = QEMU_HDA_PCM_FORMATS,
350     },{
351         .id  = AC_PAR_STREAM,
352         .val = AC_SUPFMT_PCM,
353     },{
354         .id  = AC_PAR_AMP_IN_CAP,
355         .val = QEMU_HDA_AMP_NONE,
356     },{
357         .id  = AC_PAR_AMP_OUT_CAP,
358         .val = QEMU_HDA_AMP_NONE,
359     },{
360         .id  = AC_PAR_GPIO_CAP,
361         .val = 0,
362     },{
363         .id  = AC_PAR_AUDIO_FG_CAP,
364         .val = 0x00000808,
365     },{
366         .id  = AC_PAR_POWER_STATE,
367         .val = 0,
368     },
369 };
370 
371 /* duplex: nodes */
372 static const desc_node duplex_nodes[] = {
373     {
374         .nid     = AC_NODE_ROOT,
375         .name    = "root",
376         .params  = duplex_params_root,
377         .nparams = ARRAY_SIZE(duplex_params_root),
378     },{
379         .nid     = 1,
380         .name    = "func",
381         .params  = duplex_params_audio_func,
382         .nparams = ARRAY_SIZE(duplex_params_audio_func),
383     },{
384         .nid     = 2,
385         .name    = "dac",
386         .params  = common_params_audio_dac,
387         .nparams = ARRAY_SIZE(common_params_audio_dac),
388         .stindex = 0,
389     },{
390         .nid     = 3,
391         .name    = "out",
392         .params  = common_params_audio_lineout,
393         .nparams = ARRAY_SIZE(common_params_audio_lineout),
394         .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
395                     (AC_JACK_LINE_OUT     << AC_DEFCFG_DEVICE_SHIFT)    |
396                     (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
397                     (AC_JACK_COLOR_GREEN  << AC_DEFCFG_COLOR_SHIFT)     |
398                     0x10),
399         .pinctl  = AC_PINCTL_OUT_EN,
400         .conn    = (uint32_t[]) { 2 },
401     },{
402         .nid     = 4,
403         .name    = "adc",
404         .params  = duplex_params_audio_adc,
405         .nparams = ARRAY_SIZE(duplex_params_audio_adc),
406         .stindex = 1,
407         .conn    = (uint32_t[]) { 5 },
408     },{
409         .nid     = 5,
410         .name    = "in",
411         .params  = duplex_params_audio_linein,
412         .nparams = ARRAY_SIZE(duplex_params_audio_linein),
413         .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
414                     (AC_JACK_LINE_IN      << AC_DEFCFG_DEVICE_SHIFT)    |
415                     (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
416                     (AC_JACK_COLOR_RED    << AC_DEFCFG_COLOR_SHIFT)     |
417                     0x20),
418         .pinctl  = AC_PINCTL_IN_EN,
419     }
420 };
421 
422 /* duplex: codec */
423 static const desc_codec duplex = {
424     .name   = "duplex",
425     .iid    = QEMU_HDA_ID_DUPLEX,
426     .nodes  = duplex_nodes,
427     .nnodes = ARRAY_SIZE(duplex_nodes),
428 };
429 
430 /* -------------------------------------------------------------------------- */
431 
432 static const char *fmt2name[] = {
433     [ AUD_FMT_U8  ] = "PCM-U8",
434     [ AUD_FMT_S8  ] = "PCM-S8",
435     [ AUD_FMT_U16 ] = "PCM-U16",
436     [ AUD_FMT_S16 ] = "PCM-S16",
437     [ AUD_FMT_U32 ] = "PCM-U32",
438     [ AUD_FMT_S32 ] = "PCM-S32",
439 };
440 
441 typedef struct HDAAudioState HDAAudioState;
442 typedef struct HDAAudioStream HDAAudioStream;
443 
444 struct HDAAudioStream {
445     HDAAudioState *state;
446     const desc_node *node;
447     bool output, running;
448     uint32_t stream;
449     uint32_t channel;
450     uint32_t format;
451     uint32_t gain_left, gain_right;
452     bool mute_left, mute_right;
453     struct audsettings as;
454     union {
455         SWVoiceIn *in;
456         SWVoiceOut *out;
457     } voice;
458     uint8_t buf[HDA_BUFFER_SIZE];
459     uint32_t bpos;
460 };
461 
462 struct HDAAudioState {
463     HDACodecDevice hda;
464     const char *name;
465 
466     QEMUSoundCard card;
467     const desc_codec *desc;
468     HDAAudioStream st[4];
469     bool running[16];
470 
471     /* properties */
472     uint32_t debug;
473 };
474 
hda_audio_input_cb(void * opaque,int avail)475 static void hda_audio_input_cb(void *opaque, int avail)
476 {
477     HDAAudioStream *st = opaque;
478     int recv = 0;
479     int len;
480     bool rc;
481 
482     while (avail - recv >= sizeof(st->buf)) {
483         if (st->bpos != sizeof(st->buf)) {
484             len = AUD_read(st->voice.in, st->buf + st->bpos,
485                            sizeof(st->buf) - st->bpos);
486             st->bpos += len;
487             recv += len;
488             if (st->bpos != sizeof(st->buf)) {
489                 break;
490             }
491         }
492         rc = hda_codec_xfer(&st->state->hda, st->stream, false,
493                             st->buf, sizeof(st->buf));
494         if (!rc) {
495             break;
496         }
497         st->bpos = 0;
498     }
499 }
500 
hda_audio_output_cb(void * opaque,int avail)501 static void hda_audio_output_cb(void *opaque, int avail)
502 {
503     HDAAudioStream *st = opaque;
504     int sent = 0;
505     int len;
506     bool rc;
507 
508     while (avail - sent >= sizeof(st->buf)) {
509         if (st->bpos == sizeof(st->buf)) {
510             rc = hda_codec_xfer(&st->state->hda, st->stream, true,
511                                 st->buf, sizeof(st->buf));
512             if (!rc) {
513                 break;
514             }
515             st->bpos = 0;
516         }
517         len = AUD_write(st->voice.out, st->buf + st->bpos,
518                         sizeof(st->buf) - st->bpos);
519         st->bpos += len;
520         sent += len;
521         if (st->bpos != sizeof(st->buf)) {
522             break;
523         }
524     }
525 }
526 
hda_audio_set_running(HDAAudioStream * st,bool running)527 static void hda_audio_set_running(HDAAudioStream *st, bool running)
528 {
529     if (st->node == NULL) {
530         return;
531     }
532     if (st->running == running) {
533         return;
534     }
535     st->running = running;
536     dprint(st->state, 1, "%s: %s (stream %d)\n", st->node->name,
537            st->running ? "on" : "off", st->stream);
538     if (st->output) {
539         AUD_set_active_out(st->voice.out, st->running);
540     } else {
541         AUD_set_active_in(st->voice.in, st->running);
542     }
543 }
544 
hda_audio_set_amp(HDAAudioStream * st)545 static void hda_audio_set_amp(HDAAudioStream *st)
546 {
547     bool muted;
548     uint32_t left, right;
549 
550     if (st->node == NULL) {
551         return;
552     }
553 
554     muted = st->mute_left && st->mute_right;
555     left  = st->mute_left  ? 0 : st->gain_left;
556     right = st->mute_right ? 0 : st->gain_right;
557 
558     left = left * 255 / QEMU_HDA_AMP_STEPS;
559     right = right * 255 / QEMU_HDA_AMP_STEPS;
560 
561     if (st->output) {
562         AUD_set_volume_out(st->voice.out, muted, left, right);
563     } else {
564         AUD_set_volume_in(st->voice.in, muted, left, right);
565     }
566 }
567 
hda_audio_setup(HDAAudioStream * st)568 static void hda_audio_setup(HDAAudioStream *st)
569 {
570     if (st->node == NULL) {
571         return;
572     }
573 
574     dprint(st->state, 1, "%s: format: %d x %s @ %d Hz\n",
575            st->node->name, st->as.nchannels,
576            fmt2name[st->as.fmt], st->as.freq);
577 
578     if (st->output) {
579         st->voice.out = AUD_open_out(&st->state->card, st->voice.out,
580                                      st->node->name, st,
581                                      hda_audio_output_cb, &st->as);
582     } else {
583         st->voice.in = AUD_open_in(&st->state->card, st->voice.in,
584                                    st->node->name, st,
585                                    hda_audio_input_cb, &st->as);
586     }
587 }
588 
hda_audio_command(HDACodecDevice * hda,uint32_t nid,uint32_t data)589 static void hda_audio_command(HDACodecDevice *hda, uint32_t nid, uint32_t data)
590 {
591     HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
592     HDAAudioStream *st;
593     const desc_node *node = NULL;
594     const desc_param *param;
595     uint32_t verb, payload, response, count, shift;
596 
597     if ((data & 0x70000) == 0x70000) {
598         /* 12/8 id/payload */
599         verb = (data >> 8) & 0xfff;
600         payload = data & 0x00ff;
601     } else {
602         /* 4/16 id/payload */
603         verb = (data >> 8) & 0xf00;
604         payload = data & 0xffff;
605     }
606 
607     node = hda_codec_find_node(a->desc, nid);
608     if (node == NULL) {
609         goto fail;
610     }
611     dprint(a, 2, "%s: nid %d (%s), verb 0x%x, payload 0x%x\n",
612            __FUNCTION__, nid, node->name, verb, payload);
613 
614     switch (verb) {
615     /* all nodes */
616     case AC_VERB_PARAMETERS:
617         param = hda_codec_find_param(node, payload);
618         if (param == NULL) {
619             goto fail;
620         }
621         hda_codec_response(hda, true, param->val);
622         break;
623     case AC_VERB_GET_SUBSYSTEM_ID:
624         hda_codec_response(hda, true, a->desc->iid);
625         break;
626 
627     /* all functions */
628     case AC_VERB_GET_CONNECT_LIST:
629         param = hda_codec_find_param(node, AC_PAR_CONNLIST_LEN);
630         count = param ? param->val : 0;
631         response = 0;
632         shift = 0;
633         while (payload < count && shift < 32) {
634             response |= node->conn[payload] << shift;
635             payload++;
636             shift += 8;
637         }
638         hda_codec_response(hda, true, response);
639         break;
640 
641     /* pin widget */
642     case AC_VERB_GET_CONFIG_DEFAULT:
643         hda_codec_response(hda, true, node->config);
644         break;
645     case AC_VERB_GET_PIN_WIDGET_CONTROL:
646         hda_codec_response(hda, true, node->pinctl);
647         break;
648     case AC_VERB_SET_PIN_WIDGET_CONTROL:
649         if (node->pinctl != payload) {
650             dprint(a, 1, "unhandled pin control bit\n");
651         }
652         hda_codec_response(hda, true, 0);
653         break;
654 
655     /* audio in/out widget */
656     case AC_VERB_SET_CHANNEL_STREAMID:
657         st = a->st + node->stindex;
658         if (st->node == NULL) {
659             goto fail;
660         }
661         hda_audio_set_running(st, false);
662         st->stream = (payload >> 4) & 0x0f;
663         st->channel = payload & 0x0f;
664         dprint(a, 2, "%s: stream %d, channel %d\n",
665                st->node->name, st->stream, st->channel);
666         hda_audio_set_running(st, a->running[st->stream]);
667         hda_codec_response(hda, true, 0);
668         break;
669     case AC_VERB_GET_CONV:
670         st = a->st + node->stindex;
671         if (st->node == NULL) {
672             goto fail;
673         }
674         response = st->stream << 4 | st->channel;
675         hda_codec_response(hda, true, response);
676         break;
677     case AC_VERB_SET_STREAM_FORMAT:
678         st = a->st + node->stindex;
679         if (st->node == NULL) {
680             goto fail;
681         }
682         st->format = payload;
683         hda_codec_parse_fmt(st->format, &st->as);
684         hda_audio_setup(st);
685         hda_codec_response(hda, true, 0);
686         break;
687     case AC_VERB_GET_STREAM_FORMAT:
688         st = a->st + node->stindex;
689         if (st->node == NULL) {
690             goto fail;
691         }
692         hda_codec_response(hda, true, st->format);
693         break;
694     case AC_VERB_GET_AMP_GAIN_MUTE:
695         st = a->st + node->stindex;
696         if (st->node == NULL) {
697             goto fail;
698         }
699         if (payload & AC_AMP_GET_LEFT) {
700             response = st->gain_left | (st->mute_left ? AC_AMP_MUTE : 0);
701         } else {
702             response = st->gain_right | (st->mute_right ? AC_AMP_MUTE : 0);
703         }
704         hda_codec_response(hda, true, response);
705         break;
706     case AC_VERB_SET_AMP_GAIN_MUTE:
707         st = a->st + node->stindex;
708         if (st->node == NULL) {
709             goto fail;
710         }
711         dprint(a, 1, "amp (%s): %s%s%s%s index %d  gain %3d %s\n",
712                st->node->name,
713                (payload & AC_AMP_SET_OUTPUT) ? "o" : "-",
714                (payload & AC_AMP_SET_INPUT)  ? "i" : "-",
715                (payload & AC_AMP_SET_LEFT)   ? "l" : "-",
716                (payload & AC_AMP_SET_RIGHT)  ? "r" : "-",
717                (payload & AC_AMP_SET_INDEX) >> AC_AMP_SET_INDEX_SHIFT,
718                (payload & AC_AMP_GAIN),
719                (payload & AC_AMP_MUTE) ? "muted" : "");
720         if (payload & AC_AMP_SET_LEFT) {
721             st->gain_left = payload & AC_AMP_GAIN;
722             st->mute_left = payload & AC_AMP_MUTE;
723         }
724         if (payload & AC_AMP_SET_RIGHT) {
725             st->gain_right = payload & AC_AMP_GAIN;
726             st->mute_right = payload & AC_AMP_MUTE;
727         }
728         hda_audio_set_amp(st);
729         hda_codec_response(hda, true, 0);
730         break;
731 
732     /* not supported */
733     case AC_VERB_SET_POWER_STATE:
734     case AC_VERB_GET_POWER_STATE:
735     case AC_VERB_GET_SDI_SELECT:
736         hda_codec_response(hda, true, 0);
737         break;
738     default:
739         goto fail;
740     }
741     return;
742 
743 fail:
744     dprint(a, 1, "%s: not handled: nid %d (%s), verb 0x%x, payload 0x%x\n",
745            __FUNCTION__, nid, node ? node->name : "?", verb, payload);
746     hda_codec_response(hda, true, 0);
747 }
748 
hda_audio_stream(HDACodecDevice * hda,uint32_t stnr,bool running)749 static void hda_audio_stream(HDACodecDevice *hda, uint32_t stnr, bool running)
750 {
751     HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
752     int s;
753 
754     a->running[stnr] = running;
755     for (s = 0; s < ARRAY_SIZE(a->st); s++) {
756         if (a->st[s].node == NULL) {
757             continue;
758         }
759         if (a->st[s].stream != stnr) {
760             continue;
761         }
762         hda_audio_set_running(&a->st[s], running);
763     }
764 }
765 
hda_audio_init(HDACodecDevice * hda,const struct desc_codec * desc)766 static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
767 {
768     HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
769     HDAAudioStream *st;
770     const desc_node *node;
771     const desc_param *param;
772     uint32_t i, type;
773 
774     a->desc = desc;
775     a->name = a->hda.qdev.info->name;
776     dprint(a, 1, "%s: cad %d\n", __FUNCTION__, a->hda.cad);
777 
778     AUD_register_card("hda", &a->card);
779     for (i = 0; i < a->desc->nnodes; i++) {
780         node = a->desc->nodes + i;
781         param = hda_codec_find_param(node, AC_PAR_AUDIO_WIDGET_CAP);
782         if (NULL == param)
783             continue;
784         type = (param->val & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
785         switch (type) {
786         case AC_WID_AUD_OUT:
787         case AC_WID_AUD_IN:
788             assert(node->stindex < ARRAY_SIZE(a->st));
789             st = a->st + node->stindex;
790             st->state = a;
791             st->node = node;
792             if (type == AC_WID_AUD_OUT) {
793                 /* unmute output by default */
794                 st->gain_left = QEMU_HDA_AMP_STEPS;
795                 st->gain_right = QEMU_HDA_AMP_STEPS;
796                 st->bpos = sizeof(st->buf);
797                 st->output = true;
798             } else {
799                 st->output = false;
800             }
801             st->format = AC_FMT_TYPE_PCM | AC_FMT_BITS_16 |
802                 (1 << AC_FMT_CHAN_SHIFT);
803             hda_codec_parse_fmt(st->format, &st->as);
804             hda_audio_setup(st);
805             break;
806         }
807     }
808     return 0;
809 }
810 
hda_audio_exit(HDACodecDevice * hda)811 static int hda_audio_exit(HDACodecDevice *hda)
812 {
813     HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
814     HDAAudioStream *st;
815     int i;
816 
817     dprint(a, 1, "%s\n", __FUNCTION__);
818     for (i = 0; i < ARRAY_SIZE(a->st); i++) {
819         st = a->st + i;
820         if (st->node == NULL) {
821             continue;
822         }
823         if (st->output) {
824             AUD_close_out(&a->card, st->voice.out);
825         } else {
826             AUD_close_in(&a->card, st->voice.in);
827         }
828     }
829     AUD_remove_card(&a->card);
830     return 0;
831 }
832 
hda_audio_post_load(void * opaque,int version)833 static int hda_audio_post_load(void *opaque, int version)
834 {
835     HDAAudioState *a = opaque;
836     HDAAudioStream *st;
837     int i;
838 
839     dprint(a, 1, "%s\n", __FUNCTION__);
840     for (i = 0; i < ARRAY_SIZE(a->st); i++) {
841         st = a->st + i;
842         if (st->node == NULL)
843             continue;
844         hda_codec_parse_fmt(st->format, &st->as);
845         hda_audio_setup(st);
846         hda_audio_set_amp(st);
847         hda_audio_set_running(st, a->running[st->stream]);
848     }
849     return 0;
850 }
851 
852 static const VMStateDescription vmstate_hda_audio_stream = {
853     .name = "hda-audio-stream",
854     .version_id = 1,
855     .fields = (VMStateField []) {
856         VMSTATE_UINT32(stream, HDAAudioStream),
857         VMSTATE_UINT32(channel, HDAAudioStream),
858         VMSTATE_UINT32(format, HDAAudioStream),
859         VMSTATE_UINT32(gain_left, HDAAudioStream),
860         VMSTATE_UINT32(gain_right, HDAAudioStream),
861         VMSTATE_BOOL(mute_left, HDAAudioStream),
862         VMSTATE_BOOL(mute_right, HDAAudioStream),
863         VMSTATE_UINT32(bpos, HDAAudioStream),
864         VMSTATE_BUFFER(buf, HDAAudioStream),
865         VMSTATE_END_OF_LIST()
866     }
867 };
868 
869 static const VMStateDescription vmstate_hda_audio = {
870     .name = "hda-audio",
871     .version_id = 1,
872     .post_load = hda_audio_post_load,
873     .fields = (VMStateField []) {
874         VMSTATE_STRUCT_ARRAY(st, HDAAudioState, 4, 0,
875                              vmstate_hda_audio_stream,
876                              HDAAudioStream),
877         VMSTATE_BOOL_ARRAY(running, HDAAudioState, 16),
878         VMSTATE_END_OF_LIST()
879     }
880 };
881 
882 static Property hda_audio_properties[] = {
883     DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0),
884     DEFINE_PROP_END_OF_LIST(),
885 };
886 
hda_audio_init_output(HDACodecDevice * hda)887 static int hda_audio_init_output(HDACodecDevice *hda)
888 {
889     return hda_audio_init(hda, &output);
890 }
891 
hda_audio_init_duplex(HDACodecDevice * hda)892 static int hda_audio_init_duplex(HDACodecDevice *hda)
893 {
894     return hda_audio_init(hda, &duplex);
895 }
896 
897 static HDACodecDeviceInfo hda_audio_info_output = {
898     .qdev.name    = "hda-output",
899     .qdev.desc    = "HDA Audio Codec, output-only",
900     .qdev.size    = sizeof(HDAAudioState),
901     .qdev.vmsd    = &vmstate_hda_audio,
902     .qdev.props   = hda_audio_properties,
903     .init         = hda_audio_init_output,
904     .exit         = hda_audio_exit,
905     .command      = hda_audio_command,
906     .stream       = hda_audio_stream,
907 };
908 
909 static HDACodecDeviceInfo hda_audio_info_duplex = {
910     .qdev.name    = "hda-duplex",
911     .qdev.desc    = "HDA Audio Codec, duplex",
912     .qdev.size    = sizeof(HDAAudioState),
913     .qdev.vmsd    = &vmstate_hda_audio,
914     .qdev.props   = hda_audio_properties,
915     .init         = hda_audio_init_duplex,
916     .exit         = hda_audio_exit,
917     .command      = hda_audio_command,
918     .stream       = hda_audio_stream,
919 };
920 
hda_audio_register(void)921 static void hda_audio_register(void)
922 {
923     hda_codec_register(&hda_audio_info_output);
924     hda_codec_register(&hda_audio_info_duplex);
925 }
926 device_init(hda_audio_register);
927