diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2012-04-26 09:15:03 +0200 |
---|---|---|
committer | malc <av1474@comtv.ru> | 2012-04-26 12:54:17 +0400 |
commit | 201100656986735250ed4cd47be6b8a31c771763 (patch) | |
tree | 61c1292008d64cfea1c2f3f949b38d1476a15e0d /hw | |
parent | d0c2bbb9f04925eeda9948586aa382ccf68e26e7 (diff) |
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>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/hda-audio.c | 143 |
1 files changed, 141 insertions, 2 deletions
diff --git a/hw/hda-audio.c b/hw/hda-audio.c index 411be082ac..4e69c3c35c 100644 --- a/hw/hda-audio.c +++ b/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) |