Statistics
| Branch: | Revision:

root / hw / audio / hda-codec.c @ 2690e61e

History | View | Annotate | Download (20.6 kB)

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/hw.h"
21
#include "hw/pci/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   PARAM mixemu
123
#define   HDA_MIXER
124
#include "hda-codec-common.h"
125
#endif
126

    
127
#define   PARAM nomixemu
128
#include  "hda-codec-common.h"
129

    
130
/* -------------------------------------------------------------------------- */
131

    
132
static const char *fmt2name[] = {
133
    [ AUD_FMT_U8  ] = "PCM-U8",
134
    [ AUD_FMT_S8  ] = "PCM-S8",
135
    [ AUD_FMT_U16 ] = "PCM-U16",
136
    [ AUD_FMT_S16 ] = "PCM-S16",
137
    [ AUD_FMT_U32 ] = "PCM-U32",
138
    [ AUD_FMT_S32 ] = "PCM-S32",
139
};
140

    
141
typedef struct HDAAudioState HDAAudioState;
142
typedef struct HDAAudioStream HDAAudioStream;
143

    
144
struct HDAAudioStream {
145
    HDAAudioState *state;
146
    const desc_node *node;
147
    bool output, running;
148
    uint32_t stream;
149
    uint32_t channel;
150
    uint32_t format;
151
    uint32_t gain_left, gain_right;
152
    bool mute_left, mute_right;
153
    struct audsettings as;
154
    union {
155
        SWVoiceIn *in;
156
        SWVoiceOut *out;
157
    } voice;
158
    uint8_t buf[HDA_BUFFER_SIZE];
159
    uint32_t bpos;
160
};
161

    
162
struct HDAAudioState {
163
    HDACodecDevice hda;
164
    const char *name;
165

    
166
    QEMUSoundCard card;
167
    const desc_codec *desc;
168
    HDAAudioStream st[4];
169
    bool running_compat[16];
170
    bool running_real[2 * 16];
171

    
172
    /* properties */
173
    uint32_t debug;
174
    bool     mixer;
175
};
176

    
177
static void hda_audio_input_cb(void *opaque, int avail)
178
{
179
    HDAAudioStream *st = opaque;
180
    int recv = 0;
181
    int len;
182
    bool rc;
183

    
184
    while (avail - recv >= sizeof(st->buf)) {
185
        if (st->bpos != sizeof(st->buf)) {
186
            len = AUD_read(st->voice.in, st->buf + st->bpos,
187
                           sizeof(st->buf) - st->bpos);
188
            st->bpos += len;
189
            recv += len;
190
            if (st->bpos != sizeof(st->buf)) {
191
                break;
192
            }
193
        }
194
        rc = hda_codec_xfer(&st->state->hda, st->stream, false,
195
                            st->buf, sizeof(st->buf));
196
        if (!rc) {
197
            break;
198
        }
199
        st->bpos = 0;
200
    }
201
}
202

    
203
static void hda_audio_output_cb(void *opaque, int avail)
204
{
205
    HDAAudioStream *st = opaque;
206
    int sent = 0;
207
    int len;
208
    bool rc;
209

    
210
    while (avail - sent >= sizeof(st->buf)) {
211
        if (st->bpos == sizeof(st->buf)) {
212
            rc = hda_codec_xfer(&st->state->hda, st->stream, true,
213
                                st->buf, sizeof(st->buf));
214
            if (!rc) {
215
                break;
216
            }
217
            st->bpos = 0;
218
        }
219
        len = AUD_write(st->voice.out, st->buf + st->bpos,
220
                        sizeof(st->buf) - st->bpos);
221
        st->bpos += len;
222
        sent += len;
223
        if (st->bpos != sizeof(st->buf)) {
224
            break;
225
        }
226
    }
227
}
228

    
229
static void hda_audio_set_running(HDAAudioStream *st, bool running)
230
{
231
    if (st->node == NULL) {
232
        return;
233
    }
234
    if (st->running == running) {
235
        return;
236
    }
237
    st->running = running;
238
    dprint(st->state, 1, "%s: %s (stream %d)\n", st->node->name,
239
           st->running ? "on" : "off", st->stream);
240
    if (st->output) {
241
        AUD_set_active_out(st->voice.out, st->running);
242
    } else {
243
        AUD_set_active_in(st->voice.in, st->running);
244
    }
245
}
246

    
247
static void hda_audio_set_amp(HDAAudioStream *st)
248
{
249
    bool muted;
250
    uint32_t left, right;
251

    
252
    if (st->node == NULL) {
253
        return;
254
    }
255

    
256
    muted = st->mute_left && st->mute_right;
257
    left  = st->mute_left  ? 0 : st->gain_left;
258
    right = st->mute_right ? 0 : st->gain_right;
259

    
260
    left = left * 255 / QEMU_HDA_AMP_STEPS;
261
    right = right * 255 / QEMU_HDA_AMP_STEPS;
262

    
263
    if (st->output) {
264
        AUD_set_volume_out(st->voice.out, muted, left, right);
265
    } else {
266
        AUD_set_volume_in(st->voice.in, muted, left, right);
267
    }
268
}
269

    
270
static void hda_audio_setup(HDAAudioStream *st)
271
{
272
    if (st->node == NULL) {
273
        return;
274
    }
275

    
276
    dprint(st->state, 1, "%s: format: %d x %s @ %d Hz\n",
277
           st->node->name, st->as.nchannels,
278
           fmt2name[st->as.fmt], st->as.freq);
279

    
280
    if (st->output) {
281
        st->voice.out = AUD_open_out(&st->state->card, st->voice.out,
282
                                     st->node->name, st,
283
                                     hda_audio_output_cb, &st->as);
284
    } else {
285
        st->voice.in = AUD_open_in(&st->state->card, st->voice.in,
286
                                   st->node->name, st,
287
                                   hda_audio_input_cb, &st->as);
288
    }
289
}
290

    
291
static void hda_audio_command(HDACodecDevice *hda, uint32_t nid, uint32_t data)
292
{
293
    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
294
    HDAAudioStream *st;
295
    const desc_node *node = NULL;
296
    const desc_param *param;
297
    uint32_t verb, payload, response, count, shift;
298

    
299
    if ((data & 0x70000) == 0x70000) {
300
        /* 12/8 id/payload */
301
        verb = (data >> 8) & 0xfff;
302
        payload = data & 0x00ff;
303
    } else {
304
        /* 4/16 id/payload */
305
        verb = (data >> 8) & 0xf00;
306
        payload = data & 0xffff;
307
    }
308

    
309
    node = hda_codec_find_node(a->desc, nid);
310
    if (node == NULL) {
311
        goto fail;
312
    }
313
    dprint(a, 2, "%s: nid %d (%s), verb 0x%x, payload 0x%x\n",
314
           __FUNCTION__, nid, node->name, verb, payload);
315

    
316
    switch (verb) {
317
    /* all nodes */
318
    case AC_VERB_PARAMETERS:
319
        param = hda_codec_find_param(node, payload);
320
        if (param == NULL) {
321
            goto fail;
322
        }
323
        hda_codec_response(hda, true, param->val);
324
        break;
325
    case AC_VERB_GET_SUBSYSTEM_ID:
326
        hda_codec_response(hda, true, a->desc->iid);
327
        break;
328

    
329
    /* all functions */
330
    case AC_VERB_GET_CONNECT_LIST:
331
        param = hda_codec_find_param(node, AC_PAR_CONNLIST_LEN);
332
        count = param ? param->val : 0;
333
        response = 0;
334
        shift = 0;
335
        while (payload < count && shift < 32) {
336
            response |= node->conn[payload] << shift;
337
            payload++;
338
            shift += 8;
339
        }
340
        hda_codec_response(hda, true, response);
341
        break;
342

    
343
    /* pin widget */
344
    case AC_VERB_GET_CONFIG_DEFAULT:
345
        hda_codec_response(hda, true, node->config);
346
        break;
347
    case AC_VERB_GET_PIN_WIDGET_CONTROL:
348
        hda_codec_response(hda, true, node->pinctl);
349
        break;
350
    case AC_VERB_SET_PIN_WIDGET_CONTROL:
351
        if (node->pinctl != payload) {
352
            dprint(a, 1, "unhandled pin control bit\n");
353
        }
354
        hda_codec_response(hda, true, 0);
355
        break;
356

    
357
    /* audio in/out widget */
358
    case AC_VERB_SET_CHANNEL_STREAMID:
359
        st = a->st + node->stindex;
360
        if (st->node == NULL) {
361
            goto fail;
362
        }
363
        hda_audio_set_running(st, false);
364
        st->stream = (payload >> 4) & 0x0f;
365
        st->channel = payload & 0x0f;
366
        dprint(a, 2, "%s: stream %d, channel %d\n",
367
               st->node->name, st->stream, st->channel);
368
        hda_audio_set_running(st, a->running_real[st->output * 16 + st->stream]);
369
        hda_codec_response(hda, true, 0);
370
        break;
371
    case AC_VERB_GET_CONV:
372
        st = a->st + node->stindex;
373
        if (st->node == NULL) {
374
            goto fail;
375
        }
376
        response = st->stream << 4 | st->channel;
377
        hda_codec_response(hda, true, response);
378
        break;
379
    case AC_VERB_SET_STREAM_FORMAT:
380
        st = a->st + node->stindex;
381
        if (st->node == NULL) {
382
            goto fail;
383
        }
384
        st->format = payload;
385
        hda_codec_parse_fmt(st->format, &st->as);
386
        hda_audio_setup(st);
387
        hda_codec_response(hda, true, 0);
388
        break;
389
    case AC_VERB_GET_STREAM_FORMAT:
390
        st = a->st + node->stindex;
391
        if (st->node == NULL) {
392
            goto fail;
393
        }
394
        hda_codec_response(hda, true, st->format);
395
        break;
396
    case AC_VERB_GET_AMP_GAIN_MUTE:
397
        st = a->st + node->stindex;
398
        if (st->node == NULL) {
399
            goto fail;
400
        }
401
        if (payload & AC_AMP_GET_LEFT) {
402
            response = st->gain_left | (st->mute_left ? AC_AMP_MUTE : 0);
403
        } else {
404
            response = st->gain_right | (st->mute_right ? AC_AMP_MUTE : 0);
405
        }
406
        hda_codec_response(hda, true, response);
407
        break;
408
    case AC_VERB_SET_AMP_GAIN_MUTE:
409
        st = a->st + node->stindex;
410
        if (st->node == NULL) {
411
            goto fail;
412
        }
413
        dprint(a, 1, "amp (%s): %s%s%s%s index %d  gain %3d %s\n",
414
               st->node->name,
415
               (payload & AC_AMP_SET_OUTPUT) ? "o" : "-",
416
               (payload & AC_AMP_SET_INPUT)  ? "i" : "-",
417
               (payload & AC_AMP_SET_LEFT)   ? "l" : "-",
418
               (payload & AC_AMP_SET_RIGHT)  ? "r" : "-",
419
               (payload & AC_AMP_SET_INDEX) >> AC_AMP_SET_INDEX_SHIFT,
420
               (payload & AC_AMP_GAIN),
421
               (payload & AC_AMP_MUTE) ? "muted" : "");
422
        if (payload & AC_AMP_SET_LEFT) {
423
            st->gain_left = payload & AC_AMP_GAIN;
424
            st->mute_left = payload & AC_AMP_MUTE;
425
        }
426
        if (payload & AC_AMP_SET_RIGHT) {
427
            st->gain_right = payload & AC_AMP_GAIN;
428
            st->mute_right = payload & AC_AMP_MUTE;
429
        }
430
        hda_audio_set_amp(st);
431
        hda_codec_response(hda, true, 0);
432
        break;
433

    
434
    /* not supported */
435
    case AC_VERB_SET_POWER_STATE:
436
    case AC_VERB_GET_POWER_STATE:
437
    case AC_VERB_GET_SDI_SELECT:
438
        hda_codec_response(hda, true, 0);
439
        break;
440
    default:
441
        goto fail;
442
    }
443
    return;
444

    
445
fail:
446
    dprint(a, 1, "%s: not handled: nid %d (%s), verb 0x%x, payload 0x%x\n",
447
           __FUNCTION__, nid, node ? node->name : "?", verb, payload);
448
    hda_codec_response(hda, true, 0);
449
}
450

    
451
static void hda_audio_stream(HDACodecDevice *hda, uint32_t stnr, bool running, bool output)
452
{
453
    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
454
    int s;
455

    
456
    a->running_compat[stnr] = running;
457
    a->running_real[output * 16 + stnr] = running;
458
    for (s = 0; s < ARRAY_SIZE(a->st); s++) {
459
        if (a->st[s].node == NULL) {
460
            continue;
461
        }
462
        if (a->st[s].output != output) {
463
            continue;
464
        }
465
        if (a->st[s].stream != stnr) {
466
            continue;
467
        }
468
        hda_audio_set_running(&a->st[s], running);
469
    }
470
}
471

    
472
static int hda_audio_init(HDACodecDevice *hda, const struct desc_codec *desc)
473
{
474
    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
475
    HDAAudioStream *st;
476
    const desc_node *node;
477
    const desc_param *param;
478
    uint32_t i, type;
479

    
480
    a->desc = desc;
481
    a->name = object_get_typename(OBJECT(a));
482
    dprint(a, 1, "%s: cad %d\n", __FUNCTION__, a->hda.cad);
483

    
484
    AUD_register_card("hda", &a->card);
485
    for (i = 0; i < a->desc->nnodes; i++) {
486
        node = a->desc->nodes + i;
487
        param = hda_codec_find_param(node, AC_PAR_AUDIO_WIDGET_CAP);
488
        if (NULL == param)
489
            continue;
490
        type = (param->val & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
491
        switch (type) {
492
        case AC_WID_AUD_OUT:
493
        case AC_WID_AUD_IN:
494
            assert(node->stindex < ARRAY_SIZE(a->st));
495
            st = a->st + node->stindex;
496
            st->state = a;
497
            st->node = node;
498
            if (type == AC_WID_AUD_OUT) {
499
                /* unmute output by default */
500
                st->gain_left = QEMU_HDA_AMP_STEPS;
501
                st->gain_right = QEMU_HDA_AMP_STEPS;
502
                st->bpos = sizeof(st->buf);
503
                st->output = true;
504
            } else {
505
                st->output = false;
506
            }
507
            st->format = AC_FMT_TYPE_PCM | AC_FMT_BITS_16 |
508
                (1 << AC_FMT_CHAN_SHIFT);
509
            hda_codec_parse_fmt(st->format, &st->as);
510
            hda_audio_setup(st);
511
            break;
512
        }
513
    }
514
    return 0;
515
}
516

    
517
static int hda_audio_exit(HDACodecDevice *hda)
518
{
519
    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
520
    HDAAudioStream *st;
521
    int i;
522

    
523
    dprint(a, 1, "%s\n", __FUNCTION__);
524
    for (i = 0; i < ARRAY_SIZE(a->st); i++) {
525
        st = a->st + i;
526
        if (st->node == NULL) {
527
            continue;
528
        }
529
        if (st->output) {
530
            AUD_close_out(&a->card, st->voice.out);
531
        } else {
532
            AUD_close_in(&a->card, st->voice.in);
533
        }
534
    }
535
    AUD_remove_card(&a->card);
536
    return 0;
537
}
538

    
539
static int hda_audio_post_load(void *opaque, int version)
540
{
541
    HDAAudioState *a = opaque;
542
    HDAAudioStream *st;
543
    int i;
544

    
545
    dprint(a, 1, "%s\n", __FUNCTION__);
546
    if (version == 1) {
547
        /* assume running_compat[] is for output streams */
548
        for (i = 0; i < ARRAY_SIZE(a->running_compat); i++)
549
            a->running_real[16 + i] = a->running_compat[i];
550
    }
551

    
552
    for (i = 0; i < ARRAY_SIZE(a->st); i++) {
553
        st = a->st + i;
554
        if (st->node == NULL)
555
            continue;
556
        hda_codec_parse_fmt(st->format, &st->as);
557
        hda_audio_setup(st);
558
        hda_audio_set_amp(st);
559
        hda_audio_set_running(st, a->running_real[st->output * 16 + st->stream]);
560
    }
561
    return 0;
562
}
563

    
564
static const VMStateDescription vmstate_hda_audio_stream = {
565
    .name = "hda-audio-stream",
566
    .version_id = 1,
567
    .fields = (VMStateField []) {
568
        VMSTATE_UINT32(stream, HDAAudioStream),
569
        VMSTATE_UINT32(channel, HDAAudioStream),
570
        VMSTATE_UINT32(format, HDAAudioStream),
571
        VMSTATE_UINT32(gain_left, HDAAudioStream),
572
        VMSTATE_UINT32(gain_right, HDAAudioStream),
573
        VMSTATE_BOOL(mute_left, HDAAudioStream),
574
        VMSTATE_BOOL(mute_right, HDAAudioStream),
575
        VMSTATE_UINT32(bpos, HDAAudioStream),
576
        VMSTATE_BUFFER(buf, HDAAudioStream),
577
        VMSTATE_END_OF_LIST()
578
    }
579
};
580

    
581
static const VMStateDescription vmstate_hda_audio = {
582
    .name = "hda-audio",
583
    .version_id = 2,
584
    .post_load = hda_audio_post_load,
585
    .fields = (VMStateField []) {
586
        VMSTATE_STRUCT_ARRAY(st, HDAAudioState, 4, 0,
587
                             vmstate_hda_audio_stream,
588
                             HDAAudioStream),
589
        VMSTATE_BOOL_ARRAY(running_compat, HDAAudioState, 16),
590
        VMSTATE_BOOL_ARRAY_V(running_real, HDAAudioState, 2 * 16, 2),
591
        VMSTATE_END_OF_LIST()
592
    }
593
};
594

    
595
static Property hda_audio_properties[] = {
596
    DEFINE_PROP_UINT32("debug", HDAAudioState, debug,   0),
597
#ifdef CONFIG_MIXEMU
598
    DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer,  true),
599
#else
600
    DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer, false),
601
#endif
602
    DEFINE_PROP_END_OF_LIST(),
603
};
604

    
605
static int hda_audio_init_output(HDACodecDevice *hda)
606
{
607
    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
608

    
609
    if (!a->mixer) {
610
        return hda_audio_init(hda, &output_nomixemu);
611
    } else {
612

    
613
#ifdef CONFIG_MIXEMU
614
        return hda_audio_init(hda, &output_mixemu);
615
#else
616
        fprintf(stderr, "ERROR: "
617
                "hda-codec : Mixer emulation has not been compiled in!\n");
618
        return -1;
619
#endif
620

    
621
    }
622
}
623

    
624
static int hda_audio_init_duplex(HDACodecDevice *hda)
625
{
626
    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
627

    
628
    if (!a->mixer) {
629
        return hda_audio_init(hda, &duplex_nomixemu);
630
    } else {
631

    
632
#ifdef CONFIG_MIXEMU
633
        return hda_audio_init(hda, &duplex_mixemu);
634
#else
635
        fprintf(stderr, "ERROR: "
636
                "hda-codec : Mixer emulation has not been compiled in!\n");
637
        return -1;
638
#endif
639

    
640
    }
641
}
642

    
643
static int hda_audio_init_micro(HDACodecDevice *hda)
644
{
645
    HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda);
646

    
647
    if (!a->mixer) {
648
        return hda_audio_init(hda, &micro_nomixemu);
649
    } else {
650

    
651
#ifdef CONFIG_MIXEMU
652
        return hda_audio_init(hda, &micro_mixemu);
653
#else
654
        fprintf(stderr, "ERROR: "
655
                "hda-codec : Mixer emulation has not been compiled in!\n");
656
        return -1;
657
#endif
658

    
659
    }
660
}
661

    
662
static void hda_audio_output_class_init(ObjectClass *klass, void *data)
663
{
664
    DeviceClass *dc = DEVICE_CLASS(klass);
665
    HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
666

    
667
    k->init = hda_audio_init_output;
668
    k->exit = hda_audio_exit;
669
    k->command = hda_audio_command;
670
    k->stream = hda_audio_stream;
671
    set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
672
    dc->desc = "HDA Audio Codec, output-only (line-out)";
673
    dc->vmsd = &vmstate_hda_audio;
674
    dc->props = hda_audio_properties;
675
}
676

    
677
static const TypeInfo hda_audio_output_info = {
678
    .name          = "hda-output",
679
    .parent        = TYPE_HDA_CODEC_DEVICE,
680
    .instance_size = sizeof(HDAAudioState),
681
    .class_init    = hda_audio_output_class_init,
682
};
683

    
684
static void hda_audio_duplex_class_init(ObjectClass *klass, void *data)
685
{
686
    DeviceClass *dc = DEVICE_CLASS(klass);
687
    HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
688

    
689
    k->init = hda_audio_init_duplex;
690
    k->exit = hda_audio_exit;
691
    k->command = hda_audio_command;
692
    k->stream = hda_audio_stream;
693
    set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
694
    dc->desc = "HDA Audio Codec, duplex (line-out, line-in)";
695
    dc->vmsd = &vmstate_hda_audio;
696
    dc->props = hda_audio_properties;
697
}
698

    
699
static const TypeInfo hda_audio_duplex_info = {
700
    .name          = "hda-duplex",
701
    .parent        = TYPE_HDA_CODEC_DEVICE,
702
    .instance_size = sizeof(HDAAudioState),
703
    .class_init    = hda_audio_duplex_class_init,
704
};
705

    
706
static void hda_audio_micro_class_init(ObjectClass *klass, void *data)
707
{
708
    DeviceClass *dc = DEVICE_CLASS(klass);
709
    HDACodecDeviceClass *k = HDA_CODEC_DEVICE_CLASS(klass);
710

    
711
    k->init = hda_audio_init_micro;
712
    k->exit = hda_audio_exit;
713
    k->command = hda_audio_command;
714
    k->stream = hda_audio_stream;
715
    set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
716
    dc->desc = "HDA Audio Codec, duplex (speaker, microphone)";
717
    dc->vmsd = &vmstate_hda_audio;
718
    dc->props = hda_audio_properties;
719
}
720

    
721
static const TypeInfo hda_audio_micro_info = {
722
    .name          = "hda-micro",
723
    .parent        = TYPE_HDA_CODEC_DEVICE,
724
    .instance_size = sizeof(HDAAudioState),
725
    .class_init    = hda_audio_micro_class_init,
726
};
727

    
728
static void hda_audio_register_types(void)
729
{
730
    type_register_static(&hda_audio_output_info);
731
    type_register_static(&hda_audio_duplex_info);
732
    type_register_static(&hda_audio_micro_info);
733
}
734

    
735
type_init(hda_audio_register_types)