245d56fb0cb70c8cc856705396205cbe695f1a2b
[qemu] / hw / wm8750.c
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;
59     if (!s->idx_out)
60         return;
61     sent = AUD_write(*s->out[0], s->data_out, 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 #if 0
72     wm8750_in_load(s);
73 #endif
74 }
75
76 static void wm8750_audio_out_cb(void *opaque, int free_b)
77 {
78     struct wm8750_s *s = (struct wm8750_s *) opaque;
79     wm8750_out_flush(s);
80
81     s->req_out = free_b;
82     s->data_req(s->opaque, free_b >> 2, s->req_in >> 2);
83 }
84
85 struct wm_rate_s {
86     int adc;
87     int adc_hz;
88     int dac;
89     int dac_hz;
90 };
91
92 static const struct wm_rate_s wm_rate_table[] = {
93     {  256, 48000,  256, 48000 },       /* SR: 00000 */
94     {  384, 48000,  384, 48000 },       /* SR: 00001 */
95     {  256, 48000, 1536,  8000 },       /* SR: 00010 */
96     {  384, 48000, 2304,  8000 },       /* SR: 00011 */
97     { 1536,  8000,  256, 48000 },       /* SR: 00100 */
98     { 2304,  8000,  384, 48000 },       /* SR: 00101 */
99     { 1536,  8000, 1536,  8000 },       /* SR: 00110 */
100     { 2304,  8000, 2304,  8000 },       /* SR: 00111 */
101     { 1024, 12000, 1024, 12000 },       /* SR: 01000 */
102     { 1526, 12000, 1536, 12000 },       /* SR: 01001 */
103     {  768, 16000,  768, 16000 },       /* SR: 01010 */
104     { 1152, 16000, 1152, 16000 },       /* SR: 01011 */
105     {  384, 32000,  384, 32000 },       /* SR: 01100 */
106     {  576, 32000,  576, 32000 },       /* SR: 01101 */
107     {  128, 96000,  128, 96000 },       /* SR: 01110 */
108     {  192, 96000,  192, 96000 },       /* SR: 01111 */
109     {  256, 44100,  256, 44100 },       /* SR: 10000 */
110     {  384, 44100,  384, 44100 },       /* SR: 10001 */
111     {  256, 44100, 1408,  8018 },       /* SR: 10010 */
112     {  384, 44100, 2112,  8018 },       /* SR: 10011 */
113     { 1408,  8018,  256, 44100 },       /* SR: 10100 */
114     { 2112,  8018,  384, 44100 },       /* SR: 10101 */
115     { 1408,  8018, 1408,  8018 },       /* SR: 10110 */
116     { 2112,  8018, 2112,  8018 },       /* SR: 10111 */
117     { 1024, 11025, 1024, 11025 },       /* SR: 11000 */
118     { 1536, 11025, 1536, 11025 },       /* SR: 11001 */
119     {  512, 22050,  512, 22050 },       /* SR: 11010 */
120     {  768, 22050,  768, 22050 },       /* SR: 11011 */
121     {  512, 24000,  512, 24000 },       /* SR: 11100 */
122     {  768, 24000,  768, 24000 },       /* SR: 11101 */
123     {  128, 88200,  128, 88200 },       /* SR: 11110 */
124     {  192, 88200,  128, 88200 },       /* SR: 11111 */
125 };
126
127 void wm8750_set_format(struct wm8750_s *s)
128 {
129     int i;
130     audsettings_t in_fmt;
131     audsettings_t out_fmt;
132     audsettings_t monoout_fmt;
133
134     wm8750_out_flush(s);
135
136     if (s->in[0] && *s->in[0])
137         AUD_set_active_in(*s->in[0], 0);
138     if (s->out[0] && *s->out[0])
139         AUD_set_active_out(*s->out[0], 0);
140
141     for (i = 0; i < IN_PORT_N; i ++)
142         if (s->adc_voice[i]) {
143             AUD_close_in(&s->card, s->adc_voice[i]);
144             s->adc_voice[i] = 0;
145         }
146     for (i = 0; i < OUT_PORT_N; i ++)
147         if (s->dac_voice[i]) {
148             AUD_close_out(&s->card, s->dac_voice[i]);
149             s->dac_voice[i] = 0;
150         }
151
152     if (!s->enable)
153         return;
154
155     /* Setup input */
156     in_fmt.endianness = 0;
157     in_fmt.nchannels = 2;
158     in_fmt.freq = s->rate->adc_hz;
159     in_fmt.fmt = AUD_FMT_S16;
160
161     s->adc_voice[0] = AUD_open_in(&s->card, s->adc_voice[0],
162                     CODEC ".input1", s, wm8750_audio_in_cb, &in_fmt);
163     s->adc_voice[1] = AUD_open_in(&s->card, s->adc_voice[1],
164                     CODEC ".input2", s, wm8750_audio_in_cb, &in_fmt);
165     s->adc_voice[2] = AUD_open_in(&s->card, s->adc_voice[2],
166                     CODEC ".input3", s, wm8750_audio_in_cb, &in_fmt);
167
168     /* Setup output */
169     out_fmt.endianness = 0;
170     out_fmt.nchannels = 2;
171     out_fmt.freq = s->rate->dac_hz;
172     out_fmt.fmt = AUD_FMT_S16;
173     monoout_fmt.endianness = 0;
174     monoout_fmt.nchannels = 1;
175     monoout_fmt.freq = s->rate->dac_hz;
176     monoout_fmt.fmt = AUD_FMT_S16;
177
178     s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0],
179                     CODEC ".speaker", s, wm8750_audio_out_cb, &out_fmt);
180     s->dac_voice[1] = AUD_open_out(&s->card, s->dac_voice[1],
181                     CODEC ".headphone", s, wm8750_audio_out_cb, &out_fmt);
182     /* MONOMIX is also in stereo for simplicity */
183     s->dac_voice[2] = AUD_open_out(&s->card, s->dac_voice[2],
184                     CODEC ".monomix", s, wm8750_audio_out_cb, &out_fmt);
185     /* no sense emulating OUT3 which is a mix of other outputs */
186
187     /* We should connect the left and right channels to their
188      * respective inputs/outputs but we have completely no need
189      * for mixing or combining paths to different ports, so we
190      * connect both channels to where the left channel is routed.  */
191     if (s->in[0] && *s->in[0])
192         AUD_set_active_in(*s->in[0], 1);
193     if (s->out[0] && *s->out[0])
194         AUD_set_active_out(*s->out[0], 1);
195 }
196
197 void inline wm8750_mask_update(struct wm8750_s *s)
198 {
199 #define R_ONLY  0x0000ffff
200 #define L_ONLY  0xffff0000
201 #define BOTH    (R_ONLY | L_ONLY)
202 #define NONE    (R_ONLY & L_ONLY)
203     s->inmask =
204             (s->inmute[0] ? R_ONLY : BOTH) &
205             (s->inmute[1] ? L_ONLY : BOTH) &
206             (s->mute ? NONE : BOTH);
207     s->outmask =
208             (s->outmute[0] ? R_ONLY : BOTH) &
209             (s->outmute[1] ? L_ONLY : BOTH) &
210             (s->mute ? NONE : BOTH);
211 }
212
213 void wm8750_reset(i2c_slave *i2c)
214 {
215     struct wm8750_s *s = (struct wm8750_s *) i2c;
216     s->enable = 0;
217     wm8750_set_format(s);
218     s->diff[0] = 0;
219     s->diff[1] = 0;
220     s->ds = 0;
221     s->alc = 0;
222     s->in[0] = &s->adc_voice[0];
223     s->invol[0] = 0x17;
224     s->invol[1] = 0x17;
225     s->invol[2] = 0xc3;
226     s->invol[3] = 0xc3;
227     s->out[0] = &s->dac_voice[0];
228     s->outvol[0] = 0xff;
229     s->outvol[1] = 0xff;
230     s->outvol[2] = 0x79;
231     s->outvol[3] = 0x79;
232     s->outvol[4] = 0x79;
233     s->outvol[5] = 0x79;
234     s->inmute[0] = 0;
235     s->inmute[1] = 0;
236     s->outmute[0] = 0;
237     s->outmute[1] = 0;
238     s->mute = 1;
239     s->path[0] = 0;
240     s->path[1] = 0;
241     s->path[2] = 0;
242     s->path[3] = 0;
243     s->mpath[0] = 0;
244     s->mpath[1] = 0;
245     s->format = 0x0a;
246     s->idx_in = sizeof(s->data_in);
247     s->req_in = 0;
248     s->idx_out = 0;
249     s->req_out = 0;
250     wm8750_mask_update(s);
251     s->i2c_len = 0;
252 }
253
254 static void wm8750_event(i2c_slave *i2c, enum i2c_event event)
255 {
256     struct wm8750_s *s = (struct wm8750_s *) i2c;
257
258     switch (event) {
259     case I2C_START_SEND:
260         s->i2c_len = 0;
261         break;
262     case I2C_FINISH:
263 #ifdef VERBOSE
264         if (s->i2c_len < 2)
265             printf("%s: message too short (%i bytes)\n",
266                             __FUNCTION__, s->i2c_len);
267 #endif
268         break;
269     default:
270         break;
271     }
272 }
273
274 #define WM8750_LINVOL   0x00
275 #define WM8750_RINVOL   0x01
276 #define WM8750_LOUT1V   0x02
277 #define WM8750_ROUT1V   0x03
278 #define WM8750_ADCDAC   0x05
279 #define WM8750_IFACE    0x07
280 #define WM8750_SRATE    0x08
281 #define WM8750_LDAC     0x0a
282 #define WM8750_RDAC     0x0b
283 #define WM8750_BASS     0x0c
284 #define WM8750_TREBLE   0x0d
285 #define WM8750_RESET    0x0f
286 #define WM8750_3D       0x10
287 #define WM8750_ALC1     0x11
288 #define WM8750_ALC2     0x12
289 #define WM8750_ALC3     0x13
290 #define WM8750_NGATE    0x14
291 #define WM8750_LADC     0x15
292 #define WM8750_RADC     0x16
293 #define WM8750_ADCTL1   0x17
294 #define WM8750_ADCTL2   0x18
295 #define WM8750_PWR1     0x19
296 #define WM8750_PWR2     0x1a
297 #define WM8750_ADCTL3   0x1b
298 #define WM8750_ADCIN    0x1f
299 #define WM8750_LADCIN   0x20
300 #define WM8750_RADCIN   0x21
301 #define WM8750_LOUTM1   0x22
302 #define WM8750_LOUTM2   0x23
303 #define WM8750_ROUTM1   0x24
304 #define WM8750_ROUTM2   0x25
305 #define WM8750_MOUTM1   0x26
306 #define WM8750_MOUTM2   0x27
307 #define WM8750_LOUT2V   0x28
308 #define WM8750_ROUT2V   0x29
309 #define WM8750_MOUTV    0x2a
310
311 static int wm8750_tx(i2c_slave *i2c, uint8_t data)
312 {
313     struct wm8750_s *s = (struct wm8750_s *) i2c;
314     uint8_t cmd;
315     uint16_t value;
316
317     if (s->i2c_len >= 2) {
318         printf("%s: long message (%i bytes)\n", __FUNCTION__, s->i2c_len);
319 #ifdef VERBOSE
320         return 1;
321 #endif
322     }
323     s->i2c_data[s->i2c_len ++] = data;
324     if (s->i2c_len != 2)
325         return 0;
326
327     cmd = s->i2c_data[0] >> 1;
328     value = ((s->i2c_data[0] << 8) | s->i2c_data[1]) & 0x1ff;
329
330     switch (cmd) {
331     case WM8750_LADCIN: /* ADC Signal Path Control (Left) */
332         s->diff[0] = (((value >> 6) & 3) == 3); /* LINSEL */
333         if (s->diff[0])
334             s->in[0] = &s->adc_voice[0 + s->ds * 1];
335         else
336             s->in[0] = &s->adc_voice[((value >> 6) & 3) * 1 + 0];
337         break;
338
339     case WM8750_RADCIN: /* ADC Signal Path Control (Right) */
340         s->diff[1] = (((value >> 6) & 3) == 3); /* RINSEL */
341         if (s->diff[1])
342             s->in[1] = &s->adc_voice[0 + s->ds * 1];
343         else
344             s->in[1] = &s->adc_voice[((value >> 6) & 3) * 1 + 0];
345         break;
346
347     case WM8750_ADCIN:  /* ADC Input Mode */
348         s->ds = (value >> 8) & 1;       /* DS */
349         if (s->diff[0])
350             s->in[0] = &s->adc_voice[0 + s->ds * 1];
351         if (s->diff[1])
352             s->in[1] = &s->adc_voice[0 + s->ds * 1];
353         s->monomix[0] = (value >> 6) & 3;       /* MONOMIX */
354         break;
355
356     case WM8750_ADCTL1: /* Additional Control (1) */
357         s->monomix[1] = (value >> 1) & 1;       /* DMONOMIX */
358         break;
359
360     case WM8750_PWR1:   /* Power Management (1) */
361         s->enable = ((value >> 6) & 7) == 3;    /* VMIDSEL, VREF */
362         wm8750_set_format(s);
363         break;
364
365     case WM8750_LINVOL: /* Left Channel PGA */
366         s->invol[0] = value & 0x3f;             /* LINVOL */
367         s->inmute[0] = (value >> 7) & 1;        /* LINMUTE */
368         wm8750_mask_update(s);
369         break;
370
371     case WM8750_RINVOL: /* Right Channel PGA */
372         s->invol[1] = value & 0x3f;             /* RINVOL */
373         s->inmute[1] = (value >> 7) & 1;        /* RINMUTE */
374         wm8750_mask_update(s);
375         break;
376
377     case WM8750_ADCDAC: /* ADC and DAC Control */
378         s->pol = (value >> 5) & 3;              /* ADCPOL */
379         s->mute = (value >> 3) & 1;             /* DACMU */
380         wm8750_mask_update(s);
381         break;
382
383     case WM8750_ADCTL3: /* Additional Control (3) */
384         break;
385
386     case WM8750_LADC:   /* Left ADC Digital Volume */
387         s->invol[2] = value & 0xff;             /* LADCVOL */
388         break;
389
390     case WM8750_RADC:   /* Right ADC Digital Volume */
391         s->invol[3] = value & 0xff;             /* RADCVOL */
392         break;
393
394     case WM8750_ALC1:   /* ALC Control (1) */
395         s->alc = (value >> 7) & 3;              /* ALCSEL */
396         break;
397
398     case WM8750_NGATE:  /* Noise Gate Control */
399     case WM8750_3D:     /* 3D enhance */
400         break;
401
402     case WM8750_LDAC:   /* Left Channel Digital Volume */
403         s->outvol[0] = value & 0xff;            /* LDACVOL */
404         break;
405
406     case WM8750_RDAC:   /* Right Channel Digital Volume */
407         s->outvol[1] = value & 0xff;            /* RDACVOL */
408         break;
409
410     case WM8750_BASS:   /* Bass Control */
411         break;
412
413     case WM8750_LOUTM1: /* Left Mixer Control (1) */
414         s->path[0] = (value >> 8) & 1;          /* LD2LO */
415         break;
416
417     case WM8750_LOUTM2: /* Left Mixer Control (2) */
418         s->path[1] = (value >> 8) & 1;          /* RD2LO */
419         break;
420
421     case WM8750_ROUTM1: /* Right Mixer Control (1) */
422         s->path[2] = (value >> 8) & 1;          /* LD2RO */
423         break;
424
425     case WM8750_ROUTM2: /* Right Mixer Control (2) */
426         s->path[3] = (value >> 8) & 1;          /* RD2RO */
427         break;
428
429     case WM8750_MOUTM1: /* Mono Mixer Control (1) */
430         s->mpath[0] = (value >> 8) & 1;         /* LD2MO */
431         break;
432
433     case WM8750_MOUTM2: /* Mono Mixer Control (2) */
434         s->mpath[1] = (value >> 8) & 1;         /* RD2MO */
435         break;
436
437     case WM8750_LOUT1V: /* LOUT1 Volume */
438         s->outvol[2] = value & 0x7f;            /* LOUT2VOL */
439         break;
440
441     case WM8750_LOUT2V: /* LOUT2 Volume */
442         s->outvol[4] = value & 0x7f;            /* LOUT2VOL */
443         break;
444
445     case WM8750_ROUT1V: /* ROUT1 Volume */
446         s->outvol[3] = value & 0x7f;            /* ROUT2VOL */
447         break;
448
449     case WM8750_ROUT2V: /* ROUT2 Volume */
450         s->outvol[5] = value & 0x7f;            /* ROUT2VOL */
451         break;
452
453     case WM8750_MOUTV:  /* MONOOUT Volume */
454         s->outvol[6] = value & 0x7f;            /* MONOOUTVOL */
455         break;
456
457     case WM8750_ADCTL2: /* Additional Control (2) */
458         break;
459
460     case WM8750_PWR2:   /* Power Management (2) */
461         s->power = value & 0x7e;
462         break;
463
464     case WM8750_IFACE:  /* Digital Audio Interface Format */
465 #ifdef VERBOSE
466         if (value & 0x40)                       /* MS */
467             printf("%s: attempt to enable Master Mode\n", __FUNCTION__);
468 #endif
469         s->format = value;
470         wm8750_set_format(s);
471         break;
472
473     case WM8750_SRATE:  /* Clocking and Sample Rate Control */
474         s->rate = &wm_rate_table[(value >> 1) & 0x1f];
475         wm8750_set_format(s);
476         break;
477
478     case WM8750_RESET:  /* Reset */
479         wm8750_reset(&s->i2c);
480         break;
481
482 #ifdef VERBOSE
483     default:
484         printf("%s: unknown register %02x\n", __FUNCTION__, cmd);
485 #endif
486     }
487
488     return 0;
489 }
490
491 static int wm8750_rx(i2c_slave *i2c)
492 {
493     return 0x00;
494 }
495
496 static void wm8750_save(QEMUFile *f, void *opaque)
497 {
498     struct wm8750_s *s = (struct wm8750_s *) opaque;
499     int i;
500     qemu_put_8s(f, &s->i2c_data[0]);
501     qemu_put_8s(f, &s->i2c_data[1]);
502     qemu_put_be32(f, s->i2c_len);
503     qemu_put_be32(f, s->enable);
504     qemu_put_be32(f, s->idx_in);
505     qemu_put_be32(f, s->req_in);
506     qemu_put_be32(f, s->idx_out);
507     qemu_put_be32(f, s->req_out);
508
509     for (i = 0; i < 7; i ++)
510         qemu_put_8s(f, &s->outvol[i]);
511     for (i = 0; i < 2; i ++)
512         qemu_put_8s(f, &s->outmute[i]);
513     for (i = 0; i < 4; i ++)
514         qemu_put_8s(f, &s->invol[i]);
515     for (i = 0; i < 2; i ++)
516         qemu_put_8s(f, &s->inmute[i]);
517
518     for (i = 0; i < 2; i ++)
519         qemu_put_8s(f, &s->diff[i]);
520     qemu_put_8s(f, &s->pol);
521     qemu_put_8s(f, &s->ds);
522     for (i = 0; i < 2; i ++)
523         qemu_put_8s(f, &s->monomix[i]);
524     qemu_put_8s(f, &s->alc);
525     qemu_put_8s(f, &s->mute);
526     for (i = 0; i < 4; i ++)
527         qemu_put_8s(f, &s->path[i]);
528     for (i = 0; i < 2; i ++)
529         qemu_put_8s(f, &s->mpath[i]);
530     qemu_put_8s(f, &s->format);
531     qemu_put_8s(f, &s->power);
532     qemu_put_be32s(f, &s->inmask);
533     qemu_put_be32s(f, &s->outmask);
534     qemu_put_byte(f, (s->rate - wm_rate_table) / sizeof(*s->rate));
535     i2c_slave_save(f, &s->i2c);
536 }
537
538 static int wm8750_load(QEMUFile *f, void *opaque, int version_id)
539 {
540     struct wm8750_s *s = (struct wm8750_s *) opaque;
541     int i;
542     qemu_get_8s(f, &s->i2c_data[0]);
543     qemu_get_8s(f, &s->i2c_data[1]);
544     s->i2c_len = qemu_get_be32(f);
545     s->enable = qemu_get_be32(f);
546     s->idx_in = qemu_get_be32(f);
547     s->req_in = qemu_get_be32(f);
548     s->idx_out = qemu_get_be32(f);
549     s->req_out = qemu_get_be32(f);
550
551     for (i = 0; i < 7; i ++)
552         qemu_get_8s(f, &s->outvol[i]);
553     for (i = 0; i < 2; i ++)
554         qemu_get_8s(f, &s->outmute[i]);
555     for (i = 0; i < 4; i ++)
556         qemu_get_8s(f, &s->invol[i]);
557     for (i = 0; i < 2; i ++)
558         qemu_get_8s(f, &s->inmute[i]);
559
560     for (i = 0; i < 2; i ++)
561         qemu_get_8s(f, &s->diff[i]);
562     qemu_get_8s(f, &s->pol);
563     qemu_get_8s(f, &s->ds);
564     for (i = 0; i < 2; i ++)
565         qemu_get_8s(f, &s->monomix[i]);
566     qemu_get_8s(f, &s->alc);
567     qemu_get_8s(f, &s->mute);
568     for (i = 0; i < 4; i ++)
569         qemu_get_8s(f, &s->path[i]);
570     for (i = 0; i < 2; i ++)
571         qemu_get_8s(f, &s->mpath[i]);
572     qemu_get_8s(f, &s->format);
573     qemu_get_8s(f, &s->power);
574     qemu_get_be32s(f, &s->inmask);
575     qemu_get_be32s(f, &s->outmask);
576     s->rate = &wm_rate_table[(uint8_t) qemu_get_byte(f) & 0x1f];
577     i2c_slave_load(f, &s->i2c);
578     return 0;
579 }
580
581 static int wm8750_iid = 0;
582
583 i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio)
584 {
585     struct wm8750_s *s = (struct wm8750_s *)
586             i2c_slave_init(bus, 0, sizeof(struct wm8750_s));
587     s->i2c.event = wm8750_event;
588     s->i2c.recv = wm8750_rx;
589     s->i2c.send = wm8750_tx;
590
591     AUD_register_card(audio, CODEC, &s->card);
592     wm8750_reset(&s->i2c);
593
594     register_savevm(CODEC, wm8750_iid ++, 0, wm8750_save, wm8750_load, s);
595
596     return &s->i2c;
597 }
598
599 void wm8750_fini(i2c_slave *i2c)
600 {
601     struct wm8750_s *s = (struct wm8750_s *) i2c;
602     wm8750_reset(&s->i2c);
603     AUD_remove_card(&s->card);
604     qemu_free(s);
605 }
606
607 void wm8750_data_req_set(i2c_slave *i2c,
608                 void (*data_req)(void *, int, int), void *opaque)
609 {
610     struct wm8750_s *s = (struct wm8750_s *) i2c;
611     s->data_req = data_req;
612     s->opaque = opaque;
613 }
614
615 void wm8750_dac_dat(void *opaque, uint32_t sample)
616 {
617     struct wm8750_s *s = (struct wm8750_s *) opaque;
618     uint32_t *data = (uint32_t *) &s->data_out[s->idx_out];
619     *data = sample & s->outmask;
620     s->req_out -= 4;
621     s->idx_out += 4;
622     if (s->idx_out >= sizeof(s->data_out) || s->req_out <= 0)
623         wm8750_out_flush(s);
624 }
625
626 uint32_t wm8750_adc_dat(void *opaque)
627 {
628     struct wm8750_s *s = (struct wm8750_s *) opaque;
629     uint32_t *data;
630     if (s->idx_in >= sizeof(s->data_in))
631         wm8750_in_load(s);
632     data = (uint32_t *) &s->data_in[s->idx_in];
633     s->req_in -= 4;
634     s->idx_in += 4;
635     return *data & s->inmask;
636 }