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
25 #include "qemu/osdep.h"
26 #include "hw/audio/soundhw.h"
27 #include "audio/audio.h"
29 #include "hw/isa/isa.h"
30 #include "hw/qdev-properties.h"
31 #include "migration/vmstate.h"
32 #include "qemu/module.h"
33 #include "qemu/timer.h"
34 #include "qapi/error.h"
46 /* #define DEBUG_XLAW */
53 #define dolog(...) AUD_log ("cs4231a", __VA_ARGS__)
58 #define lwarn(...) AUD_log ("cs4231a", "warning: " __VA_ARGS__)
59 #define lerr(...) AUD_log ("cs4231a", "error: " __VA_ARGS__)
64 #define TYPE_CS4231A "cs4231a"
65 #define CS4231A(obj) OBJECT_CHECK (CSState, (obj), TYPE_CS4231A)
67 typedef struct CSState
{
72 uint32_t regs
[CS_REGS
];
73 uint8_t dregs
[CS_DREGS
];
87 #define MODE2 (1 << 6)
108 Left_ADC_Input_Control
,
109 Right_ADC_Input_Control
,
110 Left_AUX1_Input_Control
,
111 Right_AUX1_Input_Control
,
112 Left_AUX2_Input_Control
,
113 Right_AUX2_Input_Control
,
114 Left_DAC_Output_Control
,
115 Right_DAC_Output_Control
,
116 FS_And_Playback_Data_Format
,
117 Interface_Configuration
,
119 Error_Status_And_Initialization
,
122 Playback_Upper_Base_Count
,
123 Playback_Lower_Base_Count
,
124 Alternate_Feature_Enable_I
,
125 Alternate_Feature_Enable_II
,
126 Left_Line_Input_Control
,
127 Right_Line_Input_Control
,
131 Alternate_Feature_Enable_III
,
132 Alternate_Feature_Status
,
134 Mono_Input_And_Output_Control
,
138 Capture_Upper_Base_Count
,
139 Capture_Lower_Base_Count
142 static int freqs
[2][8] = {
143 { 8000, 16000, 27420, 32000, -1, -1, 48000, 9000 },
144 { 5510, 11025, 18900, 22050, 37800, 44100, 33075, 6620 }
147 /* Tables courtesy http://hazelware.luggle.com/tutorials/mulawcompression.html */
148 static int16_t MuLawDecompressTable
[256] =
150 -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
151 -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
152 -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
153 -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
154 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
155 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
156 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
157 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
158 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
159 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
160 -876, -844, -812, -780, -748, -716, -684, -652,
161 -620, -588, -556, -524, -492, -460, -428, -396,
162 -372, -356, -340, -324, -308, -292, -276, -260,
163 -244, -228, -212, -196, -180, -164, -148, -132,
164 -120, -112, -104, -96, -88, -80, -72, -64,
165 -56, -48, -40, -32, -24, -16, -8, 0,
166 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
167 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
168 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
169 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
170 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
171 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
172 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
173 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
174 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
175 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
176 876, 844, 812, 780, 748, 716, 684, 652,
177 620, 588, 556, 524, 492, 460, 428, 396,
178 372, 356, 340, 324, 308, 292, 276, 260,
179 244, 228, 212, 196, 180, 164, 148, 132,
180 120, 112, 104, 96, 88, 80, 72, 64,
181 56, 48, 40, 32, 24, 16, 8, 0
184 static int16_t ALawDecompressTable
[256] =
186 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
187 -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
188 -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
189 -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
190 -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
191 -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
192 -11008,-10496,-12032,-11520,-8960, -8448, -9984, -9472,
193 -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
194 -344, -328, -376, -360, -280, -264, -312, -296,
195 -472, -456, -504, -488, -408, -392, -440, -424,
196 -88, -72, -120, -104, -24, -8, -56, -40,
197 -216, -200, -248, -232, -152, -136, -184, -168,
198 -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
199 -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
200 -688, -656, -752, -720, -560, -528, -624, -592,
201 -944, -912, -1008, -976, -816, -784, -880, -848,
202 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
203 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
204 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
205 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
206 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
207 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
208 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
209 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
210 344, 328, 376, 360, 280, 264, 312, 296,
211 472, 456, 504, 488, 408, 392, 440, 424,
212 88, 72, 120, 104, 24, 8, 56, 40,
213 216, 200, 248, 232, 152, 136, 184, 168,
214 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
215 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
216 688, 656, 752, 720, 560, 528, 624, 592,
217 944, 912, 1008, 976, 816, 784, 880, 848
220 static void cs4231a_reset (DeviceState
*dev
)
222 CSState
*s
= CS4231A (dev
);
224 s
->regs
[Index_Address
] = 0x40;
225 s
->regs
[Index_Data
] = 0x00;
226 s
->regs
[Status
] = 0x00;
227 s
->regs
[PIO_Data
] = 0x00;
229 s
->dregs
[Left_ADC_Input_Control
] = 0x00;
230 s
->dregs
[Right_ADC_Input_Control
] = 0x00;
231 s
->dregs
[Left_AUX1_Input_Control
] = 0x88;
232 s
->dregs
[Right_AUX1_Input_Control
] = 0x88;
233 s
->dregs
[Left_AUX2_Input_Control
] = 0x88;
234 s
->dregs
[Right_AUX2_Input_Control
] = 0x88;
235 s
->dregs
[Left_DAC_Output_Control
] = 0x80;
236 s
->dregs
[Right_DAC_Output_Control
] = 0x80;
237 s
->dregs
[FS_And_Playback_Data_Format
] = 0x00;
238 s
->dregs
[Interface_Configuration
] = 0x08;
239 s
->dregs
[Pin_Control
] = 0x00;
240 s
->dregs
[Error_Status_And_Initialization
] = 0x00;
241 s
->dregs
[MODE_And_ID
] = 0x8a;
242 s
->dregs
[Loopback_Control
] = 0x00;
243 s
->dregs
[Playback_Upper_Base_Count
] = 0x00;
244 s
->dregs
[Playback_Lower_Base_Count
] = 0x00;
245 s
->dregs
[Alternate_Feature_Enable_I
] = 0x00;
246 s
->dregs
[Alternate_Feature_Enable_II
] = 0x00;
247 s
->dregs
[Left_Line_Input_Control
] = 0x88;
248 s
->dregs
[Right_Line_Input_Control
] = 0x88;
249 s
->dregs
[Timer_Low_Base
] = 0x00;
250 s
->dregs
[Timer_High_Base
] = 0x00;
251 s
->dregs
[RESERVED
] = 0x00;
252 s
->dregs
[Alternate_Feature_Enable_III
] = 0x00;
253 s
->dregs
[Alternate_Feature_Status
] = 0x00;
254 s
->dregs
[Version_Chip_ID
] = 0xa0;
255 s
->dregs
[Mono_Input_And_Output_Control
] = 0xa0;
256 s
->dregs
[RESERVED_2
] = 0x00;
257 s
->dregs
[Capture_Data_Format
] = 0x00;
258 s
->dregs
[RESERVED_3
] = 0x00;
259 s
->dregs
[Capture_Upper_Base_Count
] = 0x00;
260 s
->dregs
[Capture_Lower_Base_Count
] = 0x00;
263 static void cs_audio_callback (void *opaque
, int free
)
266 s
->audio_free
= free
;
269 static void cs_reset_voices (CSState
*s
, uint32_t val
)
272 struct audsettings as
;
273 IsaDmaClass
*k
= ISADMA_GET_CLASS(s
->isa_dma
);
276 if (val
== 0 || val
== 32)
277 val
= (1 << 4) | (1 << 5);
281 as
.freq
= freqs
[xtal
][(val
>> 1) & 7];
284 lerr ("unsupported frequency (val=%#x)\n", val
);
288 as
.nchannels
= (val
& (1 << 4)) ? 2 : 1;
292 switch ((val
>> 5) & ((s
->dregs
[MODE_And_ID
] & MODE2
) ? 7 : 3)) {
294 as
.fmt
= AUDIO_FORMAT_U8
;
295 s
->shift
= as
.nchannels
== 2;
299 s
->tab
= MuLawDecompressTable
;
302 s
->tab
= ALawDecompressTable
;
304 as
.fmt
= AUDIO_FORMAT_S16
;
305 as
.endianness
= AUDIO_HOST_ENDIANNESS
;
306 s
->shift
= as
.nchannels
== 2;
313 as
.fmt
= AUDIO_FORMAT_S16
;
314 s
->shift
= as
.nchannels
;
319 lerr ("attempt to use reserved format value (%#x)\n", val
);
323 lerr ("ADPCM 4 bit IMA compatible format is not supported\n");
327 s
->voice
= AUD_open_out (
336 if (s
->dregs
[Interface_Configuration
] & PEN
) {
337 if (!s
->dma_running
) {
338 k
->hold_DREQ(s
->isa_dma
, s
->dma
);
339 AUD_set_active_out (s
->voice
, 1);
345 if (s
->dma_running
) {
346 k
->release_DREQ(s
->isa_dma
, s
->dma
);
347 AUD_set_active_out (s
->voice
, 0);
354 if (s
->dma_running
) {
355 k
->release_DREQ(s
->isa_dma
, s
->dma
);
356 AUD_set_active_out (s
->voice
, 0);
360 static uint64_t cs_read (void *opaque
, hwaddr addr
, unsigned size
)
363 uint32_t saddr
, iaddr
, ret
;
370 ret
= s
->regs
[saddr
] & ~0x80;
374 if (!(s
->dregs
[MODE_And_ID
] & MODE2
))
375 iaddr
= s
->regs
[Index_Address
] & 0x0f;
377 iaddr
= s
->regs
[Index_Address
] & 0x1f;
379 ret
= s
->dregs
[iaddr
];
380 if (iaddr
== Error_Status_And_Initialization
) {
381 /* keep SEAL happy */
382 if (s
->aci_counter
) {
390 ret
= s
->regs
[saddr
];
393 dolog ("read %d:%d -> %d\n", saddr
, iaddr
, ret
);
397 static void cs_write (void *opaque
, hwaddr addr
,
398 uint64_t val64
, unsigned size
)
401 uint32_t saddr
, iaddr
, val
;
408 if (!(s
->regs
[Index_Address
] & MCE
) && (val
& MCE
)
409 && (s
->dregs
[Interface_Configuration
] & (3 << 3)))
410 s
->aci_counter
= conf
.aci_counter
;
412 s
->regs
[Index_Address
] = val
& ~(1 << 7);
416 if (!(s
->dregs
[MODE_And_ID
] & MODE2
))
417 iaddr
= s
->regs
[Index_Address
] & 0x0f;
419 iaddr
= s
->regs
[Index_Address
] & 0x1f;
425 lwarn ("attempt to write %#x to reserved indirect register %d\n",
429 case FS_And_Playback_Data_Format
:
430 if (s
->regs
[Index_Address
] & MCE
) {
431 cs_reset_voices (s
, val
);
434 if (s
->dregs
[Alternate_Feature_Status
] & PMCE
) {
435 val
= (val
& ~0x0f) | (s
->dregs
[iaddr
] & 0x0f);
436 cs_reset_voices (s
, val
);
439 lwarn ("[P]MCE(%#x, %#x) is not set, val=%#x\n",
440 s
->regs
[Index_Address
],
441 s
->dregs
[Alternate_Feature_Status
],
446 s
->dregs
[iaddr
] = val
;
449 case Interface_Configuration
:
450 val
&= ~(1 << 5); /* D5 is reserved */
451 s
->dregs
[iaddr
] = val
;
453 lwarn ("PIO is not supported (%#x)\n", val
);
457 if (!s
->dma_running
) {
458 cs_reset_voices (s
, s
->dregs
[FS_And_Playback_Data_Format
]);
462 if (s
->dma_running
) {
463 IsaDmaClass
*k
= ISADMA_GET_CLASS(s
->isa_dma
);
464 k
->release_DREQ(s
->isa_dma
, s
->dma
);
465 AUD_set_active_out (s
->voice
, 0);
471 case Error_Status_And_Initialization
:
472 lwarn ("attempt to write to read only register %d\n", iaddr
);
476 dolog ("val=%#x\n", val
);
478 s
->dregs
[iaddr
] |= MODE2
;
480 s
->dregs
[iaddr
] &= ~MODE2
;
483 case Alternate_Feature_Enable_I
:
485 lerr ("timer is not yet supported\n");
486 s
->dregs
[iaddr
] = val
;
489 case Alternate_Feature_Status
:
490 if ((s
->dregs
[iaddr
] & PI
) && !(val
& PI
)) {
492 qemu_irq_lower (s
->pic
);
493 s
->regs
[Status
] &= ~INT
;
495 s
->dregs
[iaddr
] = val
;
498 case Version_Chip_ID
:
499 lwarn ("write to Version_Chip_ID register %#x\n", val
);
500 s
->dregs
[iaddr
] = val
;
504 s
->dregs
[iaddr
] = val
;
507 dolog ("written value %#x to indirect register %d\n", val
, iaddr
);
511 if (s
->regs
[Status
] & INT
) {
512 qemu_irq_lower (s
->pic
);
514 s
->regs
[Status
] &= ~INT
;
515 s
->dregs
[Alternate_Feature_Status
] &= ~(PI
| CI
| TI
);
519 lwarn ("attempt to write value %#x to PIO register\n", val
);
524 static int cs_write_audio (CSState
*s
, int nchan
, int dma_pos
,
525 int dma_len
, int len
)
528 uint8_t tmpbuf
[4096];
529 IsaDmaClass
*k
= ISADMA_GET_CLASS(s
->isa_dma
);
535 int left
= dma_len
- dma_pos
;
539 to_copy
= MIN (temp
, left
);
540 if (to_copy
> sizeof (tmpbuf
)) {
541 to_copy
= sizeof (tmpbuf
);
544 copied
= k
->read_memory(s
->isa_dma
, nchan
, tmpbuf
, dma_pos
, to_copy
);
547 int16_t linbuf
[4096];
549 for (i
= 0; i
< copied
; ++i
)
550 linbuf
[i
] = s
->tab
[tmpbuf
[i
]];
551 copied
= AUD_write (s
->voice
, linbuf
, copied
<< 1);
555 copied
= AUD_write (s
->voice
, tmpbuf
, copied
);
559 dma_pos
= (dma_pos
+ copied
) % dma_len
;
570 static int cs_dma_read (void *opaque
, int nchan
, int dma_pos
, int dma_len
)
576 copy
= s
->voice
? (s
->audio_free
>> (s
->tab
!= NULL
)) : dma_len
;
578 if (s
->dregs
[Pin_Control
] & IEN
) {
579 till
= (s
->dregs
[Playback_Lower_Base_Count
]
580 | (s
->dregs
[Playback_Upper_Base_Count
] << 8)) << s
->shift
;
581 till
-= s
->transferred
;
582 copy
= MIN (till
, copy
);
585 if ((copy
<= 0) || (dma_len
<= 0)) {
589 written
= cs_write_audio (s
, nchan
, dma_pos
, dma_len
, copy
);
591 dma_pos
= (dma_pos
+ written
) % dma_len
;
592 s
->audio_free
-= (written
<< (s
->tab
!= NULL
));
594 if (written
== till
) {
595 s
->regs
[Status
] |= INT
;
596 s
->dregs
[Alternate_Feature_Status
] |= PI
;
598 qemu_irq_raise (s
->pic
);
601 s
->transferred
+= written
;
607 static int cs4231a_pre_load (void *opaque
)
611 if (s
->dma_running
) {
612 IsaDmaClass
*k
= ISADMA_GET_CLASS(s
->isa_dma
);
613 k
->release_DREQ(s
->isa_dma
, s
->dma
);
614 AUD_set_active_out (s
->voice
, 0);
620 static int cs4231a_post_load (void *opaque
, int version_id
)
624 if (s
->dma_running
&& (s
->dregs
[Interface_Configuration
] & PEN
)) {
626 cs_reset_voices (s
, s
->dregs
[FS_And_Playback_Data_Format
]);
631 static const VMStateDescription vmstate_cs4231a
= {
634 .minimum_version_id
= 1,
635 .pre_load
= cs4231a_pre_load
,
636 .post_load
= cs4231a_post_load
,
637 .fields
= (VMStateField
[]) {
638 VMSTATE_UINT32_ARRAY (regs
, CSState
, CS_REGS
),
639 VMSTATE_BUFFER (dregs
, CSState
),
640 VMSTATE_INT32 (dma_running
, CSState
),
641 VMSTATE_INT32 (audio_free
, CSState
),
642 VMSTATE_INT32 (transferred
, CSState
),
643 VMSTATE_INT32 (aci_counter
, CSState
),
644 VMSTATE_END_OF_LIST ()
648 static const MemoryRegionOps cs_ioport_ops
= {
652 .min_access_size
= 1,
653 .max_access_size
= 1,
657 static void cs4231a_initfn (Object
*obj
)
659 CSState
*s
= CS4231A (obj
);
661 memory_region_init_io (&s
->ioports
, OBJECT(s
), &cs_ioport_ops
, s
,
665 static void cs4231a_realizefn (DeviceState
*dev
, Error
**errp
)
667 ISADevice
*d
= ISA_DEVICE (dev
);
668 CSState
*s
= CS4231A (dev
);
671 s
->isa_dma
= isa_get_dma(isa_bus_from_device(d
), s
->dma
);
673 error_setg(errp
, "ISA controller does not support DMA");
677 isa_init_irq(d
, &s
->pic
, s
->irq
);
678 k
= ISADMA_GET_CLASS(s
->isa_dma
);
679 k
->register_channel(s
->isa_dma
, s
->dma
, cs_dma_read
, s
);
681 isa_register_ioport (d
, &s
->ioports
, s
->port
);
683 AUD_register_card ("cs4231a", &s
->card
);
686 static Property cs4231a_properties
[] = {
687 DEFINE_AUDIO_PROPERTIES(CSState
, card
),
688 DEFINE_PROP_UINT32 ("iobase", CSState
, port
, 0x534),
689 DEFINE_PROP_UINT32 ("irq", CSState
, irq
, 9),
690 DEFINE_PROP_UINT32 ("dma", CSState
, dma
, 3),
691 DEFINE_PROP_END_OF_LIST (),
694 static void cs4231a_class_initfn (ObjectClass
*klass
, void *data
)
696 DeviceClass
*dc
= DEVICE_CLASS (klass
);
698 dc
->realize
= cs4231a_realizefn
;
699 dc
->reset
= cs4231a_reset
;
700 set_bit(DEVICE_CATEGORY_SOUND
, dc
->categories
);
701 dc
->desc
= "Crystal Semiconductor CS4231A";
702 dc
->vmsd
= &vmstate_cs4231a
;
703 device_class_set_props(dc
, cs4231a_properties
);
706 static const TypeInfo cs4231a_info
= {
707 .name
= TYPE_CS4231A
,
708 .parent
= TYPE_ISA_DEVICE
,
709 .instance_size
= sizeof (CSState
),
710 .instance_init
= cs4231a_initfn
,
711 .class_init
= cs4231a_class_initfn
,
714 static void cs4231a_register_types (void)
716 type_register_static (&cs4231a_info
);
717 deprecated_register_soundhw("cs4231a", "CS4231A", 1, TYPE_CS4231A
);
720 type_init (cs4231a_register_types
)