hda: add hda-micro codec
It's identical to the hda-duplex codec, except that it advertises the input as microphone instead of line-in and the output as speaker instead of line-out. Some guest apps (microsoft netmeeting being one) are picky when it comes to selecting the recording source and don't accept line-in, so give them what they expect. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: malc <av1474@comtv.ru>
This commit is contained in:
parent
d0c2bbb9f0
commit
2011006569
143
hw/hda-audio.c
143
hw/hda-audio.c
|
@ -115,6 +115,7 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
|
|||
#define QEMU_HDA_ID_VENDOR 0x1af4
|
||||
#define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x10)
|
||||
#define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x20)
|
||||
#define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x30)
|
||||
|
||||
#define QEMU_HDA_PCM_FORMATS (AC_SUPPCM_BITS_16 | \
|
||||
0x1fc /* 16 -> 96 kHz */)
|
||||
|
@ -427,6 +428,117 @@ static const desc_codec duplex = {
|
|||
.nnodes = ARRAY_SIZE(duplex_nodes),
|
||||
};
|
||||
|
||||
/* micro: root node */
|
||||
static const desc_param micro_params_root[] = {
|
||||
{
|
||||
.id = AC_PAR_VENDOR_ID,
|
||||
.val = QEMU_HDA_ID_MICRO,
|
||||
},{
|
||||
.id = AC_PAR_SUBSYSTEM_ID,
|
||||
.val = QEMU_HDA_ID_MICRO,
|
||||
},{
|
||||
.id = AC_PAR_REV_ID,
|
||||
.val = 0x00100101,
|
||||
},{
|
||||
.id = AC_PAR_NODE_COUNT,
|
||||
.val = 0x00010001,
|
||||
},
|
||||
};
|
||||
|
||||
/* micro: audio function */
|
||||
static const desc_param micro_params_audio_func[] = {
|
||||
{
|
||||
.id = AC_PAR_FUNCTION_TYPE,
|
||||
.val = AC_GRP_AUDIO_FUNCTION,
|
||||
},{
|
||||
.id = AC_PAR_SUBSYSTEM_ID,
|
||||
.val = QEMU_HDA_ID_MICRO,
|
||||
},{
|
||||
.id = AC_PAR_NODE_COUNT,
|
||||
.val = 0x00020004,
|
||||
},{
|
||||
.id = AC_PAR_PCM,
|
||||
.val = QEMU_HDA_PCM_FORMATS,
|
||||
},{
|
||||
.id = AC_PAR_STREAM,
|
||||
.val = AC_SUPFMT_PCM,
|
||||
},{
|
||||
.id = AC_PAR_AMP_IN_CAP,
|
||||
.val = QEMU_HDA_AMP_NONE,
|
||||
},{
|
||||
.id = AC_PAR_AMP_OUT_CAP,
|
||||
.val = QEMU_HDA_AMP_NONE,
|
||||
},{
|
||||
.id = AC_PAR_GPIO_CAP,
|
||||
.val = 0,
|
||||
},{
|
||||
.id = AC_PAR_AUDIO_FG_CAP,
|
||||
.val = 0x00000808,
|
||||
},{
|
||||
.id = AC_PAR_POWER_STATE,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
/* micro: nodes */
|
||||
static const desc_node micro_nodes[] = {
|
||||
{
|
||||
.nid = AC_NODE_ROOT,
|
||||
.name = "root",
|
||||
.params = micro_params_root,
|
||||
.nparams = ARRAY_SIZE(micro_params_root),
|
||||
},{
|
||||
.nid = 1,
|
||||
.name = "func",
|
||||
.params = micro_params_audio_func,
|
||||
.nparams = ARRAY_SIZE(micro_params_audio_func),
|
||||
},{
|
||||
.nid = 2,
|
||||
.name = "dac",
|
||||
.params = common_params_audio_dac,
|
||||
.nparams = ARRAY_SIZE(common_params_audio_dac),
|
||||
.stindex = 0,
|
||||
},{
|
||||
.nid = 3,
|
||||
.name = "out",
|
||||
.params = common_params_audio_lineout,
|
||||
.nparams = ARRAY_SIZE(common_params_audio_lineout),
|
||||
.config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
|
||||
(AC_JACK_SPEAKER << AC_DEFCFG_DEVICE_SHIFT) |
|
||||
(AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
|
||||
(AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) |
|
||||
0x10),
|
||||
.pinctl = AC_PINCTL_OUT_EN,
|
||||
.conn = (uint32_t[]) { 2 },
|
||||
},{
|
||||
.nid = 4,
|
||||
.name = "adc",
|
||||
.params = common_params_audio_adc,
|
||||
.nparams = ARRAY_SIZE(common_params_audio_adc),
|
||||
.stindex = 1,
|
||||
.conn = (uint32_t[]) { 5 },
|
||||
},{
|
||||
.nid = 5,
|
||||
.name = "in",
|
||||
.params = common_params_audio_linein,
|
||||
.nparams = ARRAY_SIZE(common_params_audio_linein),
|
||||
.config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
|
||||
(AC_JACK_MIC_IN << AC_DEFCFG_DEVICE_SHIFT) |
|
||||
(AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
|
||||
(AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) |
|
||||
0x20),
|
||||
.pinctl = AC_PINCTL_IN_EN,
|
||||
}
|
||||
};
|
||||
|
||||
/* micro: codec */
|
||||
static const desc_codec micro = {
|
||||
.name = "micro",
|
||||
.iid = QEMU_HDA_ID_MICRO,
|
||||
.nodes = micro_nodes,
|
||||
.nnodes = ARRAY_SIZE(micro_nodes),
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static const char *fmt2name[] = {
|
||||
|
@ -906,6 +1018,11 @@ static int hda_audio_init_duplex(HDACodecDevice *hda)
|
|||
return hda_audio_init(hda, &duplex);
|
||||
}
|
||||
|
||||
static int hda_audio_init_micro(HDACodecDevice *hda)
|
||||
{
|
||||
return hda_audio_init(hda, µ);
|
||||
}
|
||||
|
||||
static void hda_audio_output_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
@ -915,7 +1032,7 @@ static void hda_audio_output_class_init(ObjectClass *klass, void *data)
|
|||
k->exit = hda_audio_exit;
|
||||
k->command = hda_audio_command;
|
||||
k->stream = hda_audio_stream;
|
||||
dc->desc = "HDA Audio Codec, output-only";
|
||||
dc->desc = "HDA Audio Codec, output-only (line-out)";
|
||||
dc->vmsd = &vmstate_hda_audio;
|
||||
dc->props = hda_audio_properties;
|
||||
}
|
||||
|
@ -936,7 +1053,7 @@ static void hda_audio_duplex_class_init(ObjectClass *klass, void *data)
|
|||
k->exit = hda_audio_exit;
|
||||
k->command = hda_audio_command;
|
||||
k->stream = hda_audio_stream;
|
||||
dc->desc = "HDA Audio Codec, duplex";
|
||||
dc->desc = "HDA Audio Codec, duplex (line-out, line-in)";
|
||||
dc->vmsd = &vmstate_hda_audio;
|
||||
dc->props = hda_audio_properties;
|
||||
}
|
||||
|
@ -948,10 +1065,32 @@ static TypeInfo hda_audio_duplex_info = {
|
|||
.class_init = hda_audio_duplex_class_init,
|
||||
};
|
||||
|
||||
static void hda_audio_micro_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
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;
|
||||
dc->desc = "HDA Audio Codec, duplex (speaker, microphone)";
|
||||
dc->vmsd = &vmstate_hda_audio;
|
||||
dc->props = hda_audio_properties;
|
||||
}
|
||||
|
||||
static TypeInfo hda_audio_micro_info = {
|
||||
.name = "hda-micro",
|
||||
.parent = TYPE_HDA_CODEC_DEVICE,
|
||||
.instance_size = sizeof(HDAAudioState),
|
||||
.class_init = hda_audio_micro_class_init,
|
||||
};
|
||||
|
||||
static void hda_audio_register_types(void)
|
||||
{
|
||||
type_register_static(&hda_audio_output_info);
|
||||
type_register_static(&hda_audio_duplex_info);
|
||||
type_register_static(&hda_audio_micro_info);
|
||||
}
|
||||
|
||||
type_init(hda_audio_register_types)
|
||||
|
|
Loading…
Reference in a new issue