Statistics
| Branch: | Revision:

root / hw / wm8750.c @ 523111e7

History | View | Annotate | Download (17.9 kB)

1
/*
2
 * WM8750 audio CODEC.
3
 *
4
 * Copyright (c) 2006 Openedhand Ltd.
5
 * Written by Andrzej Zaborowski <balrog@zabor.org>
6
 *
7
 * This file is licensed under GNU GPL.
8
 */
9

    
10
#include "hw.h"
11
#include "i2c.h"
12
#include "audio/audio.h"
13

    
14
#define IN_PORT_N        3
15
#define OUT_PORT_N        3
16

    
17
#define CODEC                "wm8750"
18

    
19
struct wm_rate_s;
20
struct wm8750_s {
21
    i2c_slave i2c;
22
    uint8_t i2c_data[2];
23
    int i2c_len;
24
    QEMUSoundCard card;
25
    SWVoiceIn *adc_voice[IN_PORT_N];
26
    SWVoiceOut *dac_voice[OUT_PORT_N];
27
    int enable;
28
    void (*data_req)(void *, int, int);
29
    void *opaque;
30
    uint8_t data_in[4096];
31
    uint8_t data_out[4096];
32
    int idx_in, req_in;
33
    int idx_out, req_out;
34

    
35
    SWVoiceOut **out[2];
36
    uint8_t outvol[7], outmute[2];
37
    SWVoiceIn **in[2];
38
    uint8_t invol[4], inmute[2];
39

    
40
    uint8_t diff[2], pol, ds, monomix[2], alc, mute;
41
    uint8_t path[4], mpath[2], power, format;
42
    uint32_t inmask, outmask;
43
    const struct wm_rate_s *rate;
44
};
45

    
46
static inline void wm8750_in_load(struct wm8750_s *s)
47
{
48
    int acquired;
49
    if (s->idx_in + s->req_in <= sizeof(s->data_in))
50
        return;
51
    s->idx_in = audio_MAX(0, (int) sizeof(s->data_in) - s->req_in);
52
    acquired = AUD_read(*s->in[0], s->data_in + s->idx_in,
53
                    sizeof(s->data_in) - s->idx_in);
54
}
55

    
56
static inline void wm8750_out_flush(struct wm8750_s *s)
57
{
58
    int sent = 0;
59
    while (sent < s->idx_out)
60
        sent += AUD_write(*s->out[0], s->data_out + sent, s->idx_out - sent)
61
                ?: s->idx_out;
62
    s->idx_out = 0;
63
}
64

    
65
static void wm8750_audio_in_cb(void *opaque, int avail_b)
66
{
67
    struct wm8750_s *s = (struct wm8750_s *) opaque;
68
    s->req_in = avail_b;
69
    s->data_req(s->opaque, s->req_out >> 2, avail_b >> 2);
70
}
71

    
72
static void wm8750_audio_out_cb(void *opaque, int free_b)
73
{
74
    struct wm8750_s *s = (struct wm8750_s *) opaque;
75

    
76
    if (s->idx_out >= free_b) {
77
        s->idx_out = free_b;
78
        s->req_out = 0;
79
        wm8750_out_flush(s);
80
    } else
81
        s->req_out = free_b - s->idx_out;
82
 
83
    s->data_req(s->opaque, s->req_out >> 2, s->req_in >> 2);
84
}
85

    
86
struct wm_rate_s {
87
    int adc;
88
    int adc_hz;
89
    int dac;
90
    int dac_hz;
91
};
92

    
93
static const struct wm_rate_s wm_rate_table[] = {
94
    {  256, 48000,  256, 48000 },        /* SR: 00000 */
95
    {  384, 48000,  384, 48000 },        /* SR: 00001 */
96
    {  256, 48000, 1536,  8000 },        /* SR: 00010 */
97
    {  384, 48000, 2304,  8000 },        /* SR: 00011 */
98
    { 1536,  8000,  256, 48000 },        /* SR: 00100 */
99
    { 2304,  8000,  384, 48000 },        /* SR: 00101 */
100
    { 1536,  8000, 1536,  8000 },        /* SR: 00110 */
101
    { 2304,  8000, 2304,  8000 },        /* SR: 00111 */
102
    { 1024, 12000, 1024, 12000 },        /* SR: 01000 */
103
    { 1526, 12000, 1536, 12000 },        /* SR: 01001 */
104
    {  768, 16000,  768, 16000 },        /* SR: 01010 */
105
    { 1152, 16000, 1152, 16000 },        /* SR: 01011 */
106
    {  384, 32000,  384, 32000 },        /* SR: 01100 */
107
    {  576, 32000,  576, 32000 },        /* SR: 01101 */
108
    {  128, 96000,  128, 96000 },        /* SR: 01110 */
109
    {  192, 96000,  192, 96000 },        /* SR: 01111 */
110
    {  256, 44100,  256, 44100 },        /* SR: 10000 */
111
    {  384, 44100,  384, 44100 },        /* SR: 10001 */
112
    {  256, 44100, 1408,  8018 },        /* SR: 10010 */
113
    {  384, 44100, 2112,  8018 },        /* SR: 10011 */
114
    { 1408,  8018,  256, 44100 },        /* SR: 10100 */
115
    { 2112,  8018,  384, 44100 },        /* SR: 10101 */
116
    { 1408,  8018, 1408,  8018 },        /* SR: 10110 */
117
    { 2112,  8018, 2112,  8018 },        /* SR: 10111 */
118
    { 1024, 11025, 1024, 11025 },        /* SR: 11000 */
119
    { 1536, 11025, 1536, 11025 },        /* SR: 11001 */
120
    {  512, 22050,  512, 22050 },        /* SR: 11010 */
121
    {  768, 22050,  768, 22050 },        /* SR: 11011 */
122
    {  512, 24000,  512, 24000 },        /* SR: 11100 */
123
    {  768, 24000,  768, 24000 },        /* SR: 11101 */
124
    {  128, 88200,  128, 88200 },        /* SR: 11110 */
125
    {  192, 88200,  192, 88200 },        /* SR: 11111 */
126
};
127

    
128
static void wm8750_set_format(struct wm8750_s *s)
129
{
130
    int i;
131
    audsettings_t in_fmt;
132
    audsettings_t out_fmt;
133
    audsettings_t monoout_fmt;
134

    
135
    wm8750_out_flush(s);
136

    
137
    if (s->in[0] && *s->in[0])
138
        AUD_set_active_in(*s->in[0], 0);
139
    if (s->out[0] && *s->out[0])
140
        AUD_set_active_out(*s->out[0], 0);
141

    
142
    for (i = 0; i < IN_PORT_N; i ++)
143
        if (s->adc_voice[i]) {
144
            AUD_close_in(&s->card, s->adc_voice[i]);
145
            s->adc_voice[i] = 0;
146
        }
147
    for (i = 0; i < OUT_PORT_N; i ++)
148
        if (s->dac_voice[i]) {
149
            AUD_close_out(&s->card, s->dac_voice[i]);
150
            s->dac_voice[i] = 0;
151
        }
152

    
153
    if (!s->enable)
154
        return;
155

    
156
    /* Setup input */
157
    in_fmt.endianness = 0;
158
    in_fmt.nchannels = 2;
159
    in_fmt.freq = s->rate->adc_hz;
160
    in_fmt.fmt = AUD_FMT_S16;
161

    
162
    s->adc_voice[0] = AUD_open_in(&s->card, s->adc_voice[0],
163
                    CODEC ".input1", s, wm8750_audio_in_cb, &in_fmt);
164
    s->adc_voice[1] = AUD_open_in(&s->card, s->adc_voice[1],
165
                    CODEC ".input2", s, wm8750_audio_in_cb, &in_fmt);
166
    s->adc_voice[2] = AUD_open_in(&s->card, s->adc_voice[2],
167
                    CODEC ".input3", s, wm8750_audio_in_cb, &in_fmt);
168

    
169
    /* Setup output */
170
    out_fmt.endianness = 0;
171
    out_fmt.nchannels = 2;
172
    out_fmt.freq = s->rate->dac_hz;
173
    out_fmt.fmt = AUD_FMT_S16;
174
    monoout_fmt.endianness = 0;
175
    monoout_fmt.nchannels = 1;
176
    monoout_fmt.freq = s->rate->dac_hz;
177
    monoout_fmt.fmt = AUD_FMT_S16;
178

    
179
    s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0],
180
                    CODEC ".speaker", s, wm8750_audio_out_cb, &out_fmt);
181
    s->dac_voice[1] = AUD_open_out(&s->card, s->dac_voice[1],
182
                    CODEC ".headphone", s, wm8750_audio_out_cb, &out_fmt);
183
    /* MONOMIX is also in stereo for simplicity */
184
    s->dac_voice[2] = AUD_open_out(&s->card, s->dac_voice[2],
185
                    CODEC ".monomix", s, wm8750_audio_out_cb, &out_fmt);
186
    /* no sense emulating OUT3 which is a mix of other outputs */
187

    
188
    /* We should connect the left and right channels to their
189
     * respective inputs/outputs but we have completely no need
190
     * for mixing or combining paths to different ports, so we
191
     * connect both channels to where the left channel is routed.  */
192
    if (s->in[0] && *s->in[0])
193
        AUD_set_active_in(*s->in[0], 1);
194
    if (s->out[0] && *s->out[0])
195
        AUD_set_active_out(*s->out[0], 1);
196
}
197

    
198
static void inline wm8750_mask_update(struct wm8750_s *s)
199
{
200
#define R_ONLY        0x0000ffff
201
#define L_ONLY        0xffff0000
202
#define BOTH        (R_ONLY | L_ONLY)
203
#define NONE        (R_ONLY & L_ONLY)
204
    s->inmask =
205
            (s->inmute[0] ? R_ONLY : BOTH) &
206
            (s->inmute[1] ? L_ONLY : BOTH) &
207
            (s->mute ? NONE : BOTH);
208
    s->outmask =
209
            (s->outmute[0] ? R_ONLY : BOTH) &
210
            (s->outmute[1] ? L_ONLY : BOTH) &
211
            (s->mute ? NONE : BOTH);
212
}
213

    
214
void wm8750_reset(i2c_slave *i2c)
215
{
216
    struct wm8750_s *s = (struct wm8750_s *) i2c;
217
    s->rate = &wm_rate_table[0];
218
    s->enable = 0;
219
    wm8750_set_format(s);
220
    s->diff[0] = 0;
221
    s->diff[1] = 0;
222
    s->ds = 0;
223
    s->alc = 0;
224
    s->in[0] = &s->adc_voice[0];
225
    s->invol[0] = 0x17;
226
    s->invol[1] = 0x17;
227
    s->invol[2] = 0xc3;
228
    s->invol[3] = 0xc3;
229
    s->out[0] = &s->dac_voice[0];
230
    s->outvol[0] = 0xff;
231
    s->outvol[1] = 0xff;
232
    s->outvol[2] = 0x79;
233
    s->outvol[3] = 0x79;
234
    s->outvol[4] = 0x79;
235
    s->outvol[5] = 0x79;
236
    s->inmute[0] = 0;
237
    s->inmute[1] = 0;
238
    s->outmute[0] = 0;
239
    s->outmute[1] = 0;
240
    s->mute = 1;
241
    s->path[0] = 0;
242
    s->path[1] = 0;
243
    s->path[2] = 0;
244
    s->path[3] = 0;
245
    s->mpath[0] = 0;
246
    s->mpath[1] = 0;
247
    s->format = 0x0a;
248
    s->idx_in = sizeof(s->data_in);
249
    s->req_in = 0;
250
    s->idx_out = 0;
251
    s->req_out = 0;
252
    wm8750_mask_update(s);
253
    s->i2c_len = 0;
254
}
255

    
256
static void wm8750_event(i2c_slave *i2c, enum i2c_event event)
257
{
258
    struct wm8750_s *s = (struct wm8750_s *) i2c;
259

    
260
    switch (event) {
261
    case I2C_START_SEND:
262
        s->i2c_len = 0;
263
        break;
264
    case I2C_FINISH:
265
#ifdef VERBOSE
266
        if (s->i2c_len < 2)
267
            printf("%s: message too short (%i bytes)\n",
268
                            __FUNCTION__, s->i2c_len);
269
#endif
270
        break;
271
    default:
272
        break;
273
    }
274
}
275

    
276
#define WM8750_LINVOL        0x00
277
#define WM8750_RINVOL        0x01
278
#define WM8750_LOUT1V        0x02
279
#define WM8750_ROUT1V        0x03
280
#define WM8750_ADCDAC        0x05
281
#define WM8750_IFACE        0x07
282
#define WM8750_SRATE        0x08
283
#define WM8750_LDAC        0x0a
284
#define WM8750_RDAC        0x0b
285
#define WM8750_BASS        0x0c
286
#define WM8750_TREBLE        0x0d
287
#define WM8750_RESET        0x0f
288
#define WM8750_3D        0x10
289
#define WM8750_ALC1        0x11
290
#define WM8750_ALC2        0x12
291
#define WM8750_ALC3        0x13
292
#define WM8750_NGATE        0x14
293
#define WM8750_LADC        0x15
294
#define WM8750_RADC        0x16
295
#define WM8750_ADCTL1        0x17
296
#define WM8750_ADCTL2        0x18
297
#define WM8750_PWR1        0x19
298
#define WM8750_PWR2        0x1a
299
#define WM8750_ADCTL3        0x1b
300
#define WM8750_ADCIN        0x1f
301
#define WM8750_LADCIN        0x20
302
#define WM8750_RADCIN        0x21
303
#define WM8750_LOUTM1        0x22
304
#define WM8750_LOUTM2        0x23
305
#define WM8750_ROUTM1        0x24
306
#define WM8750_ROUTM2        0x25
307
#define WM8750_MOUTM1        0x26
308
#define WM8750_MOUTM2        0x27
309
#define WM8750_LOUT2V        0x28
310
#define WM8750_ROUT2V        0x29
311
#define WM8750_MOUTV        0x2a
312

    
313
static int wm8750_tx(i2c_slave *i2c, uint8_t data)
314
{
315
    struct wm8750_s *s = (struct wm8750_s *) i2c;
316
    uint8_t cmd;
317
    uint16_t value;
318

    
319
    if (s->i2c_len >= 2) {
320
        printf("%s: long message (%i bytes)\n", __FUNCTION__, s->i2c_len);
321
#ifdef VERBOSE
322
        return 1;
323
#endif
324
    }
325
    s->i2c_data[s->i2c_len ++] = data;
326
    if (s->i2c_len != 2)
327
        return 0;
328

    
329
    cmd = s->i2c_data[0] >> 1;
330
    value = ((s->i2c_data[0] << 8) | s->i2c_data[1]) & 0x1ff;
331

    
332
    switch (cmd) {
333
    case WM8750_LADCIN:        /* ADC Signal Path Control (Left) */
334
        s->diff[0] = (((value >> 6) & 3) == 3);        /* LINSEL */
335
        if (s->diff[0])
336
            s->in[0] = &s->adc_voice[0 + s->ds * 1];
337
        else
338
            s->in[0] = &s->adc_voice[((value >> 6) & 3) * 1 + 0];
339
        break;
340

    
341
    case WM8750_RADCIN:        /* ADC Signal Path Control (Right) */
342
        s->diff[1] = (((value >> 6) & 3) == 3);        /* RINSEL */
343
        if (s->diff[1])
344
            s->in[1] = &s->adc_voice[0 + s->ds * 1];
345
        else
346
            s->in[1] = &s->adc_voice[((value >> 6) & 3) * 1 + 0];
347
        break;
348

    
349
    case WM8750_ADCIN:        /* ADC Input Mode */
350
        s->ds = (value >> 8) & 1;        /* DS */
351
        if (s->diff[0])
352
            s->in[0] = &s->adc_voice[0 + s->ds * 1];
353
        if (s->diff[1])
354
            s->in[1] = &s->adc_voice[0 + s->ds * 1];
355
        s->monomix[0] = (value >> 6) & 3;        /* MONOMIX */
356
        break;
357

    
358
    case WM8750_ADCTL1:        /* Additional Control (1) */
359
        s->monomix[1] = (value >> 1) & 1;        /* DMONOMIX */
360
        break;
361

    
362
    case WM8750_PWR1:        /* Power Management (1) */
363
        s->enable = ((value >> 6) & 7) == 3;        /* VMIDSEL, VREF */
364
        wm8750_set_format(s);
365
        break;
366

    
367
    case WM8750_LINVOL:        /* Left Channel PGA */
368
        s->invol[0] = value & 0x3f;                /* LINVOL */
369
        s->inmute[0] = (value >> 7) & 1;        /* LINMUTE */
370
        wm8750_mask_update(s);
371
        break;
372

    
373
    case WM8750_RINVOL:        /* Right Channel PGA */
374
        s->invol[1] = value & 0x3f;                /* RINVOL */
375
        s->inmute[1] = (value >> 7) & 1;        /* RINMUTE */
376
        wm8750_mask_update(s);
377
        break;
378

    
379
    case WM8750_ADCDAC:        /* ADC and DAC Control */
380
        s->pol = (value >> 5) & 3;                /* ADCPOL */
381
        s->mute = (value >> 3) & 1;                /* DACMU */
382
        wm8750_mask_update(s);
383
        break;
384

    
385
    case WM8750_ADCTL3:        /* Additional Control (3) */
386
        break;
387

    
388
    case WM8750_LADC:        /* Left ADC Digital Volume */
389
        s->invol[2] = value & 0xff;                /* LADCVOL */
390
        break;
391

    
392
    case WM8750_RADC:        /* Right ADC Digital Volume */
393
        s->invol[3] = value & 0xff;                /* RADCVOL */
394
        break;
395

    
396
    case WM8750_ALC1:        /* ALC Control (1) */
397
        s->alc = (value >> 7) & 3;                /* ALCSEL */
398
        break;
399

    
400
    case WM8750_NGATE:        /* Noise Gate Control */
401
    case WM8750_3D:        /* 3D enhance */
402
        break;
403

    
404
    case WM8750_LDAC:        /* Left Channel Digital Volume */
405
        s->outvol[0] = value & 0xff;                /* LDACVOL */
406
        break;
407

    
408
    case WM8750_RDAC:        /* Right Channel Digital Volume */
409
        s->outvol[1] = value & 0xff;                /* RDACVOL */
410
        break;
411

    
412
    case WM8750_BASS:        /* Bass Control */
413
        break;
414

    
415
    case WM8750_LOUTM1:        /* Left Mixer Control (1) */
416
        s->path[0] = (value >> 8) & 1;                /* LD2LO */
417
        break;
418

    
419
    case WM8750_LOUTM2:        /* Left Mixer Control (2) */
420
        s->path[1] = (value >> 8) & 1;                /* RD2LO */
421
        break;
422

    
423
    case WM8750_ROUTM1:        /* Right Mixer Control (1) */
424
        s->path[2] = (value >> 8) & 1;                /* LD2RO */
425
        break;
426

    
427
    case WM8750_ROUTM2:        /* Right Mixer Control (2) */
428
        s->path[3] = (value >> 8) & 1;                /* RD2RO */
429
        break;
430

    
431
    case WM8750_MOUTM1:        /* Mono Mixer Control (1) */
432
        s->mpath[0] = (value >> 8) & 1;                /* LD2MO */
433
        break;
434

    
435
    case WM8750_MOUTM2:        /* Mono Mixer Control (2) */
436
        s->mpath[1] = (value >> 8) & 1;                /* RD2MO */
437
        break;
438

    
439
    case WM8750_LOUT1V:        /* LOUT1 Volume */
440
        s->outvol[2] = value & 0x7f;                /* LOUT2VOL */
441
        break;
442

    
443
    case WM8750_LOUT2V:        /* LOUT2 Volume */
444
        s->outvol[4] = value & 0x7f;                /* LOUT2VOL */
445
        break;
446

    
447
    case WM8750_ROUT1V:        /* ROUT1 Volume */
448
        s->outvol[3] = value & 0x7f;                /* ROUT2VOL */
449
        break;
450

    
451
    case WM8750_ROUT2V:        /* ROUT2 Volume */
452
        s->outvol[5] = value & 0x7f;                /* ROUT2VOL */
453
        break;
454

    
455
    case WM8750_MOUTV:        /* MONOOUT Volume */
456
        s->outvol[6] = value & 0x7f;                /* MONOOUTVOL */
457
        break;
458

    
459
    case WM8750_ADCTL2:        /* Additional Control (2) */
460
        break;
461

    
462
    case WM8750_PWR2:        /* Power Management (2) */
463
        s->power = value & 0x7e;
464
        break;
465

    
466
    case WM8750_IFACE:        /* Digital Audio Interface Format */
467
#ifdef VERBOSE
468
        if (value & 0x40)                        /* MS */
469
            printf("%s: attempt to enable Master Mode\n", __FUNCTION__);
470
#endif
471
        s->format = value;
472
        wm8750_set_format(s);
473
        break;
474

    
475
    case WM8750_SRATE:        /* Clocking and Sample Rate Control */
476
        s->rate = &wm_rate_table[(value >> 1) & 0x1f];
477
        wm8750_set_format(s);
478
        break;
479

    
480
    case WM8750_RESET:        /* Reset */
481
        wm8750_reset(&s->i2c);
482
        break;
483

    
484
#ifdef VERBOSE
485
    default:
486
        printf("%s: unknown register %02x\n", __FUNCTION__, cmd);
487
#endif
488
    }
489

    
490
    return 0;
491
}
492

    
493
static int wm8750_rx(i2c_slave *i2c)
494
{
495
    return 0x00;
496
}
497

    
498
static void wm8750_save(QEMUFile *f, void *opaque)
499
{
500
    struct wm8750_s *s = (struct wm8750_s *) opaque;
501
    int i;
502
    qemu_put_8s(f, &s->i2c_data[0]);
503
    qemu_put_8s(f, &s->i2c_data[1]);
504
    qemu_put_be32(f, s->i2c_len);
505
    qemu_put_be32(f, s->enable);
506
    qemu_put_be32(f, s->idx_in);
507
    qemu_put_be32(f, s->req_in);
508
    qemu_put_be32(f, s->idx_out);
509
    qemu_put_be32(f, s->req_out);
510

    
511
    for (i = 0; i < 7; i ++)
512
        qemu_put_8s(f, &s->outvol[i]);
513
    for (i = 0; i < 2; i ++)
514
        qemu_put_8s(f, &s->outmute[i]);
515
    for (i = 0; i < 4; i ++)
516
        qemu_put_8s(f, &s->invol[i]);
517
    for (i = 0; i < 2; i ++)
518
        qemu_put_8s(f, &s->inmute[i]);
519

    
520
    for (i = 0; i < 2; i ++)
521
        qemu_put_8s(f, &s->diff[i]);
522
    qemu_put_8s(f, &s->pol);
523
    qemu_put_8s(f, &s->ds);
524
    for (i = 0; i < 2; i ++)
525
        qemu_put_8s(f, &s->monomix[i]);
526
    qemu_put_8s(f, &s->alc);
527
    qemu_put_8s(f, &s->mute);
528
    for (i = 0; i < 4; i ++)
529
        qemu_put_8s(f, &s->path[i]);
530
    for (i = 0; i < 2; i ++)
531
        qemu_put_8s(f, &s->mpath[i]);
532
    qemu_put_8s(f, &s->format);
533
    qemu_put_8s(f, &s->power);
534
    qemu_put_be32s(f, &s->inmask);
535
    qemu_put_be32s(f, &s->outmask);
536
    qemu_put_byte(f, (s->rate - wm_rate_table) / sizeof(*s->rate));
537
    i2c_slave_save(f, &s->i2c);
538
}
539

    
540
static int wm8750_load(QEMUFile *f, void *opaque, int version_id)
541
{
542
    struct wm8750_s *s = (struct wm8750_s *) opaque;
543
    int i;
544
    qemu_get_8s(f, &s->i2c_data[0]);
545
    qemu_get_8s(f, &s->i2c_data[1]);
546
    s->i2c_len = qemu_get_be32(f);
547
    s->enable = qemu_get_be32(f);
548
    s->idx_in = qemu_get_be32(f);
549
    s->req_in = qemu_get_be32(f);
550
    s->idx_out = qemu_get_be32(f);
551
    s->req_out = qemu_get_be32(f);
552

    
553
    for (i = 0; i < 7; i ++)
554
        qemu_get_8s(f, &s->outvol[i]);
555
    for (i = 0; i < 2; i ++)
556
        qemu_get_8s(f, &s->outmute[i]);
557
    for (i = 0; i < 4; i ++)
558
        qemu_get_8s(f, &s->invol[i]);
559
    for (i = 0; i < 2; i ++)
560
        qemu_get_8s(f, &s->inmute[i]);
561

    
562
    for (i = 0; i < 2; i ++)
563
        qemu_get_8s(f, &s->diff[i]);
564
    qemu_get_8s(f, &s->pol);
565
    qemu_get_8s(f, &s->ds);
566
    for (i = 0; i < 2; i ++)
567
        qemu_get_8s(f, &s->monomix[i]);
568
    qemu_get_8s(f, &s->alc);
569
    qemu_get_8s(f, &s->mute);
570
    for (i = 0; i < 4; i ++)
571
        qemu_get_8s(f, &s->path[i]);
572
    for (i = 0; i < 2; i ++)
573
        qemu_get_8s(f, &s->mpath[i]);
574
    qemu_get_8s(f, &s->format);
575
    qemu_get_8s(f, &s->power);
576
    qemu_get_be32s(f, &s->inmask);
577
    qemu_get_be32s(f, &s->outmask);
578
    s->rate = &wm_rate_table[(uint8_t) qemu_get_byte(f) & 0x1f];
579
    i2c_slave_load(f, &s->i2c);
580
    return 0;
581
}
582

    
583
static int wm8750_iid = 0;
584

    
585
i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio)
586
{
587
    struct wm8750_s *s = (struct wm8750_s *)
588
            i2c_slave_init(bus, 0, sizeof(struct wm8750_s));
589
    s->i2c.event = wm8750_event;
590
    s->i2c.recv = wm8750_rx;
591
    s->i2c.send = wm8750_tx;
592

    
593
    AUD_register_card(audio, CODEC, &s->card);
594
    wm8750_reset(&s->i2c);
595

    
596
    register_savevm(CODEC, wm8750_iid ++, 0, wm8750_save, wm8750_load, s);
597

    
598
    return &s->i2c;
599
}
600

    
601
#if 0
602
static void wm8750_fini(i2c_slave *i2c)
603
{
604
    struct wm8750_s *s = (struct wm8750_s *) i2c;
605
    wm8750_reset(&s->i2c);
606
    AUD_remove_card(&s->card);
607
    qemu_free(s);
608
}
609
#endif
610

    
611
void wm8750_data_req_set(i2c_slave *i2c,
612
                void (*data_req)(void *, int, int), void *opaque)
613
{
614
    struct wm8750_s *s = (struct wm8750_s *) i2c;
615
    s->data_req = data_req;
616
    s->opaque = opaque;
617
}
618

    
619
void wm8750_dac_dat(void *opaque, uint32_t sample)
620
{
621
    struct wm8750_s *s = (struct wm8750_s *) opaque;
622
    uint32_t *data = (uint32_t *) &s->data_out[s->idx_out];
623
    *data = sample & s->outmask;
624
    s->req_out -= 4;
625
    s->idx_out += 4;
626
    if (s->idx_out >= sizeof(s->data_out) || s->req_out <= 0)
627
        wm8750_out_flush(s);
628
}
629

    
630
uint32_t wm8750_adc_dat(void *opaque)
631
{
632
    struct wm8750_s *s = (struct wm8750_s *) opaque;
633
    uint32_t *data;
634
    if (s->idx_in >= sizeof(s->data_in))
635
        wm8750_in_load(s);
636
    data = (uint32_t *) &s->data_in[s->idx_in];
637
    s->req_in -= 4;
638
    s->idx_in += 4;
639
    return *data & s->inmask;
640
}