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_close_stream(HDAAudioState
*a
, HDAAudioStream
*st
)
477 if (st
->node
== NULL
) {
481 timer_free(st
->buft
);
485 AUD_close_out(&a
->card
, st
->voice
.out
);
486 st
->voice
.out
= NULL
;
488 AUD_close_in(&a
->card
, st
->voice
.in
);
493 static void hda_audio_setup(HDAAudioStream
*st
)
495 bool use_timer
= st
->state
->use_timer
;
496 audio_callback_fn cb
;
498 if (st
->node
== NULL
) {
502 trace_hda_audio_format(st
->node
->name
, st
->as
.nchannels
,
503 fmt2name
[st
->as
.fmt
], st
->as
.freq
);
505 hda_close_stream(st
->state
, st
);
508 cb
= hda_audio_output_cb
;
509 st
->buft
= timer_new_ns(QEMU_CLOCK_VIRTUAL
,
510 hda_audio_output_timer
, st
);
512 cb
= hda_audio_compat_output_cb
;
514 st
->voice
.out
= AUD_open_out(&st
->state
->card
, st
->voice
.out
,
515 st
->node
->name
, st
, cb
, &st
->as
);
518 cb
= hda_audio_input_cb
;
519 st
->buft
= timer_new_ns(QEMU_CLOCK_VIRTUAL
,
520 hda_audio_input_timer
, st
);
522 cb
= hda_audio_compat_input_cb
;
524 st
->voice
.in
= AUD_open_in(&st
->state
->card
, st
->voice
.in
,
525 st
->node
->name
, st
, cb
, &st
->as
);
529 static void hda_audio_command(HDACodecDevice
*hda
, uint32_t nid
, uint32_t data
)
531 HDAAudioState
*a
= HDA_AUDIO(hda
);
533 const desc_node
*node
= NULL
;
534 const desc_param
*param
;
535 uint32_t verb
, payload
, response
, count
, shift
;
537 if ((data
& 0x70000) == 0x70000) {
538 /* 12/8 id/payload */
539 verb
= (data
>> 8) & 0xfff;
540 payload
= data
& 0x00ff;
542 /* 4/16 id/payload */
543 verb
= (data
>> 8) & 0xf00;
544 payload
= data
& 0xffff;
547 node
= hda_codec_find_node(a
->desc
, nid
);
551 dprint(a
, 2, "%s: nid %d (%s), verb 0x%x, payload 0x%x\n",
552 __func__
, nid
, node
->name
, verb
, payload
);
556 case AC_VERB_PARAMETERS
:
557 param
= hda_codec_find_param(node
, payload
);
561 hda_codec_response(hda
, true, param
->val
);
563 case AC_VERB_GET_SUBSYSTEM_ID
:
564 hda_codec_response(hda
, true, a
->desc
->iid
);
568 case AC_VERB_GET_CONNECT_LIST
:
569 param
= hda_codec_find_param(node
, AC_PAR_CONNLIST_LEN
);
570 count
= param
? param
->val
: 0;
573 while (payload
< count
&& shift
< 32) {
574 response
|= node
->conn
[payload
] << shift
;
578 hda_codec_response(hda
, true, response
);
582 case AC_VERB_GET_CONFIG_DEFAULT
:
583 hda_codec_response(hda
, true, node
->config
);
585 case AC_VERB_GET_PIN_WIDGET_CONTROL
:
586 hda_codec_response(hda
, true, node
->pinctl
);
588 case AC_VERB_SET_PIN_WIDGET_CONTROL
:
589 if (node
->pinctl
!= payload
) {
590 dprint(a
, 1, "unhandled pin control bit\n");
592 hda_codec_response(hda
, true, 0);
595 /* audio in/out widget */
596 case AC_VERB_SET_CHANNEL_STREAMID
:
597 st
= a
->st
+ node
->stindex
;
598 if (st
->node
== NULL
) {
601 hda_audio_set_running(st
, false);
602 st
->stream
= (payload
>> 4) & 0x0f;
603 st
->channel
= payload
& 0x0f;
604 dprint(a
, 2, "%s: stream %d, channel %d\n",
605 st
->node
->name
, st
->stream
, st
->channel
);
606 hda_audio_set_running(st
, a
->running_real
[st
->output
* 16 + st
->stream
]);
607 hda_codec_response(hda
, true, 0);
609 case AC_VERB_GET_CONV
:
610 st
= a
->st
+ node
->stindex
;
611 if (st
->node
== NULL
) {
614 response
= st
->stream
<< 4 | st
->channel
;
615 hda_codec_response(hda
, true, response
);
617 case AC_VERB_SET_STREAM_FORMAT
:
618 st
= a
->st
+ node
->stindex
;
619 if (st
->node
== NULL
) {
622 st
->format
= payload
;
623 hda_codec_parse_fmt(st
->format
, &st
->as
);
625 hda_codec_response(hda
, true, 0);
627 case AC_VERB_GET_STREAM_FORMAT
:
628 st
= a
->st
+ node
->stindex
;
629 if (st
->node
== NULL
) {
632 hda_codec_response(hda
, true, st
->format
);
634 case AC_VERB_GET_AMP_GAIN_MUTE
:
635 st
= a
->st
+ node
->stindex
;
636 if (st
->node
== NULL
) {
639 if (payload
& AC_AMP_GET_LEFT
) {
640 response
= st
->gain_left
| (st
->mute_left
? AC_AMP_MUTE
: 0);
642 response
= st
->gain_right
| (st
->mute_right
? AC_AMP_MUTE
: 0);
644 hda_codec_response(hda
, true, response
);
646 case AC_VERB_SET_AMP_GAIN_MUTE
:
647 st
= a
->st
+ node
->stindex
;
648 if (st
->node
== NULL
) {
651 dprint(a
, 1, "amp (%s): %s%s%s%s index %d gain %3d %s\n",
653 (payload
& AC_AMP_SET_OUTPUT
) ? "o" : "-",
654 (payload
& AC_AMP_SET_INPUT
) ? "i" : "-",
655 (payload
& AC_AMP_SET_LEFT
) ? "l" : "-",
656 (payload
& AC_AMP_SET_RIGHT
) ? "r" : "-",
657 (payload
& AC_AMP_SET_INDEX
) >> AC_AMP_SET_INDEX_SHIFT
,
658 (payload
& AC_AMP_GAIN
),
659 (payload
& AC_AMP_MUTE
) ? "muted" : "");
660 if (payload
& AC_AMP_SET_LEFT
) {
661 st
->gain_left
= payload
& AC_AMP_GAIN
;
662 st
->mute_left
= payload
& AC_AMP_MUTE
;
664 if (payload
& AC_AMP_SET_RIGHT
) {
665 st
->gain_right
= payload
& AC_AMP_GAIN
;
666 st
->mute_right
= payload
& AC_AMP_MUTE
;
668 hda_audio_set_amp(st
);
669 hda_codec_response(hda
, true, 0);
673 case AC_VERB_SET_POWER_STATE
:
674 case AC_VERB_GET_POWER_STATE
:
675 case AC_VERB_GET_SDI_SELECT
:
676 hda_codec_response(hda
, true, 0);
684 dprint(a
, 1, "%s: not handled: nid %d (%s), verb 0x%x, payload 0x%x\n",
685 __func__
, nid
, node
? node
->name
: "?", verb
, payload
);
686 hda_codec_response(hda
, true, 0);
689 static void hda_audio_stream(HDACodecDevice
*hda
, uint32_t stnr
, bool running
, bool output
)
691 HDAAudioState
*a
= HDA_AUDIO(hda
);
694 a
->running_compat
[stnr
] = running
;
695 a
->running_real
[output
* 16 + stnr
] = running
;
696 for (s
= 0; s
< ARRAY_SIZE(a
->st
); s
++) {
697 if (a
->st
[s
].node
== NULL
) {
700 if (a
->st
[s
].output
!= output
) {
703 if (a
->st
[s
].stream
!= stnr
) {
706 hda_audio_set_running(&a
->st
[s
], running
);
710 static void hda_audio_init(HDACodecDevice
*hda
,
711 const struct desc_codec
*desc
,
714 HDAAudioState
*a
= HDA_AUDIO(hda
);
716 const desc_node
*node
;
717 const desc_param
*param
;
720 if (!AUD_register_card("hda", &a
->card
, errp
)) {
725 a
->name
= object_get_typename(OBJECT(a
));
726 dprint(a
, 1, "%s: cad %d\n", __func__
, a
->hda
.cad
);
728 for (i
= 0; i
< a
->desc
->nnodes
; i
++) {
729 node
= a
->desc
->nodes
+ i
;
730 param
= hda_codec_find_param(node
, AC_PAR_AUDIO_WIDGET_CAP
);
734 type
= (param
->val
& AC_WCAP_TYPE
) >> AC_WCAP_TYPE_SHIFT
;
738 assert(node
->stindex
< ARRAY_SIZE(a
->st
));
739 st
= a
->st
+ node
->stindex
;
742 if (type
== AC_WID_AUD_OUT
) {
743 /* unmute output by default */
744 st
->gain_left
= QEMU_HDA_AMP_STEPS
;
745 st
->gain_right
= QEMU_HDA_AMP_STEPS
;
746 st
->compat_bpos
= sizeof(st
->compat_buf
);
751 st
->format
= AC_FMT_TYPE_PCM
| AC_FMT_BITS_16
|
752 (1 << AC_FMT_CHAN_SHIFT
);
753 hda_codec_parse_fmt(st
->format
, &st
->as
);
760 static void hda_audio_exit(HDACodecDevice
*hda
)
762 HDAAudioState
*a
= HDA_AUDIO(hda
);
765 dprint(a
, 1, "%s\n", __func__
);
766 for (i
= 0; i
< ARRAY_SIZE(a
->st
); i
++) {
767 hda_close_stream(a
, a
->st
+ i
);
769 AUD_remove_card(&a
->card
);
772 static int hda_audio_post_load(void *opaque
, int version
)
774 HDAAudioState
*a
= opaque
;
778 dprint(a
, 1, "%s\n", __func__
);
780 /* assume running_compat[] is for output streams */
781 for (i
= 0; i
< ARRAY_SIZE(a
->running_compat
); i
++)
782 a
->running_real
[16 + i
] = a
->running_compat
[i
];
785 for (i
= 0; i
< ARRAY_SIZE(a
->st
); i
++) {
787 if (st
->node
== NULL
)
789 hda_codec_parse_fmt(st
->format
, &st
->as
);
791 hda_audio_set_amp(st
);
792 hda_audio_set_running(st
, a
->running_real
[st
->output
* 16 + st
->stream
]);
797 static void hda_audio_reset(DeviceState
*dev
)
799 HDAAudioState
*a
= HDA_AUDIO(dev
);
803 dprint(a
, 1, "%s\n", __func__
);
804 for (i
= 0; i
< ARRAY_SIZE(a
->st
); i
++) {
806 if (st
->node
!= NULL
) {
807 hda_audio_set_running(st
, false);
812 static bool vmstate_hda_audio_stream_buf_needed(void *opaque
)
814 HDAAudioStream
*st
= opaque
;
815 return st
->state
&& st
->state
->use_timer
;
818 static const VMStateDescription vmstate_hda_audio_stream_buf
= {
819 .name
= "hda-audio-stream/buffer",
821 .needed
= vmstate_hda_audio_stream_buf_needed
,
822 .fields
= (const VMStateField
[]) {
823 VMSTATE_BUFFER(buf
, HDAAudioStream
),
824 VMSTATE_INT64(rpos
, HDAAudioStream
),
825 VMSTATE_INT64(wpos
, HDAAudioStream
),
826 VMSTATE_TIMER_PTR(buft
, HDAAudioStream
),
827 VMSTATE_INT64(buft_start
, HDAAudioStream
),
828 VMSTATE_END_OF_LIST()
832 static const VMStateDescription vmstate_hda_audio_stream
= {
833 .name
= "hda-audio-stream",
835 .fields
= (const VMStateField
[]) {
836 VMSTATE_UINT32(stream
, HDAAudioStream
),
837 VMSTATE_UINT32(channel
, HDAAudioStream
),
838 VMSTATE_UINT32(format
, HDAAudioStream
),
839 VMSTATE_UINT32(gain_left
, HDAAudioStream
),
840 VMSTATE_UINT32(gain_right
, HDAAudioStream
),
841 VMSTATE_BOOL(mute_left
, HDAAudioStream
),
842 VMSTATE_BOOL(mute_right
, HDAAudioStream
),
843 VMSTATE_UINT32(compat_bpos
, HDAAudioStream
),
844 VMSTATE_BUFFER(compat_buf
, HDAAudioStream
),
845 VMSTATE_END_OF_LIST()
847 .subsections
= (const VMStateDescription
* const []) {
848 &vmstate_hda_audio_stream_buf
,
853 static const VMStateDescription vmstate_hda_audio
= {
856 .post_load
= hda_audio_post_load
,
857 .fields
= (const VMStateField
[]) {
858 VMSTATE_STRUCT_ARRAY(st
, HDAAudioState
, 4, 0,
859 vmstate_hda_audio_stream
,
861 VMSTATE_BOOL_ARRAY(running_compat
, HDAAudioState
, 16),
862 VMSTATE_BOOL_ARRAY_V(running_real
, HDAAudioState
, 2 * 16, 2),
863 VMSTATE_END_OF_LIST()
867 static Property hda_audio_properties
[] = {
868 DEFINE_AUDIO_PROPERTIES(HDAAudioState
, card
),
869 DEFINE_PROP_UINT32("debug", HDAAudioState
, debug
, 0),
870 DEFINE_PROP_BOOL("mixer", HDAAudioState
, mixer
, true),
871 DEFINE_PROP_BOOL("use-timer", HDAAudioState
, use_timer
, true),
872 DEFINE_PROP_END_OF_LIST(),
875 static void hda_audio_init_output(HDACodecDevice
*hda
, Error
**errp
)
877 HDAAudioState
*a
= HDA_AUDIO(hda
);
878 const struct desc_codec
*desc
= &output_mixemu
;
881 desc
= &output_nomixemu
;
884 hda_audio_init(hda
, desc
, errp
);
887 static void hda_audio_init_duplex(HDACodecDevice
*hda
, Error
**errp
)
889 HDAAudioState
*a
= HDA_AUDIO(hda
);
890 const struct desc_codec
*desc
= &duplex_mixemu
;
893 desc
= &duplex_nomixemu
;
896 hda_audio_init(hda
, desc
, errp
);
899 static void hda_audio_init_micro(HDACodecDevice
*hda
, Error
**errp
)
901 HDAAudioState
*a
= HDA_AUDIO(hda
);
902 const struct desc_codec
*desc
= µ_mixemu
;
905 desc
= µ_nomixemu
;
908 hda_audio_init(hda
, desc
, errp
);
911 static void hda_audio_base_class_init(ObjectClass
*klass
, void *data
)
913 DeviceClass
*dc
= DEVICE_CLASS(klass
);
914 HDACodecDeviceClass
*k
= HDA_CODEC_DEVICE_CLASS(klass
);
916 k
->exit
= hda_audio_exit
;
917 k
->command
= hda_audio_command
;
918 k
->stream
= hda_audio_stream
;
919 set_bit(DEVICE_CATEGORY_SOUND
, dc
->categories
);
920 device_class_set_legacy_reset(dc
, hda_audio_reset
);
921 dc
->vmsd
= &vmstate_hda_audio
;
922 device_class_set_props(dc
, hda_audio_properties
);
925 static const TypeInfo hda_audio_info
= {
926 .name
= TYPE_HDA_AUDIO
,
927 .parent
= TYPE_HDA_CODEC_DEVICE
,
928 .instance_size
= sizeof(HDAAudioState
),
929 .class_init
= hda_audio_base_class_init
,
933 static void hda_audio_output_class_init(ObjectClass
*klass
, void *data
)
935 DeviceClass
*dc
= DEVICE_CLASS(klass
);
936 HDACodecDeviceClass
*k
= HDA_CODEC_DEVICE_CLASS(klass
);
938 k
->init
= hda_audio_init_output
;
939 dc
->desc
= "HDA Audio Codec, output-only (line-out)";
942 static const TypeInfo hda_audio_output_info
= {
943 .name
= "hda-output",
944 .parent
= TYPE_HDA_AUDIO
,
945 .class_init
= hda_audio_output_class_init
,
948 static void hda_audio_duplex_class_init(ObjectClass
*klass
, void *data
)
950 DeviceClass
*dc
= DEVICE_CLASS(klass
);
951 HDACodecDeviceClass
*k
= HDA_CODEC_DEVICE_CLASS(klass
);
953 k
->init
= hda_audio_init_duplex
;
954 dc
->desc
= "HDA Audio Codec, duplex (line-out, line-in)";
957 static const TypeInfo hda_audio_duplex_info
= {
958 .name
= "hda-duplex",
959 .parent
= TYPE_HDA_AUDIO
,
960 .class_init
= hda_audio_duplex_class_init
,
963 static void hda_audio_micro_class_init(ObjectClass
*klass
, void *data
)
965 DeviceClass
*dc
= DEVICE_CLASS(klass
);
966 HDACodecDeviceClass
*k
= HDA_CODEC_DEVICE_CLASS(klass
);
968 k
->init
= hda_audio_init_micro
;
969 dc
->desc
= "HDA Audio Codec, duplex (speaker, microphone)";
972 static const TypeInfo hda_audio_micro_info
= {
974 .parent
= TYPE_HDA_AUDIO
,
975 .class_init
= hda_audio_micro_class_init
,
978 static void hda_audio_register_types(void)
980 type_register_static(&hda_audio_info
);
981 type_register_static(&hda_audio_output_info
);
982 type_register_static(&hda_audio_duplex_info
);
983 type_register_static(&hda_audio_micro_info
);
986 type_init(hda_audio_register_types
)