iotests: add small-granularity mirror test
[qemu.git] / hw / audio / cs4231a.c
blob3ecd0582bf63510eaca4decd9c1a632117be3a4b
1 /*
2 * QEMU Crystal CS4231 audio chip emulation
4 * Copyright (c) 2006 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
24 #include "qemu/osdep.h"
25 #include "hw/hw.h"
26 #include "hw/audio/audio.h"
27 #include "audio/audio.h"
28 #include "hw/isa/isa.h"
29 #include "hw/qdev.h"
30 #include "qemu/timer.h"
33 Missing features:
34 ADC
35 Loopback
36 Timer
37 ADPCM
38 More...
41 /* #define DEBUG */
42 /* #define DEBUG_XLAW */
44 static struct {
45 int aci_counter;
46 } conf = {1};
48 #ifdef DEBUG
49 #define dolog(...) AUD_log ("cs4231a", __VA_ARGS__)
50 #else
51 #define dolog(...)
52 #endif
54 #define lwarn(...) AUD_log ("cs4231a", "warning: " __VA_ARGS__)
55 #define lerr(...) AUD_log ("cs4231a", "error: " __VA_ARGS__)
57 #define CS_REGS 16
58 #define CS_DREGS 32
60 #define TYPE_CS4231A "cs4231a"
61 #define CS4231A(obj) OBJECT_CHECK (CSState, (obj), TYPE_CS4231A)
63 typedef struct CSState {
64 ISADevice dev;
65 QEMUSoundCard card;
66 MemoryRegion ioports;
67 qemu_irq pic;
68 uint32_t regs[CS_REGS];
69 uint8_t dregs[CS_DREGS];
70 uint32_t irq;
71 uint32_t dma;
72 uint32_t port;
73 IsaDma *isa_dma;
74 int shift;
75 int dma_running;
76 int audio_free;
77 int transferred;
78 int aci_counter;
79 SWVoiceOut *voice;
80 int16_t *tab;
81 } CSState;
83 #define MODE2 (1 << 6)
84 #define MCE (1 << 6)
85 #define PMCE (1 << 4)
86 #define CMCE (1 << 5)
87 #define TE (1 << 6)
88 #define PEN (1 << 0)
89 #define INT (1 << 0)
90 #define IEN (1 << 1)
91 #define PPIO (1 << 6)
92 #define PI (1 << 4)
93 #define CI (1 << 5)
94 #define TI (1 << 6)
96 enum {
97 Index_Address,
98 Index_Data,
99 Status,
100 PIO_Data
103 enum {
104 Left_ADC_Input_Control,
105 Right_ADC_Input_Control,
106 Left_AUX1_Input_Control,
107 Right_AUX1_Input_Control,
108 Left_AUX2_Input_Control,
109 Right_AUX2_Input_Control,
110 Left_DAC_Output_Control,
111 Right_DAC_Output_Control,
112 FS_And_Playback_Data_Format,
113 Interface_Configuration,
114 Pin_Control,
115 Error_Status_And_Initialization,
116 MODE_And_ID,
117 Loopback_Control,
118 Playback_Upper_Base_Count,
119 Playback_Lower_Base_Count,
120 Alternate_Feature_Enable_I,
121 Alternate_Feature_Enable_II,
122 Left_Line_Input_Control,
123 Right_Line_Input_Control,
124 Timer_Low_Base,
125 Timer_High_Base,
126 RESERVED,
127 Alternate_Feature_Enable_III,
128 Alternate_Feature_Status,
129 Version_Chip_ID,
130 Mono_Input_And_Output_Control,
131 RESERVED_2,
132 Capture_Data_Format,
133 RESERVED_3,
134 Capture_Upper_Base_Count,
135 Capture_Lower_Base_Count
138 static int freqs[2][8] = {
139 { 8000, 16000, 27420, 32000, -1, -1, 48000, 9000 },
140 { 5510, 11025, 18900, 22050, 37800, 44100, 33075, 6620 }
143 /* Tables courtesy http://hazelware.luggle.com/tutorials/mulawcompression.html */
144 static int16_t MuLawDecompressTable[256] =
146 -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
147 -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
148 -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
149 -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
150 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
151 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
152 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
153 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
154 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
155 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
156 -876, -844, -812, -780, -748, -716, -684, -652,
157 -620, -588, -556, -524, -492, -460, -428, -396,
158 -372, -356, -340, -324, -308, -292, -276, -260,
159 -244, -228, -212, -196, -180, -164, -148, -132,
160 -120, -112, -104, -96, -88, -80, -72, -64,
161 -56, -48, -40, -32, -24, -16, -8, 0,
162 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
163 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
164 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
165 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
166 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
167 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
168 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
169 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
170 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
171 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
172 876, 844, 812, 780, 748, 716, 684, 652,
173 620, 588, 556, 524, 492, 460, 428, 396,
174 372, 356, 340, 324, 308, 292, 276, 260,
175 244, 228, 212, 196, 180, 164, 148, 132,
176 120, 112, 104, 96, 88, 80, 72, 64,
177 56, 48, 40, 32, 24, 16, 8, 0
180 static int16_t ALawDecompressTable[256] =
182 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
183 -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
184 -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
185 -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
186 -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
187 -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
188 -11008,-10496,-12032,-11520,-8960, -8448, -9984, -9472,
189 -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
190 -344, -328, -376, -360, -280, -264, -312, -296,
191 -472, -456, -504, -488, -408, -392, -440, -424,
192 -88, -72, -120, -104, -24, -8, -56, -40,
193 -216, -200, -248, -232, -152, -136, -184, -168,
194 -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
195 -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
196 -688, -656, -752, -720, -560, -528, -624, -592,
197 -944, -912, -1008, -976, -816, -784, -880, -848,
198 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
199 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
200 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
201 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
202 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
203 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
204 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
205 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
206 344, 328, 376, 360, 280, 264, 312, 296,
207 472, 456, 504, 488, 408, 392, 440, 424,
208 88, 72, 120, 104, 24, 8, 56, 40,
209 216, 200, 248, 232, 152, 136, 184, 168,
210 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
211 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
212 688, 656, 752, 720, 560, 528, 624, 592,
213 944, 912, 1008, 976, 816, 784, 880, 848
216 static void cs4231a_reset (DeviceState *dev)
218 CSState *s = CS4231A (dev);
220 s->regs[Index_Address] = 0x40;
221 s->regs[Index_Data] = 0x00;
222 s->regs[Status] = 0x00;
223 s->regs[PIO_Data] = 0x00;
225 s->dregs[Left_ADC_Input_Control] = 0x00;
226 s->dregs[Right_ADC_Input_Control] = 0x00;
227 s->dregs[Left_AUX1_Input_Control] = 0x88;
228 s->dregs[Right_AUX1_Input_Control] = 0x88;
229 s->dregs[Left_AUX2_Input_Control] = 0x88;
230 s->dregs[Right_AUX2_Input_Control] = 0x88;
231 s->dregs[Left_DAC_Output_Control] = 0x80;
232 s->dregs[Right_DAC_Output_Control] = 0x80;
233 s->dregs[FS_And_Playback_Data_Format] = 0x00;
234 s->dregs[Interface_Configuration] = 0x08;
235 s->dregs[Pin_Control] = 0x00;
236 s->dregs[Error_Status_And_Initialization] = 0x00;
237 s->dregs[MODE_And_ID] = 0x8a;
238 s->dregs[Loopback_Control] = 0x00;
239 s->dregs[Playback_Upper_Base_Count] = 0x00;
240 s->dregs[Playback_Lower_Base_Count] = 0x00;
241 s->dregs[Alternate_Feature_Enable_I] = 0x00;
242 s->dregs[Alternate_Feature_Enable_II] = 0x00;
243 s->dregs[Left_Line_Input_Control] = 0x88;
244 s->dregs[Right_Line_Input_Control] = 0x88;
245 s->dregs[Timer_Low_Base] = 0x00;
246 s->dregs[Timer_High_Base] = 0x00;
247 s->dregs[RESERVED] = 0x00;
248 s->dregs[Alternate_Feature_Enable_III] = 0x00;
249 s->dregs[Alternate_Feature_Status] = 0x00;
250 s->dregs[Version_Chip_ID] = 0xa0;
251 s->dregs[Mono_Input_And_Output_Control] = 0xa0;
252 s->dregs[RESERVED_2] = 0x00;
253 s->dregs[Capture_Data_Format] = 0x00;
254 s->dregs[RESERVED_3] = 0x00;
255 s->dregs[Capture_Upper_Base_Count] = 0x00;
256 s->dregs[Capture_Lower_Base_Count] = 0x00;
259 static void cs_audio_callback (void *opaque, int free)
261 CSState *s = opaque;
262 s->audio_free = free;
265 static void cs_reset_voices (CSState *s, uint32_t val)
267 int xtal;
268 struct audsettings as;
269 IsaDmaClass *k = ISADMA_GET_CLASS(s->isa_dma);
271 #ifdef DEBUG_XLAW
272 if (val == 0 || val == 32)
273 val = (1 << 4) | (1 << 5);
274 #endif
276 xtal = val & 1;
277 as.freq = freqs[xtal][(val >> 1) & 7];
279 if (as.freq == -1) {
280 lerr ("unsupported frequency (val=%#x)\n", val);
281 goto error;
284 as.nchannels = (val & (1 << 4)) ? 2 : 1;
285 as.endianness = 0;
286 s->tab = NULL;
288 switch ((val >> 5) & ((s->dregs[MODE_And_ID] & MODE2) ? 7 : 3)) {
289 case 0:
290 as.fmt = AUD_FMT_U8;
291 s->shift = as.nchannels == 2;
292 break;
294 case 1:
295 s->tab = MuLawDecompressTable;
296 goto x_law;
297 case 3:
298 s->tab = ALawDecompressTable;
299 x_law:
300 as.fmt = AUD_FMT_S16;
301 as.endianness = AUDIO_HOST_ENDIANNESS;
302 s->shift = as.nchannels == 2;
303 break;
305 case 6:
306 as.endianness = 1;
307 case 2:
308 as.fmt = AUD_FMT_S16;
309 s->shift = as.nchannels;
310 break;
312 case 7:
313 case 4:
314 lerr ("attempt to use reserved format value (%#x)\n", val);
315 goto error;
317 case 5:
318 lerr ("ADPCM 4 bit IMA compatible format is not supported\n");
319 goto error;
322 s->voice = AUD_open_out (
323 &s->card,
324 s->voice,
325 "cs4231a",
327 cs_audio_callback,
331 if (s->dregs[Interface_Configuration] & PEN) {
332 if (!s->dma_running) {
333 k->hold_DREQ(s->isa_dma, s->dma);
334 AUD_set_active_out (s->voice, 1);
335 s->transferred = 0;
337 s->dma_running = 1;
339 else {
340 if (s->dma_running) {
341 k->release_DREQ(s->isa_dma, s->dma);
342 AUD_set_active_out (s->voice, 0);
344 s->dma_running = 0;
346 return;
348 error:
349 if (s->dma_running) {
350 k->release_DREQ(s->isa_dma, s->dma);
351 AUD_set_active_out (s->voice, 0);
355 static uint64_t cs_read (void *opaque, hwaddr addr, unsigned size)
357 CSState *s = opaque;
358 uint32_t saddr, iaddr, ret;
360 saddr = addr;
361 iaddr = ~0U;
363 switch (saddr) {
364 case Index_Address:
365 ret = s->regs[saddr] & ~0x80;
366 break;
368 case Index_Data:
369 if (!(s->dregs[MODE_And_ID] & MODE2))
370 iaddr = s->regs[Index_Address] & 0x0f;
371 else
372 iaddr = s->regs[Index_Address] & 0x1f;
374 ret = s->dregs[iaddr];
375 if (iaddr == Error_Status_And_Initialization) {
376 /* keep SEAL happy */
377 if (s->aci_counter) {
378 ret |= 1 << 5;
379 s->aci_counter -= 1;
382 break;
384 default:
385 ret = s->regs[saddr];
386 break;
388 dolog ("read %d:%d -> %d\n", saddr, iaddr, ret);
389 return ret;
392 static void cs_write (void *opaque, hwaddr addr,
393 uint64_t val64, unsigned size)
395 CSState *s = opaque;
396 uint32_t saddr, iaddr, val;
398 saddr = addr;
399 val = val64;
401 switch (saddr) {
402 case Index_Address:
403 if (!(s->regs[Index_Address] & MCE) && (val & MCE)
404 && (s->dregs[Interface_Configuration] & (3 << 3)))
405 s->aci_counter = conf.aci_counter;
407 s->regs[Index_Address] = val & ~(1 << 7);
408 break;
410 case Index_Data:
411 if (!(s->dregs[MODE_And_ID] & MODE2))
412 iaddr = s->regs[Index_Address] & 0x0f;
413 else
414 iaddr = s->regs[Index_Address] & 0x1f;
416 switch (iaddr) {
417 case RESERVED:
418 case RESERVED_2:
419 case RESERVED_3:
420 lwarn ("attempt to write %#x to reserved indirect register %d\n",
421 val, iaddr);
422 break;
424 case FS_And_Playback_Data_Format:
425 if (s->regs[Index_Address] & MCE) {
426 cs_reset_voices (s, val);
428 else {
429 if (s->dregs[Alternate_Feature_Status] & PMCE) {
430 val = (val & ~0x0f) | (s->dregs[iaddr] & 0x0f);
431 cs_reset_voices (s, val);
433 else {
434 lwarn ("[P]MCE(%#x, %#x) is not set, val=%#x\n",
435 s->regs[Index_Address],
436 s->dregs[Alternate_Feature_Status],
437 val);
438 break;
441 s->dregs[iaddr] = val;
442 break;
444 case Interface_Configuration:
445 val &= ~(1 << 5); /* D5 is reserved */
446 s->dregs[iaddr] = val;
447 if (val & PPIO) {
448 lwarn ("PIO is not supported (%#x)\n", val);
449 break;
451 if (val & PEN) {
452 if (!s->dma_running) {
453 cs_reset_voices (s, s->dregs[FS_And_Playback_Data_Format]);
456 else {
457 if (s->dma_running) {
458 IsaDmaClass *k = ISADMA_GET_CLASS(s->isa_dma);
459 k->release_DREQ(s->isa_dma, s->dma);
460 AUD_set_active_out (s->voice, 0);
461 s->dma_running = 0;
464 break;
466 case Error_Status_And_Initialization:
467 lwarn ("attempt to write to read only register %d\n", iaddr);
468 break;
470 case MODE_And_ID:
471 dolog ("val=%#x\n", val);
472 if (val & MODE2)
473 s->dregs[iaddr] |= MODE2;
474 else
475 s->dregs[iaddr] &= ~MODE2;
476 break;
478 case Alternate_Feature_Enable_I:
479 if (val & TE)
480 lerr ("timer is not yet supported\n");
481 s->dregs[iaddr] = val;
482 break;
484 case Alternate_Feature_Status:
485 if ((s->dregs[iaddr] & PI) && !(val & PI)) {
486 /* XXX: TI CI */
487 qemu_irq_lower (s->pic);
488 s->regs[Status] &= ~INT;
490 s->dregs[iaddr] = val;
491 break;
493 case Version_Chip_ID:
494 lwarn ("write to Version_Chip_ID register %#x\n", val);
495 s->dregs[iaddr] = val;
496 break;
498 default:
499 s->dregs[iaddr] = val;
500 break;
502 dolog ("written value %#x to indirect register %d\n", val, iaddr);
503 break;
505 case Status:
506 if (s->regs[Status] & INT) {
507 qemu_irq_lower (s->pic);
509 s->regs[Status] &= ~INT;
510 s->dregs[Alternate_Feature_Status] &= ~(PI | CI | TI);
511 break;
513 case PIO_Data:
514 lwarn ("attempt to write value %#x to PIO register\n", val);
515 break;
519 static int cs_write_audio (CSState *s, int nchan, int dma_pos,
520 int dma_len, int len)
522 int temp, net;
523 uint8_t tmpbuf[4096];
524 IsaDmaClass *k = ISADMA_GET_CLASS(s->isa_dma);
526 temp = len;
527 net = 0;
529 while (temp) {
530 int left = dma_len - dma_pos;
531 int copied;
532 size_t to_copy;
534 to_copy = audio_MIN (temp, left);
535 if (to_copy > sizeof (tmpbuf)) {
536 to_copy = sizeof (tmpbuf);
539 copied = k->read_memory(s->isa_dma, nchan, tmpbuf, dma_pos, to_copy);
540 if (s->tab) {
541 int i;
542 int16_t linbuf[4096];
544 for (i = 0; i < copied; ++i)
545 linbuf[i] = s->tab[tmpbuf[i]];
546 copied = AUD_write (s->voice, linbuf, copied << 1);
547 copied >>= 1;
549 else {
550 copied = AUD_write (s->voice, tmpbuf, copied);
553 temp -= copied;
554 dma_pos = (dma_pos + copied) % dma_len;
555 net += copied;
557 if (!copied) {
558 break;
562 return net;
565 static int cs_dma_read (void *opaque, int nchan, int dma_pos, int dma_len)
567 CSState *s = opaque;
568 int copy, written;
569 int till = -1;
571 copy = s->voice ? (s->audio_free >> (s->tab != NULL)) : dma_len;
573 if (s->dregs[Pin_Control] & IEN) {
574 till = (s->dregs[Playback_Lower_Base_Count]
575 | (s->dregs[Playback_Upper_Base_Count] << 8)) << s->shift;
576 till -= s->transferred;
577 copy = audio_MIN (till, copy);
580 if ((copy <= 0) || (dma_len <= 0)) {
581 return dma_pos;
584 written = cs_write_audio (s, nchan, dma_pos, dma_len, copy);
586 dma_pos = (dma_pos + written) % dma_len;
587 s->audio_free -= (written << (s->tab != NULL));
589 if (written == till) {
590 s->regs[Status] |= INT;
591 s->dregs[Alternate_Feature_Status] |= PI;
592 s->transferred = 0;
593 qemu_irq_raise (s->pic);
595 else {
596 s->transferred += written;
599 return dma_pos;
602 static int cs4231a_pre_load (void *opaque)
604 CSState *s = opaque;
606 if (s->dma_running) {
607 IsaDmaClass *k = ISADMA_GET_CLASS(s->isa_dma);
608 k->release_DREQ(s->isa_dma, s->dma);
609 AUD_set_active_out (s->voice, 0);
611 s->dma_running = 0;
612 return 0;
615 static int cs4231a_post_load (void *opaque, int version_id)
617 CSState *s = opaque;
619 if (s->dma_running && (s->dregs[Interface_Configuration] & PEN)) {
620 s->dma_running = 0;
621 cs_reset_voices (s, s->dregs[FS_And_Playback_Data_Format]);
623 return 0;
626 static const VMStateDescription vmstate_cs4231a = {
627 .name = "cs4231a",
628 .version_id = 1,
629 .minimum_version_id = 1,
630 .pre_load = cs4231a_pre_load,
631 .post_load = cs4231a_post_load,
632 .fields = (VMStateField[]) {
633 VMSTATE_UINT32_ARRAY (regs, CSState, CS_REGS),
634 VMSTATE_BUFFER (dregs, CSState),
635 VMSTATE_INT32 (dma_running, CSState),
636 VMSTATE_INT32 (audio_free, CSState),
637 VMSTATE_INT32 (transferred, CSState),
638 VMSTATE_INT32 (aci_counter, CSState),
639 VMSTATE_END_OF_LIST ()
643 static const MemoryRegionOps cs_ioport_ops = {
644 .read = cs_read,
645 .write = cs_write,
646 .impl = {
647 .min_access_size = 1,
648 .max_access_size = 1,
652 static void cs4231a_initfn (Object *obj)
654 CSState *s = CS4231A (obj);
656 memory_region_init_io (&s->ioports, OBJECT(s), &cs_ioport_ops, s,
657 "cs4231a", 4);
660 static void cs4231a_realizefn (DeviceState *dev, Error **errp)
662 ISADevice *d = ISA_DEVICE (dev);
663 CSState *s = CS4231A (dev);
664 IsaDmaClass *k;
666 isa_init_irq (d, &s->pic, s->irq);
667 s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->dma);
668 k = ISADMA_GET_CLASS(s->isa_dma);
669 k->register_channel(s->isa_dma, s->dma, cs_dma_read, s);
671 isa_register_ioport (d, &s->ioports, s->port);
673 AUD_register_card ("cs4231a", &s->card);
676 static int cs4231a_init (ISABus *bus)
678 isa_create_simple (bus, TYPE_CS4231A);
679 return 0;
682 static Property cs4231a_properties[] = {
683 DEFINE_PROP_UINT32 ("iobase", CSState, port, 0x534),
684 DEFINE_PROP_UINT32 ("irq", CSState, irq, 9),
685 DEFINE_PROP_UINT32 ("dma", CSState, dma, 3),
686 DEFINE_PROP_END_OF_LIST (),
689 static void cs4231a_class_initfn (ObjectClass *klass, void *data)
691 DeviceClass *dc = DEVICE_CLASS (klass);
693 dc->realize = cs4231a_realizefn;
694 dc->reset = cs4231a_reset;
695 set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
696 dc->desc = "Crystal Semiconductor CS4231A";
697 dc->vmsd = &vmstate_cs4231a;
698 dc->props = cs4231a_properties;
701 static const TypeInfo cs4231a_info = {
702 .name = TYPE_CS4231A,
703 .parent = TYPE_ISA_DEVICE,
704 .instance_size = sizeof (CSState),
705 .instance_init = cs4231a_initfn,
706 .class_init = cs4231a_class_initfn,
709 static void cs4231a_register_types (void)
711 type_register_static (&cs4231a_info);
712 isa_register_soundhw("cs4231a", "CS4231A", cs4231a_init);
715 type_init (cs4231a_register_types)