From df578b15d519ce58656da73eeaee6176671a125c Mon Sep 17 00:00:00 2001
Message-Id: <df578b15d519ce58656da73eeaee6176671a125c.1345556225.git.minovotn@redhat.com>
In-Reply-To: <ec03d5b9f0ec383a962a49558156ddcf4734de59.1345556225.git.minovotn@redhat.com>
References: <ec03d5b9f0ec383a962a49558156ddcf4734de59.1345556225.git.minovotn@redhat.com>
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Mon, 9 Jul 2012 13:20:09 +0200
Subject: [PATCH 2/3] hda: add hda-micro codec

RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1341840010-30164-3-git-send-email-kraxel@redhat.com>
Patchwork-id: 40244
O-Subject: [RHEL-6.4 qemu-kvm PATCH 2/3] hda: add hda-micro codec
Bugzilla: 801063
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Hans de Goede <hdegoede@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>

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>
(cherry picked from commit 201100656986735250ed4cd47be6b8a31c771763)

Conflicts:

	hw/hda-audio.c  [ rhel6: undo qdev -> qom ]
---
 hw/hda-audio.c |  134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 132 insertions(+), 2 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 hw/hda-audio.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 132 insertions(+), 2 deletions(-)

diff --git a/hw/hda-audio.c b/hw/hda-audio.c
index de8aef8..14628c5 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[] = {
@@ -927,9 +1039,14 @@ 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, &micro);
+}
+
 static HDACodecDeviceInfo hda_audio_info_output = {
     .qdev.name    = "hda-output",
-    .qdev.desc    = "HDA Audio Codec, output-only",
+    .qdev.desc    = "HDA Audio Codec, output-only (line-out)",
     .qdev.size    = sizeof(HDAAudioState),
     .qdev.vmsd    = &vmstate_hda_audio,
     .qdev.props   = hda_audio_properties,
@@ -941,7 +1058,7 @@ static HDACodecDeviceInfo hda_audio_info_output = {
 
 static HDACodecDeviceInfo hda_audio_info_duplex = {
     .qdev.name    = "hda-duplex",
-    .qdev.desc    = "HDA Audio Codec, duplex",
+    .qdev.desc    = "HDA Audio Codec, duplex (line-out, line-in)",
     .qdev.size    = sizeof(HDAAudioState),
     .qdev.vmsd    = &vmstate_hda_audio,
     .qdev.props   = hda_audio_properties,
@@ -951,9 +1068,22 @@ static HDACodecDeviceInfo hda_audio_info_duplex = {
     .stream       = hda_audio_stream,
 };
 
+static HDACodecDeviceInfo hda_audio_info_micro = {
+    .qdev.name    = "hda-micro",
+    .qdev.desc    = "HDA Audio Codec, duplex (speaker, microphone)",
+    .qdev.size    = sizeof(HDAAudioState),
+    .qdev.vmsd    = &vmstate_hda_audio,
+    .qdev.props   = hda_audio_properties,
+    .init         = hda_audio_init_micro,
+    .exit         = hda_audio_exit,
+    .command      = hda_audio_command,
+    .stream       = hda_audio_stream,
+};
+
 static void hda_audio_register(void)
 {
     hda_codec_register(&hda_audio_info_output);
     hda_codec_register(&hda_audio_info_duplex);
+    hda_codec_register(&hda_audio_info_micro);
 }
 device_init(hda_audio_register);
-- 
1.7.11.2

