2 * Copyright (C) 2010 Red Hat, Inc.
4 * written by Gerd Hoffmann <kraxel@redhat.com>
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.
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.
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/>.
20 #include "qemu/osdep.h"
21 #include "hw/pci/pci.h"
22 #include "hw/qdev-properties.h"
23 #include "intel-hda.h"
24 #include "migration/vmstate.h"
25 #include "qemu/host-utils.h"
26 #include "qemu/module.h"
27 #include "intel-hda-defs.h"
28 #include "audio/audio.h"
30 #include "qom/object.h"
32 /* -------------------------------------------------------------------------- */
34 typedef struct desc_param
{
39 typedef struct desc_node
{
42 const desc_param
*params
;
50 typedef struct desc_codec
{
53 const desc_node
*nodes
;
57 static const desc_param
* hda_codec_find_param(const desc_node
*node
, uint32_t id
)
61 for (i
= 0; i
< node
->nparams
; i
++) {
62 if (node
->params
[i
].id
== id
) {
63 return &node
->params
[i
];
69 static const desc_node
* hda_codec_find_node(const desc_codec
*codec
, uint32_t nid
)
73 for (i
= 0; i
< codec
->nnodes
; i
++) {
74 if (codec
->nodes
[i
].nid
== nid
) {
75 return &codec
->nodes
[i
];
81 static void hda_codec_parse_fmt(uint32_t format
, struct audsettings
*as
)
83 if (format
& AC_FMT_TYPE_NON_PCM
) {
87 as
->freq
= (format
& AC_FMT_BASE_44K
) ? 44100 : 48000;
89 switch ((format
& AC_FMT_MULT_MASK
) >> AC_FMT_MULT_SHIFT
) {
90 case 1: as
->freq
*= 2; break;
91 case 2: as
->freq
*= 3; break;
92 case 3: as
->freq
*= 4; break;
95 switch ((format
& AC_FMT_DIV_MASK
) >> AC_FMT_DIV_SHIFT
) {
96 case 1: as
->freq
/= 2; break;
97 case 2: as
->freq
/= 3; break;
98 case 3: as
->freq
/= 4; break;
99 case 4: as
->freq
/= 5; break;
100 case 5: as
->freq
/= 6; break;
101 case 6: as
->freq
/= 7; break;
102 case 7: as
->freq
/= 8; break;
105 switch (format
& AC_FMT_BITS_MASK
) {
106 case AC_FMT_BITS_8
: as
->fmt
= AUDIO_FORMAT_S8
; break;
107 case AC_FMT_BITS_16
: as
->fmt
= AUDIO_FORMAT_S16
; break;
108 case AC_FMT_BITS_32
: as
->fmt
= AUDIO_FORMAT_S32
; break;
111 as
->nchannels
= ((format
& AC_FMT_CHAN_MASK
) >> AC_FMT_CHAN_SHIFT
) + 1;
114 /* -------------------------------------------------------------------------- */
116 * HDA codec descriptions
121 #define QEMU_HDA_ID_VENDOR 0x1af4
122 #define QEMU_HDA_PCM_FORMATS (AC_SUPPCM_BITS_16 | \
123 0x1fc /* 16 -> 96 kHz */)
124 #define QEMU_HDA_AMP_NONE (0)
125 #define QEMU_HDA_AMP_STEPS 0x4a
129 #include "hda-codec-common.h"
131 #define PARAM nomixemu
132 #include "hda-codec-common.h"
134 #define HDA_TIMER_TICKS (SCALE_MS)
135 #define B_SIZE sizeof(st->buf)
136 #define B_MASK (sizeof(st->buf) - 1)
138 /* -------------------------------------------------------------------------- */
140 static const char *fmt2name
[] = {
141 [ AUDIO_FORMAT_U8
] = "PCM-U8",
142 [ AUDIO_FORMAT_S8
] = "PCM-S8",
143 [ AUDIO_FORMAT_U16
] = "PCM-U16",
144 [ AUDIO_FORMAT_S16
] = "PCM-S16",
145 [ AUDIO_FORMAT_U32
] = "PCM-U32",
146 [ AUDIO_FORMAT_S32
] = "PCM-S32",
149 #define TYPE_HDA_AUDIO "hda-audio"
150 OBJECT_DECLARE_SIMPLE_TYPE(HDAAudioState
, HDA_AUDIO
)
152 typedef struct HDAAudioStream HDAAudioStream
;
154 struct HDAAudioStream
{
155 HDAAudioState
*state
;
156 const desc_node
*node
;
157 bool output
, running
;
161 uint32_t gain_left
, gain_right
;
162 bool mute_left
, mute_right
;
163 struct audsettings as
;
168 uint8_t compat_buf
[HDA_BUFFER_SIZE
];
169 uint32_t compat_bpos
;
170 uint8_t buf
[8192]; /* size must be power of two */
177 struct HDAAudioState
{
182 const desc_codec
*desc
;
183 HDAAudioStream st
[4];
184 bool running_compat
[16];
185 bool running_real
[2 * 16];
193 static inline uint32_t hda_bytes_per_second(HDAAudioStream
*st
)
195 return 2 * (uint32_t)st
->as
.nchannels
* (uint32_t)st
->as
.freq
;
198 static inline void hda_timer_sync_adjust(HDAAudioStream
*st
, int64_t target_pos
)
200 int64_t limit
= B_SIZE
/ 8;
203 if (target_pos
> limit
) {
204 corr
= HDA_TIMER_TICKS
;
206 if (target_pos
< -limit
) {
207 corr
= -HDA_TIMER_TICKS
;
209 if (target_pos
< -(2 * limit
)) {
210 corr
= -(4 * HDA_TIMER_TICKS
);
216 trace_hda_audio_adjust(st
->node
->name
, target_pos
);
217 st
->buft_start
+= corr
;
220 static void hda_audio_input_timer(void *opaque
)
222 HDAAudioStream
*st
= opaque
;
224 int64_t now
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
226 int64_t uptime
= now
- st
->buft_start
;
227 int64_t wpos
= st
->wpos
;
228 int64_t rpos
= st
->rpos
;
232 /* wanted_rpos <= 0 */
236 wanted_rpos
= muldiv64(uptime
, hda_bytes_per_second(st
),
237 NANOSECONDS_PER_SECOND
);
238 wanted_rpos
&= -4; /* IMPORTANT! clip to frames */
240 if (wanted_rpos
<= rpos
) {
241 /* we already transmitted the data */
245 int64_t to_transfer
= MIN(wpos
- rpos
, wanted_rpos
- rpos
);
246 while (to_transfer
) {
247 uint32_t start
= (rpos
& B_MASK
);
248 uint32_t chunk
= MIN(B_SIZE
- start
, to_transfer
);
249 int rc
= hda_codec_xfer(
250 &st
->state
->hda
, st
->stream
, false, st
->buf
+ start
, chunk
);
255 to_transfer
-= chunk
;
262 timer_mod_anticipate_ns(st
->buft
, now
+ HDA_TIMER_TICKS
);
266 static void hda_audio_input_cb(void *opaque
, int avail
)
268 HDAAudioStream
*st
= opaque
;
270 int64_t wpos
= st
->wpos
;
271 int64_t rpos
= st
->rpos
;
273 int64_t to_transfer
= MIN(B_SIZE
- (wpos
- rpos
), avail
);
275 while (to_transfer
) {
276 uint32_t start
= (uint32_t) (wpos
& B_MASK
);
277 uint32_t chunk
= (uint32_t) MIN(B_SIZE
- start
, to_transfer
);
278 uint32_t read
= AUD_read(st
->voice
.in
, st
->buf
+ start
, chunk
);
287 hda_timer_sync_adjust(st
, -((wpos
- rpos
) - (B_SIZE
>> 1)));
290 static void hda_audio_output_timer(void *opaque
)
292 HDAAudioStream
*st
= opaque
;
294 int64_t now
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
296 int64_t uptime
= now
- st
->buft_start
;
297 int64_t wpos
= st
->wpos
;
298 int64_t rpos
= st
->rpos
;
302 /* wanted_wpos <= 0 */
306 wanted_wpos
= muldiv64(uptime
, hda_bytes_per_second(st
),
307 NANOSECONDS_PER_SECOND
);
308 wanted_wpos
&= -4; /* IMPORTANT! clip to frames */
310 if (wanted_wpos
<= wpos
) {
311 /* we already received the data */
315 int64_t to_transfer
= MIN(B_SIZE
- (wpos
- rpos
), wanted_wpos
- wpos
);
316 while (to_transfer
) {
317 uint32_t start
= (wpos
& B_MASK
);
318 uint32_t chunk
= MIN(B_SIZE
- start
, to_transfer
);
319 int rc
= hda_codec_xfer(
320 &st
->state
->hda
, st
->stream
, true, st
->buf
+ start
, chunk
);
325 to_transfer
-= chunk
;
332 timer_mod_anticipate_ns(st
->buft
, now
+ HDA_TIMER_TICKS
);
336 static void hda_audio_output_cb(void *opaque
, int avail
)
338 HDAAudioStream
*st
= opaque
;
340 int64_t wpos
= st
->wpos
;
341 int64_t rpos
= st
->rpos
;
343 int64_t to_transfer
= MIN(wpos
- rpos
, avail
);
345 if (wpos
- rpos
== B_SIZE
) {
346 /* drop buffer, reset timer adjust */
349 st
->buft_start
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
350 trace_hda_audio_overrun(st
->node
->name
);
354 while (to_transfer
) {
355 uint32_t start
= (uint32_t) (rpos
& B_MASK
);
356 uint32_t chunk
= (uint32_t) MIN(B_SIZE
- start
, to_transfer
);
357 uint32_t written
= AUD_write(st
->voice
.out
, st
->buf
+ start
, chunk
);
359 to_transfer
-= written
;
361 if (chunk
!= written
) {
366 hda_timer_sync_adjust(st
, (wpos
- rpos
) - (B_SIZE
>> 1));
369 static void hda_audio_compat_input_cb(void *opaque
, int avail
)
371 HDAAudioStream
*st
= opaque
;
376 while (avail
- recv
>= sizeof(st
->compat_buf
)) {
377 if (st
->compat_bpos
!= sizeof(st
->compat_buf
)) {
378 len
= AUD_read(st
->voice
.in
, st
->compat_buf
+ st
->compat_bpos
,
379 sizeof(st
->compat_buf
) - st
->compat_bpos
);
380 st
->compat_bpos
+= len
;
382 if (st
->compat_bpos
!= sizeof(st
->compat_buf
)) {
386 rc
= hda_codec_xfer(&st
->state
->hda
, st
->stream
, false,
387 st
->compat_buf
, sizeof(st
->compat_buf
));
395 static void hda_audio_compat_output_cb(void *opaque
, int avail
)
397 HDAAudioStream
*st
= opaque
;
402 while (avail
- sent
>= sizeof(st
->compat_buf
)) {
403 if (st
->compat_bpos
== sizeof(st
->compat_buf
)) {
404 rc
= hda_codec_xfer(&st
->state
->hda
, st
->stream
, true,
405 st
->compat_buf
, sizeof(st
->compat_buf
));
411 len
= AUD_write(st
->voice
.out
, st
->compat_buf
+ st
->compat_bpos
,
412 sizeof(st
->compat_buf
) - st
->compat_bpos
);
413 st
->compat_bpos
+= len
;
415 if (st
->compat_bpos
!= sizeof(st
->compat_buf
)) {
421 static void hda_audio_set_running(HDAAudioStream
*st
, bool running
)
423 if (st
->node
== NULL
) {
426 if (st
->running
== running
) {
429 st
->running
= running
;
430 trace_hda_audio_running(st
->node
->name
, st
->stream
, st
->running
);
431 if (st
->state
->use_timer
) {
433 int64_t now
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
436 st
->buft_start
= now
;
437 timer_mod_anticipate_ns(st
->buft
, now
+ HDA_TIMER_TICKS
);
443 AUD_set_active_out(st
->voice
.out
, st
->running
);
445 AUD_set_active_in(st
->voice
.in
, st
->running
);
449 static void hda_audio_set_amp(HDAAudioStream
*st
)
452 uint32_t left
, right
;
454 if (st
->node
== NULL
) {
458 muted
= st
->mute_left
&& st
->mute_right
;
459 left
= st
->mute_left
? 0 : st
->gain_left
;
460 right
= st
->mute_right
? 0 : st
->gain_right
;
462 left
= left
* 255 / QEMU_HDA_AMP_STEPS
;
463 right
= right
* 255 / QEMU_HDA_AMP_STEPS
;
465 if (!st
->state
->mixer
) {
469 AUD_set_volume_out(st
->voice
.out
, muted
, left
, right
);
471 AUD_set_volume_in(st
->voice
.in
, muted
, left
, right
);
475 static void hda_audio_setup(HDAAudioStream
*st
)
477 bool use_timer
= st
->state
->use_timer
;
478 audio_callback_fn cb
;
480 if (st
->node
== NULL
) {
484 trace_hda_audio_format(st
->node
->name
, st
->as
.nchannels
,
485 fmt2name
[st
->as
.fmt
], st
->as
.freq
);
489 cb
= hda_audio_output_cb
;
490 st
->buft
= timer_new_ns(QEMU_CLOCK_VIRTUAL
,
491 hda_audio_output_timer
, st
);
493 cb
= hda_audio_compat_output_cb
;
495 st
->voice
.out
= AUD_open_out(&st
->state
->card
, st
->voice
.out
,
496 st
->node
->name
, st
, cb
, &st
->as
);
499 cb
= hda_audio_input_cb
;
500 st
->buft
= timer_new_ns(QEMU_CLOCK_VIRTUAL
,
501 hda_audio_input_timer
, st
);
503 cb
= hda_audio_compat_input_cb
;
505 st
->voice
.in
= AUD_open_in(&st
->state
->card
, st
->voice
.in
,
506 st
->node
->name
, st
, cb
, &st
->as
);
510 static void hda_audio_command(HDACodecDevice
*hda
, uint32_t nid
, uint32_t data
)
512 HDAAudioState
*a
= HDA_AUDIO(hda
);
514 const desc_node
*node
= NULL
;
515 const desc_param
*param
;
516 uint32_t verb
, payload
, response
, count
, shift
;
518 if ((data
& 0x70000) == 0x70000) {
519 /* 12/8 id/payload */
520 verb
= (data
>> 8) & 0xfff;
521 payload
= data
& 0x00ff;
523 /* 4/16 id/payload */
524 verb
= (data
>> 8) & 0xf00;
525 payload
= data
& 0xffff;
528 node
= hda_codec_find_node(a
->desc
, nid
);
532 dprint(a
, 2, "%s: nid %d (%s), verb 0x%x, payload 0x%x\n",
533 __func__
, nid
, node
->name
, verb
, payload
);
537 case AC_VERB_PARAMETERS
:
538 param
= hda_codec_find_param(node
, payload
);
542 hda_codec_response(hda
, true, param
->val
);
544 case AC_VERB_GET_SUBSYSTEM_ID
:
545 hda_codec_response(hda
, true, a
->desc
->iid
);
549 case AC_VERB_GET_CONNECT_LIST
:
550 param
= hda_codec_find_param(node
, AC_PAR_CONNLIST_LEN
);
551 count
= param
? param
->val
: 0;
554 while (payload
< count
&& shift
< 32) {
555 response
|= node
->conn
[payload
] << shift
;
559 hda_codec_response(hda
, true, response
);
563 case AC_VERB_GET_CONFIG_DEFAULT
:
564 hda_codec_response(hda
, true, node
->config
);
566 case AC_VERB_GET_PIN_WIDGET_CONTROL
:
567 hda_codec_response(hda
, true, node
->pinctl
);
569 case AC_VERB_SET_PIN_WIDGET_CONTROL
:
570 if (node
->pinctl
!= payload
) {
571 dprint(a
, 1, "unhandled pin control bit\n");
573 hda_codec_response(hda
, true, 0);
576 /* audio in/out widget */
577 case AC_VERB_SET_CHANNEL_STREAMID
:
578 st
= a
->st
+ node
->stindex
;
579 if (st
->node
== NULL
) {
582 hda_audio_set_running(st
, false);
583 st
->stream
= (payload
>> 4) & 0x0f;
584 st
->channel
= payload
& 0x0f;
585 dprint(a
, 2, "%s: stream %d, channel %d\n",
586 st
->node
->name
, st
->stream
, st
->channel
);
587 hda_audio_set_running(st
, a
->running_real
[st
->output
* 16 + st
->stream
]);
588 hda_codec_response(hda
, true, 0);
590 case AC_VERB_GET_CONV
:
591 st
= a
->st
+ node
->stindex
;
592 if (st
->node
== NULL
) {
595 response
= st
->stream
<< 4 | st
->channel
;
596 hda_codec_response(hda
, true, response
);
598 case AC_VERB_SET_STREAM_FORMAT
:
599 st
= a
->st
+ node
->stindex
;
600 if (st
->node
== NULL
) {
603 st
->format
= payload
;
604 hda_codec_parse_fmt(st
->format
, &st
->as
);
606 hda_codec_response(hda
, true, 0);
608 case AC_VERB_GET_STREAM_FORMAT
:
609 st
= a
->st
+ node
->stindex
;
610 if (st
->node
== NULL
) {
613 hda_codec_response(hda
, true, st
->format
);
615 case AC_VERB_GET_AMP_GAIN_MUTE
:
616 st
= a
->st
+ node
->stindex
;
617 if (st
->node
== NULL
) {
620 if (payload
& AC_AMP_GET_LEFT
) {
621 response
= st
->gain_left
| (st
->mute_left
? AC_AMP_MUTE
: 0);
623 response
= st
->gain_right
| (st
->mute_right
? AC_AMP_MUTE
: 0);
625 hda_codec_response(hda
, true, response
);
627 case AC_VERB_SET_AMP_GAIN_MUTE
:
628 st
= a
->st
+ node
->stindex
;
629 if (st
->node
== NULL
) {
632 dprint(a
, 1, "amp (%s): %s%s%s%s index %d gain %3d %s\n",
634 (payload
& AC_AMP_SET_OUTPUT
) ? "o" : "-",
635 (payload
& AC_AMP_SET_INPUT
) ? "i" : "-",
636 (payload
& AC_AMP_SET_LEFT
) ? "l" : "-",
637 (payload
& AC_AMP_SET_RIGHT
) ? "r" : "-",
638 (payload
& AC_AMP_SET_INDEX
) >> AC_AMP_SET_INDEX_SHIFT
,
639 (payload
& AC_AMP_GAIN
),
640 (payload
& AC_AMP_MUTE
) ? "muted" : "");
641 if (payload
& AC_AMP_SET_LEFT
) {
642 st
->gain_left
= payload
& AC_AMP_GAIN
;
643 st
->mute_left
= payload
& AC_AMP_MUTE
;
645 if (payload
& AC_AMP_SET_RIGHT
) {
646 st
->gain_right
= payload
& AC_AMP_GAIN
;
647 st
->mute_right
= payload
& AC_AMP_MUTE
;
649 hda_audio_set_amp(st
);
650 hda_codec_response(hda
, true, 0);
654 case AC_VERB_SET_POWER_STATE
:
655 case AC_VERB_GET_POWER_STATE
:
656 case AC_VERB_GET_SDI_SELECT
:
657 hda_codec_response(hda
, true, 0);
665 dprint(a
, 1, "%s: not handled: nid %d (%s), verb 0x%x, payload 0x%x\n",
666 __func__
, nid
, node
? node
->name
: "?", verb
, payload
);
667 hda_codec_response(hda
, true, 0);
670 static void hda_audio_stream(HDACodecDevice
*hda
, uint32_t stnr
, bool running
, bool output
)
672 HDAAudioState
*a
= HDA_AUDIO(hda
);
675 a
->running_compat
[stnr
] = running
;
676 a
->running_real
[output
* 16 + stnr
] = running
;
677 for (s
= 0; s
< ARRAY_SIZE(a
->st
); s
++) {
678 if (a
->st
[s
].node
== NULL
) {
681 if (a
->st
[s
].output
!= output
) {
684 if (a
->st
[s
].stream
!= stnr
) {
687 hda_audio_set_running(&a
->st
[s
], running
);
691 static void hda_audio_init(HDACodecDevice
*hda
,
692 const struct desc_codec
*desc
,
695 HDAAudioState
*a
= HDA_AUDIO(hda
);
697 const desc_node
*node
;
698 const desc_param
*param
;
701 if (!AUD_register_card("hda", &a
->card
, errp
)) {
706 a
->name
= object_get_typename(OBJECT(a
));
707 dprint(a
, 1, "%s: cad %d\n", __func__
, a
->hda
.cad
);
709 for (i
= 0; i
< a
->desc
->nnodes
; i
++) {
710 node
= a
->desc
->nodes
+ i
;
711 param
= hda_codec_find_param(node
, AC_PAR_AUDIO_WIDGET_CAP
);
715 type
= (param
->val
& AC_WCAP_TYPE
) >> AC_WCAP_TYPE_SHIFT
;
719 assert(node
->stindex
< ARRAY_SIZE(a
->st
));
720 st
= a
->st
+ node
->stindex
;
723 if (type
== AC_WID_AUD_OUT
) {
724 /* unmute output by default */
725 st
->gain_left
= QEMU_HDA_AMP_STEPS
;
726 st
->gain_right
= QEMU_HDA_AMP_STEPS
;
727 st
->compat_bpos
= sizeof(st
->compat_buf
);
732 st
->format
= AC_FMT_TYPE_PCM
| AC_FMT_BITS_16
|
733 (1 << AC_FMT_CHAN_SHIFT
);
734 hda_codec_parse_fmt(st
->format
, &st
->as
);
741 static void hda_audio_exit(HDACodecDevice
*hda
)
743 HDAAudioState
*a
= HDA_AUDIO(hda
);
747 dprint(a
, 1, "%s\n", __func__
);
748 for (i
= 0; i
< ARRAY_SIZE(a
->st
); i
++) {
750 if (st
->node
== NULL
) {
757 AUD_close_out(&a
->card
, st
->voice
.out
);
759 AUD_close_in(&a
->card
, st
->voice
.in
);
762 AUD_remove_card(&a
->card
);
765 static int hda_audio_post_load(void *opaque
, int version
)
767 HDAAudioState
*a
= opaque
;
771 dprint(a
, 1, "%s\n", __func__
);
773 /* assume running_compat[] is for output streams */
774 for (i
= 0; i
< ARRAY_SIZE(a
->running_compat
); i
++)
775 a
->running_real
[16 + i
] = a
->running_compat
[i
];
778 for (i
= 0; i
< ARRAY_SIZE(a
->st
); i
++) {
780 if (st
->node
== NULL
)
782 hda_codec_parse_fmt(st
->format
, &st
->as
);
784 hda_audio_set_amp(st
);
785 hda_audio_set_running(st
, a
->running_real
[st
->output
* 16 + st
->stream
]);
790 static void hda_audio_reset(DeviceState
*dev
)
792 HDAAudioState
*a
= HDA_AUDIO(dev
);
796 dprint(a
, 1, "%s\n", __func__
);
797 for (i
= 0; i
< ARRAY_SIZE(a
->st
); i
++) {
799 if (st
->node
!= NULL
) {
800 hda_audio_set_running(st
, false);
805 static bool vmstate_hda_audio_stream_buf_needed(void *opaque
)
807 HDAAudioStream
*st
= opaque
;
808 return st
->state
&& st
->state
->use_timer
;
811 static const VMStateDescription vmstate_hda_audio_stream_buf
= {
812 .name
= "hda-audio-stream/buffer",
814 .needed
= vmstate_hda_audio_stream_buf_needed
,
815 .fields
= (const VMStateField
[]) {
816 VMSTATE_BUFFER(buf
, HDAAudioStream
),
817 VMSTATE_INT64(rpos
, HDAAudioStream
),
818 VMSTATE_INT64(wpos
, HDAAudioStream
),
819 VMSTATE_TIMER_PTR(buft
, HDAAudioStream
),
820 VMSTATE_INT64(buft_start
, HDAAudioStream
),
821 VMSTATE_END_OF_LIST()
825 static const VMStateDescription vmstate_hda_audio_stream
= {
826 .name
= "hda-audio-stream",
828 .fields
= (const VMStateField
[]) {
829 VMSTATE_UINT32(stream
, HDAAudioStream
),
830 VMSTATE_UINT32(channel
, HDAAudioStream
),
831 VMSTATE_UINT32(format
, HDAAudioStream
),
832 VMSTATE_UINT32(gain_left
, HDAAudioStream
),
833 VMSTATE_UINT32(gain_right
, HDAAudioStream
),
834 VMSTATE_BOOL(mute_left
, HDAAudioStream
),
835 VMSTATE_BOOL(mute_right
, HDAAudioStream
),
836 VMSTATE_UINT32(compat_bpos
, HDAAudioStream
),
837 VMSTATE_BUFFER(compat_buf
, HDAAudioStream
),
838 VMSTATE_END_OF_LIST()
840 .subsections
= (const VMStateDescription
* const []) {
841 &vmstate_hda_audio_stream_buf
,
846 static const VMStateDescription vmstate_hda_audio
= {
849 .post_load
= hda_audio_post_load
,
850 .fields
= (const VMStateField
[]) {
851 VMSTATE_STRUCT_ARRAY(st
, HDAAudioState
, 4, 0,
852 vmstate_hda_audio_stream
,
854 VMSTATE_BOOL_ARRAY(running_compat
, HDAAudioState
, 16),
855 VMSTATE_BOOL_ARRAY_V(running_real
, HDAAudioState
, 2 * 16, 2),
856 VMSTATE_END_OF_LIST()
860 static Property hda_audio_properties
[] = {
861 DEFINE_AUDIO_PROPERTIES(HDAAudioState
, card
),
862 DEFINE_PROP_UINT32("debug", HDAAudioState
, debug
, 0),
863 DEFINE_PROP_BOOL("mixer", HDAAudioState
, mixer
, true),
864 DEFINE_PROP_BOOL("use-timer", HDAAudioState
, use_timer
, true),
865 DEFINE_PROP_END_OF_LIST(),
868 static void hda_audio_init_output(HDACodecDevice
*hda
, Error
**errp
)
870 HDAAudioState
*a
= HDA_AUDIO(hda
);
871 const struct desc_codec
*desc
= &output_mixemu
;
874 desc
= &output_nomixemu
;
877 hda_audio_init(hda
, desc
, errp
);
880 static void hda_audio_init_duplex(HDACodecDevice
*hda
, Error
**errp
)
882 HDAAudioState
*a
= HDA_AUDIO(hda
);
883 const struct desc_codec
*desc
= &duplex_mixemu
;
886 desc
= &duplex_nomixemu
;
889 hda_audio_init(hda
, desc
, errp
);
892 static void hda_audio_init_micro(HDACodecDevice
*hda
, Error
**errp
)
894 HDAAudioState
*a
= HDA_AUDIO(hda
);
895 const struct desc_codec
*desc
= µ_mixemu
;
898 desc
= µ_nomixemu
;
901 hda_audio_init(hda
, desc
, errp
);
904 static void hda_audio_base_class_init(ObjectClass
*klass
, void *data
)
906 DeviceClass
*dc
= DEVICE_CLASS(klass
);
907 HDACodecDeviceClass
*k
= HDA_CODEC_DEVICE_CLASS(klass
);
909 k
->exit
= hda_audio_exit
;
910 k
->command
= hda_audio_command
;
911 k
->stream
= hda_audio_stream
;
912 set_bit(DEVICE_CATEGORY_SOUND
, dc
->categories
);
913 dc
->reset
= hda_audio_reset
;
914 dc
->vmsd
= &vmstate_hda_audio
;
915 device_class_set_props(dc
, hda_audio_properties
);
918 static const TypeInfo hda_audio_info
= {
919 .name
= TYPE_HDA_AUDIO
,
920 .parent
= TYPE_HDA_CODEC_DEVICE
,
921 .instance_size
= sizeof(HDAAudioState
),
922 .class_init
= hda_audio_base_class_init
,
926 static void hda_audio_output_class_init(ObjectClass
*klass
, void *data
)
928 DeviceClass
*dc
= DEVICE_CLASS(klass
);
929 HDACodecDeviceClass
*k
= HDA_CODEC_DEVICE_CLASS(klass
);
931 k
->init
= hda_audio_init_output
;
932 dc
->desc
= "HDA Audio Codec, output-only (line-out)";
935 static const TypeInfo hda_audio_output_info
= {
936 .name
= "hda-output",
937 .parent
= TYPE_HDA_AUDIO
,
938 .class_init
= hda_audio_output_class_init
,
941 static void hda_audio_duplex_class_init(ObjectClass
*klass
, void *data
)
943 DeviceClass
*dc
= DEVICE_CLASS(klass
);
944 HDACodecDeviceClass
*k
= HDA_CODEC_DEVICE_CLASS(klass
);
946 k
->init
= hda_audio_init_duplex
;
947 dc
->desc
= "HDA Audio Codec, duplex (line-out, line-in)";
950 static const TypeInfo hda_audio_duplex_info
= {
951 .name
= "hda-duplex",
952 .parent
= TYPE_HDA_AUDIO
,
953 .class_init
= hda_audio_duplex_class_init
,
956 static void hda_audio_micro_class_init(ObjectClass
*klass
, void *data
)
958 DeviceClass
*dc
= DEVICE_CLASS(klass
);
959 HDACodecDeviceClass
*k
= HDA_CODEC_DEVICE_CLASS(klass
);
961 k
->init
= hda_audio_init_micro
;
962 dc
->desc
= "HDA Audio Codec, duplex (speaker, microphone)";
965 static const TypeInfo hda_audio_micro_info
= {
967 .parent
= TYPE_HDA_AUDIO
,
968 .class_init
= hda_audio_micro_class_init
,
971 static void hda_audio_register_types(void)
973 type_register_static(&hda_audio_info
);
974 type_register_static(&hda_audio_output_info
);
975 type_register_static(&hda_audio_duplex_info
);
976 type_register_static(&hda_audio_micro_info
);
979 type_init(hda_audio_register_types
)