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
24 #include "qemu/osdep.h"
26 #include "hw/audio/soundhw.h"
27 #include "audio/audio.h"
28 #include "hw/isa/isa.h"
30 #include "qemu/timer.h"
31 #include "qapi/error.h"
43 /* #define DEBUG_XLAW */
50 #define dolog(...) AUD_log ("cs4231a", __VA_ARGS__)
55 #define lwarn(...) AUD_log ("cs4231a", "warning: " __VA_ARGS__)
56 #define lerr(...) AUD_log ("cs4231a", "error: " __VA_ARGS__)
61 #define TYPE_CS4231A "cs4231a"
62 #define CS4231A(obj) OBJECT_CHECK (CSState, (obj), TYPE_CS4231A)
64 typedef struct CSState
{
69 uint32_t regs
[CS_REGS
];
70 uint8_t dregs
[CS_DREGS
];
84 #define MODE2 (1 << 6)
105 Left_ADC_Input_Control
,
106 Right_ADC_Input_Control
,
107 Left_AUX1_Input_Control
,
108 Right_AUX1_Input_Control
,
109 Left_AUX2_Input_Control
,
110 Right_AUX2_Input_Control
,
111 Left_DAC_Output_Control
,
112 Right_DAC_Output_Control
,
113 FS_And_Playback_Data_Format
,
114 Interface_Configuration
,
116 Error_Status_And_Initialization
,
119 Playback_Upper_Base_Count
,
120 Playback_Lower_Base_Count
,
121 Alternate_Feature_Enable_I
,
122 Alternate_Feature_Enable_II
,
123 Left_Line_Input_Control
,
124 Right_Line_Input_Control
,
128 Alternate_Feature_Enable_III
,
129 Alternate_Feature_Status
,
131 Mono_Input_And_Output_Control
,
135 Capture_Upper_Base_Count
,
136 Capture_Lower_Base_Count
139 static int freqs
[2][8] = {
140 { 8000, 16000, 27420, 32000, -1, -1, 48000, 9000 },
141 { 5510, 11025, 18900, 22050, 37800, 44100, 33075, 6620 }
144 /* Tables courtesy http://hazelware.luggle.com/tutorials/mulawcompression.html */
145 static int16_t MuLawDecompressTable
[256] =
147 -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
148 -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
149 -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
150 -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
151 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
152 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
153 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
154 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
155 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
156 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
157 -876, -844, -812, -780, -748, -716, -684, -652,
158 -620, -588, -556, -524, -492, -460, -428, -396,
159 -372, -356, -340, -324, -308, -292, -276, -260,
160 -244, -228, -212, -196, -180, -164, -148, -132,
161 -120, -112, -104, -96, -88, -80, -72, -64,
162 -56, -48, -40, -32, -24, -16, -8, 0,
163 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
164 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
165 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
166 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
167 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
168 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
169 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
170 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
171 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
172 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
173 876, 844, 812, 780, 748, 716, 684, 652,
174 620, 588, 556, 524, 492, 460, 428, 396,
175 372, 356, 340, 324, 308, 292, 276, 260,
176 244, 228, 212, 196, 180, 164, 148, 132,
177 120, 112, 104, 96, 88, 80, 72, 64,
178 56, 48, 40, 32, 24, 16, 8, 0
181 static int16_t ALawDecompressTable
[256] =
183 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
184 -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
185 -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
186 -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
187 -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
188 -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
189 -11008,-10496,-12032,-11520,-8960, -8448, -9984, -9472,
190 -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
191 -344, -328, -376, -360, -280, -264, -312, -296,
192 -472, -456, -504, -488, -408, -392, -440, -424,
193 -88, -72, -120, -104, -24, -8, -56, -40,
194 -216, -200, -248, -232, -152, -136, -184, -168,
195 -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
196 -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
197 -688, -656, -752, -720, -560, -528, -624, -592,
198 -944, -912, -1008, -976, -816, -784, -880, -848,
199 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
200 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
201 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
202 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
203 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
204 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
205 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
206 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
207 344, 328, 376, 360, 280, 264, 312, 296,
208 472, 456, 504, 488, 408, 392, 440, 424,
209 88, 72, 120, 104, 24, 8, 56, 40,
210 216, 200, 248, 232, 152, 136, 184, 168,
211 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
212 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
213 688, 656, 752, 720, 560, 528, 624, 592,
214 944, 912, 1008, 976, 816, 784, 880, 848
217 static void cs4231a_reset (DeviceState
*dev
)
219 CSState
*s
= CS4231A (dev
);
221 s
->regs
[Index_Address
] = 0x40;
222 s
->regs
[Index_Data
] = 0x00;
223 s
->regs
[Status
] = 0x00;
224 s
->regs
[PIO_Data
] = 0x00;
226 s
->dregs
[Left_ADC_Input_Control
] = 0x00;
227 s
->dregs
[Right_ADC_Input_Control
] = 0x00;
228 s
->dregs
[Left_AUX1_Input_Control
] = 0x88;
229 s
->dregs
[Right_AUX1_Input_Control
] = 0x88;
230 s
->dregs
[Left_AUX2_Input_Control
] = 0x88;
231 s
->dregs
[Right_AUX2_Input_Control
] = 0x88;
232 s
->dregs
[Left_DAC_Output_Control
] = 0x80;
233 s
->dregs
[Right_DAC_Output_Control
] = 0x80;
234 s
->dregs
[FS_And_Playback_Data_Format
] = 0x00;
235 s
->dregs
[Interface_Configuration
] = 0x08;
236 s
->dregs
[Pin_Control
] = 0x00;
237 s
->dregs
[Error_Status_And_Initialization
] = 0x00;
238 s
->dregs
[MODE_And_ID
] = 0x8a;
239 s
->dregs
[Loopback_Control
] = 0x00;
240 s
->dregs
[Playback_Upper_Base_Count
] = 0x00;
241 s
->dregs
[Playback_Lower_Base_Count
] = 0x00;
242 s
->dregs
[Alternate_Feature_Enable_I
] = 0x00;
243 s
->dregs
[Alternate_Feature_Enable_II
] = 0x00;
244 s
->dregs
[Left_Line_Input_Control
] = 0x88;
245 s
->dregs
[Right_Line_Input_Control
] = 0x88;
246 s
->dregs
[Timer_Low_Base
] = 0x00;
247 s
->dregs
[Timer_High_Base
] = 0x00;
248 s
->dregs
[RESERVED
] = 0x00;
249 s
->dregs
[Alternate_Feature_Enable_III
] = 0x00;
250 s
->dregs
[Alternate_Feature_Status
] = 0x00;
251 s
->dregs
[Version_Chip_ID
] = 0xa0;
252 s
->dregs
[Mono_Input_And_Output_Control
] = 0xa0;
253 s
->dregs
[RESERVED_2
] = 0x00;
254 s
->dregs
[Capture_Data_Format
] = 0x00;
255 s
->dregs
[RESERVED_3
] = 0x00;
256 s
->dregs
[Capture_Upper_Base_Count
] = 0x00;
257 s
->dregs
[Capture_Lower_Base_Count
] = 0x00;
260 static void cs_audio_callback (void *opaque
, int free
)
263 s
->audio_free
= free
;
266 static void cs_reset_voices (CSState
*s
, uint32_t val
)
269 struct audsettings as
;
270 IsaDmaClass
*k
= ISADMA_GET_CLASS(s
->isa_dma
);
273 if (val
== 0 || val
== 32)
274 val
= (1 << 4) | (1 << 5);
278 as
.freq
= freqs
[xtal
][(val
>> 1) & 7];
281 lerr ("unsupported frequency (val=%#x)\n", val
);
285 as
.nchannels
= (val
& (1 << 4)) ? 2 : 1;
289 switch ((val
>> 5) & ((s
->dregs
[MODE_And_ID
] & MODE2
) ? 7 : 3)) {
292 s
->shift
= as
.nchannels
== 2;
296 s
->tab
= MuLawDecompressTable
;
299 s
->tab
= ALawDecompressTable
;
301 as
.fmt
= AUD_FMT_S16
;
302 as
.endianness
= AUDIO_HOST_ENDIANNESS
;
303 s
->shift
= as
.nchannels
== 2;
309 as
.fmt
= AUD_FMT_S16
;
310 s
->shift
= as
.nchannels
;
315 lerr ("attempt to use reserved format value (%#x)\n", val
);
319 lerr ("ADPCM 4 bit IMA compatible format is not supported\n");
323 s
->voice
= AUD_open_out (
332 if (s
->dregs
[Interface_Configuration
] & PEN
) {
333 if (!s
->dma_running
) {
334 k
->hold_DREQ(s
->isa_dma
, s
->dma
);
335 AUD_set_active_out (s
->voice
, 1);
341 if (s
->dma_running
) {
342 k
->release_DREQ(s
->isa_dma
, s
->dma
);
343 AUD_set_active_out (s
->voice
, 0);
350 if (s
->dma_running
) {
351 k
->release_DREQ(s
->isa_dma
, s
->dma
);
352 AUD_set_active_out (s
->voice
, 0);
356 static uint64_t cs_read (void *opaque
, hwaddr addr
, unsigned size
)
359 uint32_t saddr
, iaddr
, ret
;
366 ret
= s
->regs
[saddr
] & ~0x80;
370 if (!(s
->dregs
[MODE_And_ID
] & MODE2
))
371 iaddr
= s
->regs
[Index_Address
] & 0x0f;
373 iaddr
= s
->regs
[Index_Address
] & 0x1f;
375 ret
= s
->dregs
[iaddr
];
376 if (iaddr
== Error_Status_And_Initialization
) {
377 /* keep SEAL happy */
378 if (s
->aci_counter
) {
386 ret
= s
->regs
[saddr
];
389 dolog ("read %d:%d -> %d\n", saddr
, iaddr
, ret
);
393 static void cs_write (void *opaque
, hwaddr addr
,
394 uint64_t val64
, unsigned size
)
397 uint32_t saddr
, iaddr
, val
;
404 if (!(s
->regs
[Index_Address
] & MCE
) && (val
& MCE
)
405 && (s
->dregs
[Interface_Configuration
] & (3 << 3)))
406 s
->aci_counter
= conf
.aci_counter
;
408 s
->regs
[Index_Address
] = val
& ~(1 << 7);
412 if (!(s
->dregs
[MODE_And_ID
] & MODE2
))
413 iaddr
= s
->regs
[Index_Address
] & 0x0f;
415 iaddr
= s
->regs
[Index_Address
] & 0x1f;
421 lwarn ("attempt to write %#x to reserved indirect register %d\n",
425 case FS_And_Playback_Data_Format
:
426 if (s
->regs
[Index_Address
] & MCE
) {
427 cs_reset_voices (s
, val
);
430 if (s
->dregs
[Alternate_Feature_Status
] & PMCE
) {
431 val
= (val
& ~0x0f) | (s
->dregs
[iaddr
] & 0x0f);
432 cs_reset_voices (s
, val
);
435 lwarn ("[P]MCE(%#x, %#x) is not set, val=%#x\n",
436 s
->regs
[Index_Address
],
437 s
->dregs
[Alternate_Feature_Status
],
442 s
->dregs
[iaddr
] = val
;
445 case Interface_Configuration
:
446 val
&= ~(1 << 5); /* D5 is reserved */
447 s
->dregs
[iaddr
] = val
;
449 lwarn ("PIO is not supported (%#x)\n", val
);
453 if (!s
->dma_running
) {
454 cs_reset_voices (s
, s
->dregs
[FS_And_Playback_Data_Format
]);
458 if (s
->dma_running
) {
459 IsaDmaClass
*k
= ISADMA_GET_CLASS(s
->isa_dma
);
460 k
->release_DREQ(s
->isa_dma
, s
->dma
);
461 AUD_set_active_out (s
->voice
, 0);
467 case Error_Status_And_Initialization
:
468 lwarn ("attempt to write to read only register %d\n", iaddr
);
472 dolog ("val=%#x\n", val
);
474 s
->dregs
[iaddr
] |= MODE2
;
476 s
->dregs
[iaddr
] &= ~MODE2
;
479 case Alternate_Feature_Enable_I
:
481 lerr ("timer is not yet supported\n");
482 s
->dregs
[iaddr
] = val
;
485 case Alternate_Feature_Status
:
486 if ((s
->dregs
[iaddr
] & PI
) && !(val
& PI
)) {
488 qemu_irq_lower (s
->pic
);
489 s
->regs
[Status
] &= ~INT
;
491 s
->dregs
[iaddr
] = val
;
494 case Version_Chip_ID
:
495 lwarn ("write to Version_Chip_ID register %#x\n", val
);
496 s
->dregs
[iaddr
] = val
;
500 s
->dregs
[iaddr
] = val
;
503 dolog ("written value %#x to indirect register %d\n", val
, iaddr
);
507 if (s
->regs
[Status
] & INT
) {
508 qemu_irq_lower (s
->pic
);
510 s
->regs
[Status
] &= ~INT
;
511 s
->dregs
[Alternate_Feature_Status
] &= ~(PI
| CI
| TI
);
515 lwarn ("attempt to write value %#x to PIO register\n", val
);
520 static int cs_write_audio (CSState
*s
, int nchan
, int dma_pos
,
521 int dma_len
, int len
)
524 uint8_t tmpbuf
[4096];
525 IsaDmaClass
*k
= ISADMA_GET_CLASS(s
->isa_dma
);
531 int left
= dma_len
- dma_pos
;
535 to_copy
= audio_MIN (temp
, left
);
536 if (to_copy
> sizeof (tmpbuf
)) {
537 to_copy
= sizeof (tmpbuf
);
540 copied
= k
->read_memory(s
->isa_dma
, nchan
, tmpbuf
, dma_pos
, to_copy
);
543 int16_t linbuf
[4096];
545 for (i
= 0; i
< copied
; ++i
)
546 linbuf
[i
] = s
->tab
[tmpbuf
[i
]];
547 copied
= AUD_write (s
->voice
, linbuf
, copied
<< 1);
551 copied
= AUD_write (s
->voice
, tmpbuf
, copied
);
555 dma_pos
= (dma_pos
+ copied
) % dma_len
;
566 static int cs_dma_read (void *opaque
, int nchan
, int dma_pos
, int dma_len
)
572 copy
= s
->voice
? (s
->audio_free
>> (s
->tab
!= NULL
)) : dma_len
;
574 if (s
->dregs
[Pin_Control
] & IEN
) {
575 till
= (s
->dregs
[Playback_Lower_Base_Count
]
576 | (s
->dregs
[Playback_Upper_Base_Count
] << 8)) << s
->shift
;
577 till
-= s
->transferred
;
578 copy
= audio_MIN (till
, copy
);
581 if ((copy
<= 0) || (dma_len
<= 0)) {
585 written
= cs_write_audio (s
, nchan
, dma_pos
, dma_len
, copy
);
587 dma_pos
= (dma_pos
+ written
) % dma_len
;
588 s
->audio_free
-= (written
<< (s
->tab
!= NULL
));
590 if (written
== till
) {
591 s
->regs
[Status
] |= INT
;
592 s
->dregs
[Alternate_Feature_Status
] |= PI
;
594 qemu_irq_raise (s
->pic
);
597 s
->transferred
+= written
;
603 static int cs4231a_pre_load (void *opaque
)
607 if (s
->dma_running
) {
608 IsaDmaClass
*k
= ISADMA_GET_CLASS(s
->isa_dma
);
609 k
->release_DREQ(s
->isa_dma
, s
->dma
);
610 AUD_set_active_out (s
->voice
, 0);
616 static int cs4231a_post_load (void *opaque
, int version_id
)
620 if (s
->dma_running
&& (s
->dregs
[Interface_Configuration
] & PEN
)) {
622 cs_reset_voices (s
, s
->dregs
[FS_And_Playback_Data_Format
]);
627 static const VMStateDescription vmstate_cs4231a
= {
630 .minimum_version_id
= 1,
631 .pre_load
= cs4231a_pre_load
,
632 .post_load
= cs4231a_post_load
,
633 .fields
= (VMStateField
[]) {
634 VMSTATE_UINT32_ARRAY (regs
, CSState
, CS_REGS
),
635 VMSTATE_BUFFER (dregs
, CSState
),
636 VMSTATE_INT32 (dma_running
, CSState
),
637 VMSTATE_INT32 (audio_free
, CSState
),
638 VMSTATE_INT32 (transferred
, CSState
),
639 VMSTATE_INT32 (aci_counter
, CSState
),
640 VMSTATE_END_OF_LIST ()
644 static const MemoryRegionOps cs_ioport_ops
= {
648 .min_access_size
= 1,
649 .max_access_size
= 1,
653 static void cs4231a_initfn (Object
*obj
)
655 CSState
*s
= CS4231A (obj
);
657 memory_region_init_io (&s
->ioports
, OBJECT(s
), &cs_ioport_ops
, s
,
661 static void cs4231a_realizefn (DeviceState
*dev
, Error
**errp
)
663 ISADevice
*d
= ISA_DEVICE (dev
);
664 CSState
*s
= CS4231A (dev
);
667 s
->isa_dma
= isa_get_dma(isa_bus_from_device(d
), s
->dma
);
669 error_setg(errp
, "ISA controller does not support DMA");
673 isa_init_irq(d
, &s
->pic
, s
->irq
);
674 k
= ISADMA_GET_CLASS(s
->isa_dma
);
675 k
->register_channel(s
->isa_dma
, s
->dma
, cs_dma_read
, s
);
677 isa_register_ioport (d
, &s
->ioports
, s
->port
);
679 AUD_register_card ("cs4231a", &s
->card
);
682 static int cs4231a_init (ISABus
*bus
)
684 isa_create_simple (bus
, TYPE_CS4231A
);
688 static Property cs4231a_properties
[] = {
689 DEFINE_PROP_UINT32 ("iobase", CSState
, port
, 0x534),
690 DEFINE_PROP_UINT32 ("irq", CSState
, irq
, 9),
691 DEFINE_PROP_UINT32 ("dma", CSState
, dma
, 3),
692 DEFINE_PROP_END_OF_LIST (),
695 static void cs4231a_class_initfn (ObjectClass
*klass
, void *data
)
697 DeviceClass
*dc
= DEVICE_CLASS (klass
);
699 dc
->realize
= cs4231a_realizefn
;
700 dc
->reset
= cs4231a_reset
;
701 set_bit(DEVICE_CATEGORY_SOUND
, dc
->categories
);
702 dc
->desc
= "Crystal Semiconductor CS4231A";
703 dc
->vmsd
= &vmstate_cs4231a
;
704 dc
->props
= cs4231a_properties
;
707 static const TypeInfo cs4231a_info
= {
708 .name
= TYPE_CS4231A
,
709 .parent
= TYPE_ISA_DEVICE
,
710 .instance_size
= sizeof (CSState
),
711 .instance_init
= cs4231a_initfn
,
712 .class_init
= cs4231a_class_initfn
,
715 static void cs4231a_register_types (void)
717 type_register_static (&cs4231a_info
);
718 isa_register_soundhw("cs4231a", "CS4231A", cs4231a_init
);
721 type_init (cs4231a_register_types
)