~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/hda-audio.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn, Serge Hallyn, Adam Conrad
  • Date: 2013-01-04 08:50:24 UTC
  • mfrom: (1.6.6) (10.1.29 sid)
  • Revision ID: package-import@ubuntu.com-20130104085024-k4mr3z3zzjxemww2
Tags: 1.2.0.dfsg-1~exp1-0ubuntu1
[ Serge Hallyn ]
* debian/control:
  - update maintainer
  - remove vde2 recommends
  - build-deps: remove libusbredir, libvdeplug2-dev,
    libspice-server-dev, libspice-protocol-dev, libiscsi-dev,
    and libxen-dev.
  - qemu-keymaps: break/replace qemu-common
  - qemu-system:
    - break/replace qemu-common
    - depend on udev
    - remove openbios-ppc, openbios-sparc, and openhackware from
      Depends.  (Intend to add them back once we can build them.)
    - provides: qemu-kvm
  - qemu-utils: break/replace qemu-kvm
  - set up transitional packages for qemu-kvm, qemu-common, and kvm.
* debian/rules:
  - install kvm-ifup and kvm-ifdown
  - dh_installinit the qemu-kvm upstart job
* install a 30-qemu-kvm.conf into /etc/sysctl.c for nr_hugepages.
* qemu-kvm.upstart:
  - add qemu-system.qemu-kvm.upstart
  - add mv_confile to qemu-system.preinst, postinst, and .postrm to rename
    /etc/init/qemu-kvm.conf to qemu-system.conf
  - debian/rules: add dh_installinit to get qemu-system.upstart installed.
  - take the defaults from the old qemu-kvm.defaults, and move them into
    the upstart job
* debian/patches:
  - apply gridcentric patches from lp:~amscanne/+junk/gridcentric-qemu-patches
  - apply arm patches from git://git.linaro.org/qemu/qemu-linaro.git
  - apply nbd-fixes-to-read-only-handling.patch from upstream to
    make read-write mount after read-only mount work.  (LP: #1077838)
* ifup/down:
  - copy Ubuntu qemu-kvm's kvm-ifup/down into debian/
  - fix dh_install for kvm-ifup/down in debian/rules
  - add links for qemu-ifup/down in qemu-system.links
  - remove (debian's original) qemu-ifup from qemu-system.install
* debian/qemu-system.postinst
  - udevadm trigger to fix up /dev/kvm perms
  - make the 'qemu' symlink point to qemu-system-x86_64, not -i386.
* debian/qemu-system.links:
  - point 'kvm' to qemu-system-x86_64
  - remove pxe-virtio, pxe-e1000 and pxe-rtl8139 links (which conflict
    with ones from kvm-ipxe).  We may want to move the links from kvm-ipxe
    back to qemu-system at some point.
  - add qemu-ifdown and qemu-ifup links
* debian/qemu-system.install:
  - remove /etc/qemu-ifup link
  - add /etc/sysctl.d/30-qemu-kvm.conf

[ Adam Conrad ]
* Appease apt-get's dist-upgrade resolver by creating a qemu-common
  transitional package to upgrade more gracefully to qemu-keymaps.
* Move all the empty transitional packages to the oldlibs section. 
* Restore the versioned dep from qemu-kvm (and kvm) to qemu-system.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010 Red Hat, Inc.
 
3
 *
 
4
 * written by Gerd Hoffmann <kraxel@redhat.com>
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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/>.
 
18
 */
 
19
 
 
20
#include "hw.h"
 
21
#include "pci.h"
 
22
#include "intel-hda.h"
 
23
#include "intel-hda-defs.h"
 
24
#include "audio/audio.h"
 
25
 
 
26
/* -------------------------------------------------------------------------- */
 
27
 
 
28
typedef struct desc_param {
 
29
    uint32_t id;
 
30
    uint32_t val;
 
31
} desc_param;
 
32
 
 
33
typedef struct desc_node {
 
34
    uint32_t nid;
 
35
    const char *name;
 
36
    const desc_param *params;
 
37
    uint32_t nparams;
 
38
    uint32_t config;
 
39
    uint32_t pinctl;
 
40
    uint32_t *conn;
 
41
    uint32_t stindex;
 
42
} desc_node;
 
43
 
 
44
typedef struct desc_codec {
 
45
    const char *name;
 
46
    uint32_t iid;
 
47
    const desc_node *nodes;
 
48
    uint32_t nnodes;
 
49
} desc_codec;
 
50
 
 
51
static const desc_param* hda_codec_find_param(const desc_node *node, uint32_t id)
 
52
{
 
53
    int i;
 
54
 
 
55
    for (i = 0; i < node->nparams; i++) {
 
56
        if (node->params[i].id == id) {
 
57
            return &node->params[i];
 
58
        }
 
59
    }
 
60
    return NULL;
 
61
}
 
62
 
 
63
static const desc_node* hda_codec_find_node(const desc_codec *codec, uint32_t nid)
 
64
{
 
65
    int i;
 
66
 
 
67
    for (i = 0; i < codec->nnodes; i++) {
 
68
        if (codec->nodes[i].nid == nid) {
 
69
            return &codec->nodes[i];
 
70
        }
 
71
    }
 
72
    return NULL;
 
73
}
 
74
 
 
75
static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
 
76
{
 
77
    if (format & AC_FMT_TYPE_NON_PCM) {
 
78
        return;
 
79
    }
 
80
 
 
81
    as->freq = (format & AC_FMT_BASE_44K) ? 44100 : 48000;
 
82
 
 
83
    switch ((format & AC_FMT_MULT_MASK) >> AC_FMT_MULT_SHIFT) {
 
84
    case 1: as->freq *= 2; break;
 
85
    case 2: as->freq *= 3; break;
 
86
    case 3: as->freq *= 4; break;
 
87
    }
 
88
 
 
89
    switch ((format & AC_FMT_DIV_MASK) >> AC_FMT_DIV_SHIFT) {
 
90
    case 1: as->freq /= 2; break;
 
91
    case 2: as->freq /= 3; break;
 
92
    case 3: as->freq /= 4; break;
 
93
    case 4: as->freq /= 5; break;
 
94
    case 5: as->freq /= 6; break;
 
95
    case 6: as->freq /= 7; break;
 
96
    case 7: as->freq /= 8; break;
 
97
    }
 
98
 
 
99
    switch (format & AC_FMT_BITS_MASK) {
 
100
    case AC_FMT_BITS_8:  as->fmt = AUD_FMT_S8;  break;
 
101
    case AC_FMT_BITS_16: as->fmt = AUD_FMT_S16; break;
 
102
    case AC_FMT_BITS_32: as->fmt = AUD_FMT_S32; break;
 
103
    }
 
104
 
 
105
    as->nchannels = ((format & AC_FMT_CHAN_MASK) >> AC_FMT_CHAN_SHIFT) + 1;
 
106
}
 
107
 
 
108
/* -------------------------------------------------------------------------- */
 
109
/*
 
110
 * HDA codec descriptions
 
111
 */
 
112
 
 
113
/* some defines */
 
114
 
 
115
#define QEMU_HDA_ID_VENDOR  0x1af4
 
116
#define QEMU_HDA_PCM_FORMATS (AC_SUPPCM_BITS_16 |       \
 
117
                              0x1fc /* 16 -> 96 kHz */)
 
118
#define QEMU_HDA_AMP_NONE    (0)
 
119
#define QEMU_HDA_AMP_STEPS   0x4a
 
120
 
 
121
#ifdef CONFIG_MIXEMU
 
122
# define QEMU_HDA_ID_OUTPUT  ((QEMU_HDA_ID_VENDOR << 16) | 0x12)
 
123
# define QEMU_HDA_ID_DUPLEX  ((QEMU_HDA_ID_VENDOR << 16) | 0x22)
 
124
# define QEMU_HDA_ID_MICRO   ((QEMU_HDA_ID_VENDOR << 16) | 0x32)
 
125
# define QEMU_HDA_AMP_CAPS                                              \
 
126
    (AC_AMPCAP_MUTE |                                                   \
 
127
     (QEMU_HDA_AMP_STEPS << AC_AMPCAP_OFFSET_SHIFT)    |                \
 
128
     (QEMU_HDA_AMP_STEPS << AC_AMPCAP_NUM_STEPS_SHIFT) |                \
 
129
     (3                  << AC_AMPCAP_STEP_SIZE_SHIFT))
 
130
#else
 
131
# define QEMU_HDA_ID_OUTPUT  ((QEMU_HDA_ID_VENDOR << 16) | 0x11)
 
132
# define QEMU_HDA_ID_DUPLEX  ((QEMU_HDA_ID_VENDOR << 16) | 0x21)
 
133
# define QEMU_HDA_ID_MICRO   ((QEMU_HDA_ID_VENDOR << 16) | 0x31)
 
134
# define QEMU_HDA_AMP_CAPS   QEMU_HDA_AMP_NONE
 
135
#endif
 
136
 
 
137
/* common: audio output widget */
 
138
static const desc_param common_params_audio_dac[] = {
 
139
    {
 
140
        .id  = AC_PAR_AUDIO_WIDGET_CAP,
 
141
        .val = ((AC_WID_AUD_OUT << AC_WCAP_TYPE_SHIFT) |
 
142
                AC_WCAP_FORMAT_OVRD |
 
143
                AC_WCAP_AMP_OVRD |
 
144
                AC_WCAP_OUT_AMP |
 
145
                AC_WCAP_STEREO),
 
146
    },{
 
147
        .id  = AC_PAR_PCM,
 
148
        .val = QEMU_HDA_PCM_FORMATS,
 
149
    },{
 
150
        .id  = AC_PAR_STREAM,
 
151
        .val = AC_SUPFMT_PCM,
 
152
    },{
 
153
        .id  = AC_PAR_AMP_IN_CAP,
 
154
        .val = QEMU_HDA_AMP_NONE,
 
155
    },{
 
156
        .id  = AC_PAR_AMP_OUT_CAP,
 
157
        .val = QEMU_HDA_AMP_CAPS,
 
158
    },
 
159
};
 
160
 
 
161
/* common: audio input widget */
 
162
static const desc_param common_params_audio_adc[] = {
 
163
    {
 
164
        .id  = AC_PAR_AUDIO_WIDGET_CAP,
 
165
        .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) |
 
166
                AC_WCAP_CONN_LIST |
 
167
                AC_WCAP_FORMAT_OVRD |
 
168
                AC_WCAP_AMP_OVRD |
 
169
                AC_WCAP_IN_AMP |
 
170
                AC_WCAP_STEREO),
 
171
    },{
 
172
        .id  = AC_PAR_CONNLIST_LEN,
 
173
        .val = 1,
 
174
    },{
 
175
        .id  = AC_PAR_PCM,
 
176
        .val = QEMU_HDA_PCM_FORMATS,
 
177
    },{
 
178
        .id  = AC_PAR_STREAM,
 
179
        .val = AC_SUPFMT_PCM,
 
180
    },{
 
181
        .id  = AC_PAR_AMP_IN_CAP,
 
182
        .val = QEMU_HDA_AMP_CAPS,
 
183
    },{
 
184
        .id  = AC_PAR_AMP_OUT_CAP,
 
185
        .val = QEMU_HDA_AMP_NONE,
 
186
    },
 
187
};
 
188
 
 
189
/* common: pin widget (line-out) */
 
190
static const desc_param common_params_audio_lineout[] = {
 
191
    {
 
192
        .id  = AC_PAR_AUDIO_WIDGET_CAP,
 
193
        .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
 
194
                AC_WCAP_CONN_LIST |
 
195
                AC_WCAP_STEREO),
 
196
    },{
 
197
        .id  = AC_PAR_PIN_CAP,
 
198
        .val = AC_PINCAP_OUT,
 
199
    },{
 
200
        .id  = AC_PAR_CONNLIST_LEN,
 
201
        .val = 1,
 
202
    },{
 
203
        .id  = AC_PAR_AMP_IN_CAP,
 
204
        .val = QEMU_HDA_AMP_NONE,
 
205
    },{
 
206
        .id  = AC_PAR_AMP_OUT_CAP,
 
207
        .val = QEMU_HDA_AMP_NONE,
 
208
    },
 
209
};
 
210
 
 
211
/* common: pin widget (line-in) */
 
212
static const desc_param common_params_audio_linein[] = {
 
213
    {
 
214
        .id  = AC_PAR_AUDIO_WIDGET_CAP,
 
215
        .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) |
 
216
                AC_WCAP_STEREO),
 
217
    },{
 
218
        .id  = AC_PAR_PIN_CAP,
 
219
        .val = AC_PINCAP_IN,
 
220
    },{
 
221
        .id  = AC_PAR_AMP_IN_CAP,
 
222
        .val = QEMU_HDA_AMP_NONE,
 
223
    },{
 
224
        .id  = AC_PAR_AMP_OUT_CAP,
 
225
        .val = QEMU_HDA_AMP_NONE,
 
226
    },
 
227
};
 
228
 
 
229
/* output: root node */
 
230
static const desc_param output_params_root[] = {
 
231
    {
 
232
        .id  = AC_PAR_VENDOR_ID,
 
233
        .val = QEMU_HDA_ID_OUTPUT,
 
234
    },{
 
235
        .id  = AC_PAR_SUBSYSTEM_ID,
 
236
        .val = QEMU_HDA_ID_OUTPUT,
 
237
    },{
 
238
        .id  = AC_PAR_REV_ID,
 
239
        .val = 0x00100101,
 
240
    },{
 
241
        .id  = AC_PAR_NODE_COUNT,
 
242
        .val = 0x00010001,
 
243
    },
 
244
};
 
245
 
 
246
/* output: audio function */
 
247
static const desc_param output_params_audio_func[] = {
 
248
    {
 
249
        .id  = AC_PAR_FUNCTION_TYPE,
 
250
        .val = AC_GRP_AUDIO_FUNCTION,
 
251
    },{
 
252
        .id  = AC_PAR_SUBSYSTEM_ID,
 
253
        .val = QEMU_HDA_ID_OUTPUT,
 
254
    },{
 
255
        .id  = AC_PAR_NODE_COUNT,
 
256
        .val = 0x00020002,
 
257
    },{
 
258
        .id  = AC_PAR_PCM,
 
259
        .val = QEMU_HDA_PCM_FORMATS,
 
260
    },{
 
261
        .id  = AC_PAR_STREAM,
 
262
        .val = AC_SUPFMT_PCM,
 
263
    },{
 
264
        .id  = AC_PAR_AMP_IN_CAP,
 
265
        .val = QEMU_HDA_AMP_NONE,
 
266
    },{
 
267
        .id  = AC_PAR_AMP_OUT_CAP,
 
268
        .val = QEMU_HDA_AMP_NONE,
 
269
    },{
 
270
        .id  = AC_PAR_GPIO_CAP,
 
271
        .val = 0,
 
272
    },{
 
273
        .id  = AC_PAR_AUDIO_FG_CAP,
 
274
        .val = 0x00000808,
 
275
    },{
 
276
        .id  = AC_PAR_POWER_STATE,
 
277
        .val = 0,
 
278
    },
 
279
};
 
280
 
 
281
/* output: nodes */
 
282
static const desc_node output_nodes[] = {
 
283
    {
 
284
        .nid     = AC_NODE_ROOT,
 
285
        .name    = "root",
 
286
        .params  = output_params_root,
 
287
        .nparams = ARRAY_SIZE(output_params_root),
 
288
    },{
 
289
        .nid     = 1,
 
290
        .name    = "func",
 
291
        .params  = output_params_audio_func,
 
292
        .nparams = ARRAY_SIZE(output_params_audio_func),
 
293
    },{
 
294
        .nid     = 2,
 
295
        .name    = "dac",
 
296
        .params  = common_params_audio_dac,
 
297
        .nparams = ARRAY_SIZE(common_params_audio_dac),
 
298
        .stindex = 0,
 
299
    },{
 
300
        .nid     = 3,
 
301
        .name    = "out",
 
302
        .params  = common_params_audio_lineout,
 
303
        .nparams = ARRAY_SIZE(common_params_audio_lineout),
 
304
        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
 
305
                    (AC_JACK_LINE_OUT     << AC_DEFCFG_DEVICE_SHIFT)    |
 
306
                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
 
307
                    (AC_JACK_COLOR_GREEN  << AC_DEFCFG_COLOR_SHIFT)     |
 
308
                    0x10),
 
309
        .pinctl  = AC_PINCTL_OUT_EN,
 
310
        .conn    = (uint32_t[]) { 2 },
 
311
    }
 
312
};
 
313
 
 
314
/* output: codec */
 
315
static const desc_codec output = {
 
316
    .name   = "output",
 
317
    .iid    = QEMU_HDA_ID_OUTPUT,
 
318
    .nodes  = output_nodes,
 
319
    .nnodes = ARRAY_SIZE(output_nodes),
 
320
};
 
321
 
 
322
/* duplex: root node */
 
323
static const desc_param duplex_params_root[] = {
 
324
    {
 
325
        .id  = AC_PAR_VENDOR_ID,
 
326
        .val = QEMU_HDA_ID_DUPLEX,
 
327
    },{
 
328
        .id  = AC_PAR_SUBSYSTEM_ID,
 
329
        .val = QEMU_HDA_ID_DUPLEX,
 
330
    },{
 
331
        .id  = AC_PAR_REV_ID,
 
332
        .val = 0x00100101,
 
333
    },{
 
334
        .id  = AC_PAR_NODE_COUNT,
 
335
        .val = 0x00010001,
 
336
    },
 
337
};
 
338
 
 
339
/* duplex: audio function */
 
340
static const desc_param duplex_params_audio_func[] = {
 
341
    {
 
342
        .id  = AC_PAR_FUNCTION_TYPE,
 
343
        .val = AC_GRP_AUDIO_FUNCTION,
 
344
    },{
 
345
        .id  = AC_PAR_SUBSYSTEM_ID,
 
346
        .val = QEMU_HDA_ID_DUPLEX,
 
347
    },{
 
348
        .id  = AC_PAR_NODE_COUNT,
 
349
        .val = 0x00020004,
 
350
    },{
 
351
        .id  = AC_PAR_PCM,
 
352
        .val = QEMU_HDA_PCM_FORMATS,
 
353
    },{
 
354
        .id  = AC_PAR_STREAM,
 
355
        .val = AC_SUPFMT_PCM,
 
356
    },{
 
357
        .id  = AC_PAR_AMP_IN_CAP,
 
358
        .val = QEMU_HDA_AMP_NONE,
 
359
    },{
 
360
        .id  = AC_PAR_AMP_OUT_CAP,
 
361
        .val = QEMU_HDA_AMP_NONE,
 
362
    },{
 
363
        .id  = AC_PAR_GPIO_CAP,
 
364
        .val = 0,
 
365
    },{
 
366
        .id  = AC_PAR_AUDIO_FG_CAP,
 
367
        .val = 0x00000808,
 
368
    },{
 
369
        .id  = AC_PAR_POWER_STATE,
 
370
        .val = 0,
 
371
    },
 
372
};
 
373
 
 
374
/* duplex: nodes */
 
375
static const desc_node duplex_nodes[] = {
 
376
    {
 
377
        .nid     = AC_NODE_ROOT,
 
378
        .name    = "root",
 
379
        .params  = duplex_params_root,
 
380
        .nparams = ARRAY_SIZE(duplex_params_root),
 
381
    },{
 
382
        .nid     = 1,
 
383
        .name    = "func",
 
384
        .params  = duplex_params_audio_func,
 
385
        .nparams = ARRAY_SIZE(duplex_params_audio_func),
 
386
    },{
 
387
        .nid     = 2,
 
388
        .name    = "dac",
 
389
        .params  = common_params_audio_dac,
 
390
        .nparams = ARRAY_SIZE(common_params_audio_dac),
 
391
        .stindex = 0,
 
392
    },{
 
393
        .nid     = 3,
 
394
        .name    = "out",
 
395
        .params  = common_params_audio_lineout,
 
396
        .nparams = ARRAY_SIZE(common_params_audio_lineout),
 
397
        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
 
398
                    (AC_JACK_LINE_OUT     << AC_DEFCFG_DEVICE_SHIFT)    |
 
399
                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
 
400
                    (AC_JACK_COLOR_GREEN  << AC_DEFCFG_COLOR_SHIFT)     |
 
401
                    0x10),
 
402
        .pinctl  = AC_PINCTL_OUT_EN,
 
403
        .conn    = (uint32_t[]) { 2 },
 
404
    },{
 
405
        .nid     = 4,
 
406
        .name    = "adc",
 
407
        .params  = common_params_audio_adc,
 
408
        .nparams = ARRAY_SIZE(common_params_audio_adc),
 
409
        .stindex = 1,
 
410
        .conn    = (uint32_t[]) { 5 },
 
411
    },{
 
412
        .nid     = 5,
 
413
        .name    = "in",
 
414
        .params  = common_params_audio_linein,
 
415
        .nparams = ARRAY_SIZE(common_params_audio_linein),
 
416
        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
 
417
                    (AC_JACK_LINE_IN      << AC_DEFCFG_DEVICE_SHIFT)    |
 
418
                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
 
419
                    (AC_JACK_COLOR_RED    << AC_DEFCFG_COLOR_SHIFT)     |
 
420
                    0x20),
 
421
        .pinctl  = AC_PINCTL_IN_EN,
 
422
    }
 
423
};
 
424
 
 
425
/* duplex: codec */
 
426
static const desc_codec duplex = {
 
427
    .name   = "duplex",
 
428
    .iid    = QEMU_HDA_ID_DUPLEX,
 
429
    .nodes  = duplex_nodes,
 
430
    .nnodes = ARRAY_SIZE(duplex_nodes),
 
431
};
 
432
 
 
433
/* micro: root node */
 
434
static const desc_param micro_params_root[] = {
 
435
    {
 
436
        .id  = AC_PAR_VENDOR_ID,
 
437
        .val = QEMU_HDA_ID_MICRO,
 
438
    },{
 
439
        .id  = AC_PAR_SUBSYSTEM_ID,
 
440
        .val = QEMU_HDA_ID_MICRO,
 
441
    },{
 
442
        .id  = AC_PAR_REV_ID,
 
443
        .val = 0x00100101,
 
444
    },{
 
445
        .id  = AC_PAR_NODE_COUNT,
 
446
        .val = 0x00010001,
 
447
    },
 
448
};
 
449
 
 
450
/* micro: audio function */
 
451
static const desc_param micro_params_audio_func[] = {
 
452
    {
 
453
        .id  = AC_PAR_FUNCTION_TYPE,
 
454
        .val = AC_GRP_AUDIO_FUNCTION,
 
455
    },{
 
456
        .id  = AC_PAR_SUBSYSTEM_ID,
 
457
        .val = QEMU_HDA_ID_MICRO,
 
458
    },{
 
459
        .id  = AC_PAR_NODE_COUNT,
 
460
        .val = 0x00020004,
 
461
    },{
 
462
        .id  = AC_PAR_PCM,
 
463
        .val = QEMU_HDA_PCM_FORMATS,
 
464
    },{
 
465
        .id  = AC_PAR_STREAM,
 
466
        .val = AC_SUPFMT_PCM,
 
467
    },{
 
468
        .id  = AC_PAR_AMP_IN_CAP,
 
469
        .val = QEMU_HDA_AMP_NONE,
 
470
    },{
 
471
        .id  = AC_PAR_AMP_OUT_CAP,
 
472
        .val = QEMU_HDA_AMP_NONE,
 
473
    },{
 
474
        .id  = AC_PAR_GPIO_CAP,
 
475
        .val = 0,
 
476
    },{
 
477
        .id  = AC_PAR_AUDIO_FG_CAP,
 
478
        .val = 0x00000808,
 
479
    },{
 
480
        .id  = AC_PAR_POWER_STATE,
 
481
        .val = 0,
 
482
    },
 
483
};
 
484
 
 
485
/* micro: nodes */
 
486
static const desc_node micro_nodes[] = {
 
487
    {
 
488
        .nid     = AC_NODE_ROOT,
 
489
        .name    = "root",
 
490
        .params  = micro_params_root,
 
491
        .nparams = ARRAY_SIZE(micro_params_root),
 
492
    },{
 
493
        .nid     = 1,
 
494
        .name    = "func",
 
495
        .params  = micro_params_audio_func,
 
496
        .nparams = ARRAY_SIZE(micro_params_audio_func),
 
497
    },{
 
498
        .nid     = 2,
 
499
        .name    = "dac",
 
500
        .params  = common_params_audio_dac,
 
501
        .nparams = ARRAY_SIZE(common_params_audio_dac),
 
502
        .stindex = 0,
 
503
    },{
 
504
        .nid     = 3,
 
505
        .name    = "out",
 
506
        .params  = common_params_audio_lineout,
 
507
        .nparams = ARRAY_SIZE(common_params_audio_lineout),
 
508
        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
 
509
                    (AC_JACK_SPEAKER      << AC_DEFCFG_DEVICE_SHIFT)    |
 
510
                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
 
511
                    (AC_JACK_COLOR_GREEN  << AC_DEFCFG_COLOR_SHIFT)     |
 
512
                    0x10),
 
513
        .pinctl  = AC_PINCTL_OUT_EN,
 
514
        .conn    = (uint32_t[]) { 2 },
 
515
    },{
 
516
        .nid     = 4,
 
517
        .name    = "adc",
 
518
        .params  = common_params_audio_adc,
 
519
        .nparams = ARRAY_SIZE(common_params_audio_adc),
 
520
        .stindex = 1,
 
521
        .conn    = (uint32_t[]) { 5 },
 
522
    },{
 
523
        .nid     = 5,
 
524
        .name    = "in",
 
525
        .params  = common_params_audio_linein,
 
526
        .nparams = ARRAY_SIZE(common_params_audio_linein),
 
527
        .config  = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) |
 
528
                    (AC_JACK_MIC_IN       << AC_DEFCFG_DEVICE_SHIFT)    |
 
529
                    (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) |
 
530
                    (AC_JACK_COLOR_RED    << AC_DEFCFG_COLOR_SHIFT)     |
 
531
                    0x20),
 
532
        .pinctl  = AC_PINCTL_IN_EN,
 
533
    }
 
534
};
 
535
 
 
536
/* micro: codec */
 
537
static const desc_codec micro = {
 
538
    .name   = "micro",
 
539
    .iid    = QEMU_HDA_ID_MICRO,
 
540
    .nodes  = micro_nodes,
 
541
    .nnodes = ARRAY_SIZE(micro_nodes),
 
542
};
 
543
 
 
544
/* -------------------------------------------------------------------------- */
 
545
 
 
546
static const char *fmt2name[] = {
 
547
    [ AUD_FMT_U8  ] = "PCM-U8",
 
548
    [ AUD_FMT_S8  ] = "PCM-S8",
 
549
    [ AUD_FMT_U16 ] = "PCM-U16",
 
550
    [ AUD_FMT_S16 ] = "PCM-S16",
 
551
    [ AUD_FMT_U32 ] = "PCM-U32",
 
552
    [ AUD_FMT_S32 ] = "PCM-S32",
 
553
};
 
554
 
 
555
typedef struct HDAAudioState HDAAudioState;
 
556
typedef struct HDAAudioStream HDAAudioStream;
 
557
 
 
558
struct HDAAudioStream {
 
559
    HDAAudioState *state;
 
560
    const desc_node *node;
 
561
    bool output, running;
 
562
    uint32_t stream;
 
563
    uint32_t channel;
 
564
    uint32_t format;
 
565
    uint32_t gain_left, gain_right;
 
566
    bool mute_left, mute_right;
 
567
    struct audsettings as;
 
568
    union {
 
569
        SWVoiceIn *in;
 
570
        SWVoiceOut *out;
 
571
    } voice;
 
572
    uint8_t buf[HDA_BUFFER_SIZE];
 
573
    uint32_t bpos;
 
574
};
 
575
 
 
576
struct HDAAudioState {
 
577
    HDACodecDevice hda;
 
578
    const char *name;
 
579
 
 
580
    QEMUSoundCard card;
 
581
    const desc_codec *desc;
 
582
    HDAAudioStream st[4];
 
583
    bool running_compat[16];
 
584
    bool running_real[2 * 16];
 
585
 
 
586
    /* properties */
 
587
    uint32_t debug;
 
588
};
 
589
 
 
590
static void hda_audio_input_cb(void *opaque, int avail)
 
591
{
 
592
    HDAAudioStream *st = opaque;
 
593
    int recv = 0;
 
594
    int len;
 
595
    bool rc;
 
596
 
 
597
    while (avail - recv >= sizeof(st->buf)) {
 
598
        if (st->bpos != sizeof(st->buf)) {
 
599
            len = AUD_read(st->voice.in, st->buf + st->bpos,
 
600
                           sizeof(st->buf) - st->bpos);
 
601
            st->bpos += len;
 
602
            recv += len;
 
603
            if (st->bpos != sizeof(st->buf)) {
 
604
                break;
 
605
            }
 
606
        }
 
607
        rc = hda_codec_xfer(&st->state->hda, st->stream, false,
 
608
                            st->buf, sizeof(st->buf));
 
609
        if (!rc) {
 
610
            break;
 
611
        }
 
612
        st->bpos = 0;
 
613
    }
 
614
}
 
615
 
 
616
static void hda_audio_output_cb(void *opaque, int avail)
 
617
{
 
618
    HDAAudioStream *st = opaque;
 
619
    int sent = 0;
 
620
    int len;
 
621
    bool rc;
 
622
 
 
623
    while (avail - sent >= sizeof(st->buf)) {
 
624
        if (st->bpos == sizeof(st->buf)) {
 
625
            rc = hda_codec_xfer(&st->state->hda, st->stream, true,
 
626
                                st->buf, sizeof(st->buf));
 
627
            if (!rc) {
 
628
                break;
 
629
            }
 
630
            st->bpos = 0;
 
631
        }
 
632
        len = AUD_write(st->voice.out, st->buf + st->bpos,
 
633
                        sizeof(st->buf) - st->bpos);
 
634
        st->bpos += len;
 
635
        sent += len;
 
636
        if (st->bpos != sizeof(st->buf)) {
 
637
            break;
 
638
        }
 
639
    }
 
640
}
 
641
 
 
642
static void hda_audio_set_running(HDAAudioStream *st, bool running)
 
643
{
 
644
    if (st->node == NULL) {
 
645
        return;
 
646
    }
 
647
    if (st->running == running) {
 
648
        return;
 
649
    }
 
650
    st->running = running;
 
651
    dprint(st->state, 1, "%s: %s (stream %d)\n", st->node->name,
 
652
           st->running ? "on" : "off", st->stream);
 
653
    if (st->output) {
 
654
        AUD_set_active_out(st->voice.out, st->running);
 
655
    } else {
 
656
        AUD_set_active_in(st->voice.in, st->running);
 
657
    }
 
658
}
 
659
 
 
660
static void hda_audio_set_amp(HDAAudioStream *st)
 
661
{
 
662
    bool muted;
 
663
    uint32_t left, right;
 
664
 
 
665
    if (st->node == NULL) {
 
666
        return;
 
667
    }
 
668
 
 
669
    muted = st->mute_left && st->mute_right;
 
670
    left  = st->mute_left  ? 0 : st->gain_left;
 
671
    right = st->mute_right ? 0 : st->gain_right;
 
672
 
 
673
    left = left * 255 / QEMU_HDA_AMP_STEPS;
 
674
    right = right * 255 / QEMU_HDA_AMP_STEPS;
 
675
 
 
676
    if (st->output) {
 
677
        AUD_set_volume_out(st->voice.out, muted, left, right);
 
678
    } else {
 
679
        AUD_set_volume_in(st->voice.in, muted, left, right);
 
680
    }
 
681
}
 
682
 
 
683
static void hda_audio_setup(HDAAudioStream *st)
 
684
{
 
685
    if (st->node == NULL) {
 
686
        return;
 
687
    }
 
688
 
 
689
    dprint(st->state, 1, "%s: format: %d x %s @ %d Hz\n",
 
690
           st->node->name, st->as.nchannels,
 
691
           fmt2name[st->as.fmt], st->as.freq);
 
692
 
 
693
    if (st->output) {
 
694
        st->voice.out = AUD_open_out(&st->state->card, st->voice.out,
 
695
                                     st->node->name, st,
 
696
                                     hda_audio_output_cb, &st->as);
 
697
    } else {
 
698
        st->voice.in = AUD_open_in(&st->state->card, st->voice.in,
 
699
                                   st->node->name, st,
 
700
                                   hda_audio_input_cb, &st->as);
 
701
    }
 
702
}
 
703
 
 
704
static void hda_audio_command(HDACodecDevice *hda, uint32_t nid, uint32_t data)
 
705
{
 
706
    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
 
707
    HDAAudioStream *st;
 
708
    const desc_node *node = NULL;
 
709
    const desc_param *param;
 
710
    uint32_t verb, payload, response, count, shift;
 
711
 
 
712
    if ((data & 0x70000) == 0x70000) {
 
713
        /* 12/8 id/payload */
 
714
        verb = (data >> 8) & 0xfff;
 
715
        payload = data & 0x00ff;
 
716
    } else {
 
717
        /* 4/16 id/payload */
 
718
        verb = (data >> 8) & 0xf00;
 
719
        payload = data & 0xffff;
 
720
    }
 
721
 
 
722
    node = hda_codec_find_node(a->desc, nid);
 
723
    if (node == NULL) {
 
724
        goto fail;
 
725
    }
 
726
    dprint(a, 2, "%s: nid %d (%s), verb 0x%x, payload 0x%x\n",
 
727
           __FUNCTION__, nid, node->name, verb, payload);
 
728
 
 
729
    switch (verb) {
 
730
    /* all nodes */
 
731
    case AC_VERB_PARAMETERS:
 
732
        param = hda_codec_find_param(node, payload);
 
733
        if (param == NULL) {
 
734
            goto fail;
 
735
        }
 
736
        hda_codec_response(hda, true, param->val);
 
737
        break;
 
738
    case AC_VERB_GET_SUBSYSTEM_ID:
 
739
        hda_codec_response(hda, true, a->desc->iid);
 
740
        break;
 
741
 
 
742
    /* all functions */
 
743
    case AC_VERB_GET_CONNECT_LIST:
 
744
        param = hda_codec_find_param(node, AC_PAR_CONNLIST_LEN);
 
745
        count = param ? param->val : 0;
 
746
        response = 0;
 
747
        shift = 0;
 
748
        while (payload < count && shift < 32) {
 
749
            response |= node->conn[payload] << shift;
 
750
            payload++;
 
751
            shift += 8;
 
752
        }
 
753
        hda_codec_response(hda, true, response);
 
754
        break;
 
755
 
 
756
    /* pin widget */
 
757
    case AC_VERB_GET_CONFIG_DEFAULT:
 
758
        hda_codec_response(hda, true, node->config);
 
759
        break;
 
760
    case AC_VERB_GET_PIN_WIDGET_CONTROL:
 
761
        hda_codec_response(hda, true, node->pinctl);
 
762
        break;
 
763
    case AC_VERB_SET_PIN_WIDGET_CONTROL:
 
764
        if (node->pinctl != payload) {
 
765
            dprint(a, 1, "unhandled pin control bit\n");
 
766
        }
 
767
        hda_codec_response(hda, true, 0);
 
768
        break;
 
769
 
 
770
    /* audio in/out widget */
 
771
    case AC_VERB_SET_CHANNEL_STREAMID:
 
772
        st = a->st + node->stindex;
 
773
        if (st->node == NULL) {
 
774
            goto fail;
 
775
        }
 
776
        hda_audio_set_running(st, false);
 
777
        st->stream = (payload >> 4) & 0x0f;
 
778
        st->channel = payload & 0x0f;
 
779
        dprint(a, 2, "%s: stream %d, channel %d\n",
 
780
               st->node->name, st->stream, st->channel);
 
781
        hda_audio_set_running(st, a->running_real[st->output * 16 + st->stream]);
 
782
        hda_codec_response(hda, true, 0);
 
783
        break;
 
784
    case AC_VERB_GET_CONV:
 
785
        st = a->st + node->stindex;
 
786
        if (st->node == NULL) {
 
787
            goto fail;
 
788
        }
 
789
        response = st->stream << 4 | st->channel;
 
790
        hda_codec_response(hda, true, response);
 
791
        break;
 
792
    case AC_VERB_SET_STREAM_FORMAT:
 
793
        st = a->st + node->stindex;
 
794
        if (st->node == NULL) {
 
795
            goto fail;
 
796
        }
 
797
        st->format = payload;
 
798
        hda_codec_parse_fmt(st->format, &st->as);
 
799
        hda_audio_setup(st);
 
800
        hda_codec_response(hda, true, 0);
 
801
        break;
 
802
    case AC_VERB_GET_STREAM_FORMAT:
 
803
        st = a->st + node->stindex;
 
804
        if (st->node == NULL) {
 
805
            goto fail;
 
806
        }
 
807
        hda_codec_response(hda, true, st->format);
 
808
        break;
 
809
    case AC_VERB_GET_AMP_GAIN_MUTE:
 
810
        st = a->st + node->stindex;
 
811
        if (st->node == NULL) {
 
812
            goto fail;
 
813
        }
 
814
        if (payload & AC_AMP_GET_LEFT) {
 
815
            response = st->gain_left | (st->mute_left ? AC_AMP_MUTE : 0);
 
816
        } else {
 
817
            response = st->gain_right | (st->mute_right ? AC_AMP_MUTE : 0);
 
818
        }
 
819
        hda_codec_response(hda, true, response);
 
820
        break;
 
821
    case AC_VERB_SET_AMP_GAIN_MUTE:
 
822
        st = a->st + node->stindex;
 
823
        if (st->node == NULL) {
 
824
            goto fail;
 
825
        }
 
826
        dprint(a, 1, "amp (%s): %s%s%s%s index %d  gain %3d %s\n",
 
827
               st->node->name,
 
828
               (payload & AC_AMP_SET_OUTPUT) ? "o" : "-",
 
829
               (payload & AC_AMP_SET_INPUT)  ? "i" : "-",
 
830
               (payload & AC_AMP_SET_LEFT)   ? "l" : "-",
 
831
               (payload & AC_AMP_SET_RIGHT)  ? "r" : "-",
 
832
               (payload & AC_AMP_SET_INDEX) >> AC_AMP_SET_INDEX_SHIFT,
 
833
               (payload & AC_AMP_GAIN),
 
834
               (payload & AC_AMP_MUTE) ? "muted" : "");
 
835
        if (payload & AC_AMP_SET_LEFT) {
 
836
            st->gain_left = payload & AC_AMP_GAIN;
 
837
            st->mute_left = payload & AC_AMP_MUTE;
 
838
        }
 
839
        if (payload & AC_AMP_SET_RIGHT) {
 
840
            st->gain_right = payload & AC_AMP_GAIN;
 
841
            st->mute_right = payload & AC_AMP_MUTE;
 
842
        }
 
843
        hda_audio_set_amp(st);
 
844
        hda_codec_response(hda, true, 0);
 
845
        break;
 
846
 
 
847
    /* not supported */
 
848
    case AC_VERB_SET_POWER_STATE:
 
849
    case AC_VERB_GET_POWER_STATE:
 
850
    case AC_VERB_GET_SDI_SELECT:
 
851
        hda_codec_response(hda, true, 0);
 
852
        break;
 
853
    default:
 
854
        goto fail;
 
855
    }
 
856
    return;
 
857
 
 
858
fail:
 
859
    dprint(a, 1, "%s: not handled: nid %d (%s), verb 0x%x, payload 0x%x\n",
 
860
           __FUNCTION__, nid, node ? node->name : "?", verb, payload);
 
861
    hda_codec_response(hda, true, 0);
 
862
}
 
863
 
 
864
static void hda_audio_stream(HDACodecDevice *hda, uint32_t stnr, bool running, bool output)
 
865
{
 
866
    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
 
867
    int s;
 
868
 
 
869
    a->running_compat[stnr] = running;
 
870
    a->running_real[output * 16 + stnr] = running;
 
871
    for (s = 0; s < ARRAY_SIZE(a->st); s++) {
 
872
        if (a->st[s].node == NULL) {
 
873
            continue;
 
874
        }
 
875
        if (a->st[s].output != output) {
 
876
            continue;
 
877
        }
 
878
        if (a->st[s].stream != stnr) {
 
879
            continue;
 
880
        }
 
881
        hda_audio_set_running(&a->st[s], running);
 
882
    }
 
883
}
 
884
 
 
885
static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
 
886
{
 
887
    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
 
888
    HDAAudioStream *st;
 
889
    const desc_node *node;
 
890
    const desc_param *param;
 
891
    uint32_t i, type;
 
892
 
 
893
    a->desc = desc;
 
894
    a->name = object_get_typename(OBJECT(a));
 
895
    dprint(a, 1, "%s: cad %d\n", __FUNCTION__, a->hda.cad);
 
896
 
 
897
    AUD_register_card("hda", &a->card);
 
898
    for (i = 0; i < a->desc->nnodes; i++) {
 
899
        node = a->desc->nodes + i;
 
900
        param = hda_codec_find_param(node, AC_PAR_AUDIO_WIDGET_CAP);
 
901
        if (NULL == param)
 
902
            continue;
 
903
        type = (param->val & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 
904
        switch (type) {
 
905
        case AC_WID_AUD_OUT:
 
906
        case AC_WID_AUD_IN:
 
907
            assert(node->stindex < ARRAY_SIZE(a->st));
 
908
            st = a->st + node->stindex;
 
909
            st->state = a;
 
910
            st->node = node;
 
911
            if (type == AC_WID_AUD_OUT) {
 
912
                /* unmute output by default */
 
913
                st->gain_left = QEMU_HDA_AMP_STEPS;
 
914
                st->gain_right = QEMU_HDA_AMP_STEPS;
 
915
                st->bpos = sizeof(st->buf);
 
916
                st->output = true;
 
917
            } else {
 
918
                st->output = false;
 
919
            }
 
920
            st->format = AC_FMT_TYPE_PCM | AC_FMT_BITS_16 |
 
921
                (1 << AC_FMT_CHAN_SHIFT);
 
922
            hda_codec_parse_fmt(st->format, &st->as);
 
923
            hda_audio_setup(st);
 
924
            break;
 
925
        }
 
926
    }
 
927
    return 0;
 
928
}
 
929
 
 
930
static int hda_audio_exit(HDACodecDevice *hda)
 
931
{
 
932
    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
 
933
    HDAAudioStream *st;
 
934
    int i;
 
935
 
 
936
    dprint(a, 1, "%s\n", __FUNCTION__);
 
937
    for (i = 0; i < ARRAY_SIZE(a->st); i++) {
 
938
        st = a->st + i;
 
939
        if (st->node == NULL) {
 
940
            continue;
 
941
        }
 
942
        if (st->output) {
 
943
            AUD_close_out(&a->card, st->voice.out);
 
944
        } else {
 
945
            AUD_close_in(&a->card, st->voice.in);
 
946
        }
 
947
    }
 
948
    AUD_remove_card(&a->card);
 
949
    return 0;
 
950
}
 
951
 
 
952
static int hda_audio_post_load(void *opaque, int version)
 
953
{
 
954
    HDAAudioState *a = opaque;
 
955
    HDAAudioStream *st;
 
956
    int i;
 
957
 
 
958
    dprint(a, 1, "%s\n", __FUNCTION__);
 
959
    if (version == 1) {
 
960
        /* assume running_compat[] is for output streams */
 
961
        for (i = 0; i < ARRAY_SIZE(a->running_compat); i++)
 
962
            a->running_real[16 + i] = a->running_compat[i];
 
963
    }
 
964
 
 
965
    for (i = 0; i < ARRAY_SIZE(a->st); i++) {
 
966
        st = a->st + i;
 
967
        if (st->node == NULL)
 
968
            continue;
 
969
        hda_codec_parse_fmt(st->format, &st->as);
 
970
        hda_audio_setup(st);
 
971
        hda_audio_set_amp(st);
 
972
        hda_audio_set_running(st, a->running_real[st->output * 16 + st->stream]);
 
973
    }
 
974
    return 0;
 
975
}
 
976
 
 
977
static const VMStateDescription vmstate_hda_audio_stream = {
 
978
    .name = "hda-audio-stream",
 
979
    .version_id = 1,
 
980
    .fields = (VMStateField []) {
 
981
        VMSTATE_UINT32(stream, HDAAudioStream),
 
982
        VMSTATE_UINT32(channel, HDAAudioStream),
 
983
        VMSTATE_UINT32(format, HDAAudioStream),
 
984
        VMSTATE_UINT32(gain_left, HDAAudioStream),
 
985
        VMSTATE_UINT32(gain_right, HDAAudioStream),
 
986
        VMSTATE_BOOL(mute_left, HDAAudioStream),
 
987
        VMSTATE_BOOL(mute_right, HDAAudioStream),
 
988
        VMSTATE_UINT32(bpos, HDAAudioStream),
 
989
        VMSTATE_BUFFER(buf, HDAAudioStream),
 
990
        VMSTATE_END_OF_LIST()
 
991
    }
 
992
};
 
993
 
 
994
static const VMStateDescription vmstate_hda_audio = {
 
995
    .name = "hda-audio",
 
996
    .version_id = 2,
 
997
    .post_load = hda_audio_post_load,
 
998
    .fields = (VMStateField []) {
 
999
        VMSTATE_STRUCT_ARRAY(st, HDAAudioState, 4, 0,
 
1000
                             vmstate_hda_audio_stream,
 
1001
                             HDAAudioStream),
 
1002
        VMSTATE_BOOL_ARRAY(running_compat, HDAAudioState, 16),
 
1003
        VMSTATE_BOOL_ARRAY_V(running_real, HDAAudioState, 2 * 16, 2),
 
1004
        VMSTATE_END_OF_LIST()
 
1005
    }
 
1006
};
 
1007
 
 
1008
static Property hda_audio_properties[] = {
 
1009
    DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0),
 
1010
    DEFINE_PROP_END_OF_LIST(),
 
1011
};
 
1012
 
 
1013
static int hda_audio_init_output(HDACodecDevice *hda)
 
1014
{
 
1015
    return hda_audio_init(hda, &output);
 
1016
}
 
1017
 
 
1018
static int hda_audio_init_duplex(HDACodecDevice *hda)
 
1019
{
 
1020
    return hda_audio_init(hda, &duplex);
 
1021
}
 
1022
 
 
1023
static int hda_audio_init_micro(HDACodecDevice *hda)
 
1024
{
 
1025
    return hda_audio_init(hda, &micro);
 
1026
}
 
1027
 
 
1028
static void hda_audio_output_class_init(ObjectClass *klass, void *data)
 
1029
{
 
1030
    DeviceClass *dc = DEVICE_CLASS(klass);
 
1031
    HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
 
1032
 
 
1033
    k->init = hda_audio_init_output;
 
1034
    k->exit = hda_audio_exit;
 
1035
    k->command = hda_audio_command;
 
1036
    k->stream = hda_audio_stream;
 
1037
    dc->desc = "HDA Audio Codec, output-only (line-out)";
 
1038
    dc->vmsd = &vmstate_hda_audio;
 
1039
    dc->props = hda_audio_properties;
 
1040
}
 
1041
 
 
1042
static TypeInfo hda_audio_output_info = {
 
1043
    .name          = "hda-output",
 
1044
    .parent        = TYPE_HDA_CODEC_DEVICE,
 
1045
    .instance_size = sizeof(HDAAudioState),
 
1046
    .class_init    = hda_audio_output_class_init,
 
1047
};
 
1048
 
 
1049
static void hda_audio_duplex_class_init(ObjectClass *klass, void *data)
 
1050
{
 
1051
    DeviceClass *dc = DEVICE_CLASS(klass);
 
1052
    HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
 
1053
 
 
1054
    k->init = hda_audio_init_duplex;
 
1055
    k->exit = hda_audio_exit;
 
1056
    k->command = hda_audio_command;
 
1057
    k->stream = hda_audio_stream;
 
1058
    dc->desc = "HDA Audio Codec, duplex (line-out, line-in)";
 
1059
    dc->vmsd = &vmstate_hda_audio;
 
1060
    dc->props = hda_audio_properties;
 
1061
}
 
1062
 
 
1063
static TypeInfo hda_audio_duplex_info = {
 
1064
    .name          = "hda-duplex",
 
1065
    .parent        = TYPE_HDA_CODEC_DEVICE,
 
1066
    .instance_size = sizeof(HDAAudioState),
 
1067
    .class_init    = hda_audio_duplex_class_init,
 
1068
};
 
1069
 
 
1070
static void hda_audio_micro_class_init(ObjectClass *klass, void *data)
 
1071
{
 
1072
    DeviceClass *dc = DEVICE_CLASS(klass);
 
1073
    HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
 
1074
 
 
1075
    k->init = hda_audio_init_micro;
 
1076
    k->exit = hda_audio_exit;
 
1077
    k->command = hda_audio_command;
 
1078
    k->stream = hda_audio_stream;
 
1079
    dc->desc = "HDA Audio Codec, duplex (speaker, microphone)";
 
1080
    dc->vmsd = &vmstate_hda_audio;
 
1081
    dc->props = hda_audio_properties;
 
1082
}
 
1083
 
 
1084
static TypeInfo hda_audio_micro_info = {
 
1085
    .name          = "hda-micro",
 
1086
    .parent        = TYPE_HDA_CODEC_DEVICE,
 
1087
    .instance_size = sizeof(HDAAudioState),
 
1088
    .class_init    = hda_audio_micro_class_init,
 
1089
};
 
1090
 
 
1091
static void hda_audio_register_types(void)
 
1092
{
 
1093
    type_register_static(&hda_audio_output_info);
 
1094
    type_register_static(&hda_audio_duplex_info);
 
1095
    type_register_static(&hda_audio_micro_info);
 
1096
}
 
1097
 
 
1098
type_init(hda_audio_register_types)