* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/pci/pci.h"
#include "intel-hda.h"
uint32_t bpos;
};
+#define TYPE_HDA_AUDIO "hda-audio"
+#define HDA_AUDIO(obj) OBJECT_CHECK(HDAAudioState, (obj), TYPE_HDA_AUDIO)
+
struct HDAAudioState {
HDACodecDevice hda;
const char *name;
left = left * 255 / QEMU_HDA_AMP_STEPS;
right = right * 255 / QEMU_HDA_AMP_STEPS;
+ if (!st->state->mixer) {
+ return;
+ }
if (st->output) {
AUD_set_volume_out(st->voice.out, muted, left, right);
} else {
static void hda_audio_command(HDACodecDevice *hda, uint32_t nid, uint32_t data)
{
- HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
+ HDAAudioState *a = HDA_AUDIO(hda);
HDAAudioStream *st;
const desc_node *node = NULL;
const desc_param *param;
static void hda_audio_stream(HDACodecDevice *hda, uint32_t stnr, bool running, bool output)
{
- HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
+ HDAAudioState *a = HDA_AUDIO(hda);
int s;
a->running_compat[stnr] = running;
static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
{
- HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
+ HDAAudioState *a = HDA_AUDIO(hda);
HDAAudioStream *st;
const desc_node *node;
const desc_param *param;
for (i = 0; i < a->desc->nnodes; i++) {
node = a->desc->nodes + i;
param = hda_codec_find_param(node, AC_PAR_AUDIO_WIDGET_CAP);
- if (NULL == param)
+ if (param == NULL) {
continue;
+ }
type = (param->val & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
switch (type) {
case AC_WID_AUD_OUT:
static int hda_audio_exit(HDACodecDevice *hda)
{
- HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
+ HDAAudioState *a = HDA_AUDIO(hda);
HDAAudioStream *st;
int i;
return 0;
}
+static void hda_audio_reset(DeviceState *dev)
+{
+ HDAAudioState *a = HDA_AUDIO(dev);
+ HDAAudioStream *st;
+ int i;
+
+ dprint(a, 1, "%s\n", __func__);
+ for (i = 0; i < ARRAY_SIZE(a->st); i++) {
+ st = a->st + i;
+ if (st->node != NULL) {
+ hda_audio_set_running(st, false);
+ }
+ }
+}
+
static const VMStateDescription vmstate_hda_audio_stream = {
.name = "hda-audio-stream",
.version_id = 1,
- .fields = (VMStateField []) {
+ .fields = (VMStateField[]) {
VMSTATE_UINT32(stream, HDAAudioStream),
VMSTATE_UINT32(channel, HDAAudioStream),
VMSTATE_UINT32(format, HDAAudioStream),
.name = "hda-audio",
.version_id = 2,
.post_load = hda_audio_post_load,
- .fields = (VMStateField []) {
+ .fields = (VMStateField[]) {
VMSTATE_STRUCT_ARRAY(st, HDAAudioState, 4, 0,
vmstate_hda_audio_stream,
HDAAudioStream),
static int hda_audio_init_output(HDACodecDevice *hda)
{
- HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
+ HDAAudioState *a = HDA_AUDIO(hda);
if (!a->mixer) {
return hda_audio_init(hda, &output_nomixemu);
static int hda_audio_init_duplex(HDACodecDevice *hda)
{
- HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
+ HDAAudioState *a = HDA_AUDIO(hda);
if (!a->mixer) {
return hda_audio_init(hda, &duplex_nomixemu);
static int hda_audio_init_micro(HDACodecDevice *hda)
{
- HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
+ HDAAudioState *a = HDA_AUDIO(hda);
if (!a->mixer) {
return hda_audio_init(hda, µ_nomixemu);
}
}
-static void hda_audio_output_class_init(ObjectClass *klass, void *data)
+static void hda_audio_base_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
- k->init = hda_audio_init_output;
k->exit = hda_audio_exit;
k->command = hda_audio_command;
k->stream = hda_audio_stream;
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
- dc->desc = "HDA Audio Codec, output-only (line-out)";
+ dc->reset = hda_audio_reset;
dc->vmsd = &vmstate_hda_audio;
dc->props = hda_audio_properties;
}
+static const TypeInfo hda_audio_info = {
+ .name = TYPE_HDA_AUDIO,
+ .parent = TYPE_HDA_CODEC_DEVICE,
+ .class_init = hda_audio_base_class_init,
+ .abstract = true,
+};
+
+static void hda_audio_output_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
+
+ k->init = hda_audio_init_output;
+ dc->desc = "HDA Audio Codec, output-only (line-out)";
+}
+
static const TypeInfo hda_audio_output_info = {
.name = "hda-output",
- .parent = TYPE_HDA_CODEC_DEVICE,
+ .parent = TYPE_HDA_AUDIO,
.instance_size = sizeof(HDAAudioState),
.class_init = hda_audio_output_class_init,
};
HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
k->init = hda_audio_init_duplex;
- k->exit = hda_audio_exit;
- k->command = hda_audio_command;
- k->stream = hda_audio_stream;
- set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "HDA Audio Codec, duplex (line-out, line-in)";
- dc->vmsd = &vmstate_hda_audio;
- dc->props = hda_audio_properties;
}
static const TypeInfo hda_audio_duplex_info = {
.name = "hda-duplex",
- .parent = TYPE_HDA_CODEC_DEVICE,
+ .parent = TYPE_HDA_AUDIO,
.instance_size = sizeof(HDAAudioState),
.class_init = hda_audio_duplex_class_init,
};
HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
k->init = hda_audio_init_micro;
- k->exit = hda_audio_exit;
- k->command = hda_audio_command;
- k->stream = hda_audio_stream;
- set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "HDA Audio Codec, duplex (speaker, microphone)";
- dc->vmsd = &vmstate_hda_audio;
- dc->props = hda_audio_properties;
}
static const TypeInfo hda_audio_micro_info = {
.name = "hda-micro",
- .parent = TYPE_HDA_CODEC_DEVICE,
+ .parent = TYPE_HDA_AUDIO,
.instance_size = sizeof(HDAAudioState),
.class_init = hda_audio_micro_class_init,
};
static void hda_audio_register_types(void)
{
+ type_register_static(&hda_audio_info);
type_register_static(&hda_audio_output_info);
type_register_static(&hda_audio_duplex_info);
type_register_static(&hda_audio_micro_info);