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
26
#include "audio/audio.h"
28
#include "qemu-timer.h"
40
/* #define DEBUG_XLAW */
47
} conf = {9, 3, 0x534, 1};
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
typedef struct CSState {
64
uint32_t regs[CS_REGS];
65
uint8_t dregs[CS_DREGS];
78
#define IO_READ_PROTO(name) \
79
static uint32_t name (void *opaque, uint32_t addr)
81
#define IO_WRITE_PROTO(name) \
82
static void name (void *opaque, uint32_t addr, uint32_t val)
84
#define GET_SADDR(addr) (addr & 3)
86
#define MODE2 (1 << 6)
107
Left_ADC_Input_Control,
108
Right_ADC_Input_Control,
109
Left_AUX1_Input_Control,
110
Right_AUX1_Input_Control,
111
Left_AUX2_Input_Control,
112
Right_AUX2_Input_Control,
113
Left_DAC_Output_Control,
114
Right_DAC_Output_Control,
115
FS_And_Playback_Data_Format,
116
Interface_Configuration,
118
Error_Status_And_Initialization,
121
Playback_Upper_Base_Count,
122
Playback_Lower_Base_Count,
123
Alternate_Feature_Enable_I,
124
Alternate_Feature_Enable_II,
125
Left_Line_Input_Control,
126
Right_Line_Input_Control,
130
Alternate_Feature_Enable_III,
131
Alternate_Feature_Status,
133
Mono_Input_And_Output_Control,
137
Capture_Upper_Base_Count,
138
Capture_Lower_Base_Count
141
static int freqs[2][8] = {
142
{ 8000, 16000, 27420, 32000, -1, -1, 48000, 9000 },
143
{ 5510, 11025, 18900, 22050, 37800, 44100, 33075, 6620 }
146
/* Tables courtesy http://hazelware.luggle.com/tutorials/mulawcompression.html */
147
static int16_t MuLawDecompressTable[256] =
149
-32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
150
-23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
151
-15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
152
-11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
153
-7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
154
-5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
155
-3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
156
-2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
157
-1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
158
-1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
159
-876, -844, -812, -780, -748, -716, -684, -652,
160
-620, -588, -556, -524, -492, -460, -428, -396,
161
-372, -356, -340, -324, -308, -292, -276, -260,
162
-244, -228, -212, -196, -180, -164, -148, -132,
163
-120, -112, -104, -96, -88, -80, -72, -64,
164
-56, -48, -40, -32, -24, -16, -8, 0,
165
32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
166
23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
167
15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
168
11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
169
7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
170
5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
171
3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
172
2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
173
1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
174
1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
175
876, 844, 812, 780, 748, 716, 684, 652,
176
620, 588, 556, 524, 492, 460, 428, 396,
177
372, 356, 340, 324, 308, 292, 276, 260,
178
244, 228, 212, 196, 180, 164, 148, 132,
179
120, 112, 104, 96, 88, 80, 72, 64,
180
56, 48, 40, 32, 24, 16, 8, 0
183
static int16_t ALawDecompressTable[256] =
185
-5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
186
-7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
187
-2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
188
-3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
189
-22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
190
-30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
191
-11008,-10496,-12032,-11520,-8960, -8448, -9984, -9472,
192
-15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
193
-344, -328, -376, -360, -280, -264, -312, -296,
194
-472, -456, -504, -488, -408, -392, -440, -424,
195
-88, -72, -120, -104, -24, -8, -56, -40,
196
-216, -200, -248, -232, -152, -136, -184, -168,
197
-1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
198
-1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
199
-688, -656, -752, -720, -560, -528, -624, -592,
200
-944, -912, -1008, -976, -816, -784, -880, -848,
201
5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
202
7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
203
2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
204
3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
205
22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
206
30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
207
11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
208
15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
209
344, 328, 376, 360, 280, 264, 312, 296,
210
472, 456, 504, 488, 408, 392, 440, 424,
211
88, 72, 120, 104, 24, 8, 56, 40,
212
216, 200, 248, 232, 152, 136, 184, 168,
213
1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
214
1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
215
688, 656, 752, 720, 560, 528, 624, 592,
216
944, 912, 1008, 976, 816, 784, 880, 848
219
static void cs_reset(void *opaque)
223
s->regs[Index_Address] = 0x40;
224
s->regs[Index_Data] = 0x00;
225
s->regs[Status] = 0x00;
226
s->regs[PIO_Data] = 0x00;
228
s->dregs[Left_ADC_Input_Control] = 0x00;
229
s->dregs[Right_ADC_Input_Control] = 0x00;
230
s->dregs[Left_AUX1_Input_Control] = 0x88;
231
s->dregs[Right_AUX1_Input_Control] = 0x88;
232
s->dregs[Left_AUX2_Input_Control] = 0x88;
233
s->dregs[Right_AUX2_Input_Control] = 0x88;
234
s->dregs[Left_DAC_Output_Control] = 0x80;
235
s->dregs[Right_DAC_Output_Control] = 0x80;
236
s->dregs[FS_And_Playback_Data_Format] = 0x00;
237
s->dregs[Interface_Configuration] = 0x08;
238
s->dregs[Pin_Control] = 0x00;
239
s->dregs[Error_Status_And_Initialization] = 0x00;
240
s->dregs[MODE_And_ID] = 0x8a;
241
s->dregs[Loopback_Control] = 0x00;
242
s->dregs[Playback_Upper_Base_Count] = 0x00;
243
s->dregs[Playback_Lower_Base_Count] = 0x00;
244
s->dregs[Alternate_Feature_Enable_I] = 0x00;
245
s->dregs[Alternate_Feature_Enable_II] = 0x00;
246
s->dregs[Left_Line_Input_Control] = 0x88;
247
s->dregs[Right_Line_Input_Control] = 0x88;
248
s->dregs[Timer_Low_Base] = 0x00;
249
s->dregs[Timer_High_Base] = 0x00;
250
s->dregs[RESERVED] = 0x00;
251
s->dregs[Alternate_Feature_Enable_III] = 0x00;
252
s->dregs[Alternate_Feature_Status] = 0x00;
253
s->dregs[Version_Chip_ID] = 0xa0;
254
s->dregs[Mono_Input_And_Output_Control] = 0xa0;
255
s->dregs[RESERVED_2] = 0x00;
256
s->dregs[Capture_Data_Format] = 0x00;
257
s->dregs[RESERVED_3] = 0x00;
258
s->dregs[Capture_Upper_Base_Count] = 0x00;
259
s->dregs[Capture_Lower_Base_Count] = 0x00;
262
static void cs_audio_callback (void *opaque, int free)
265
s->audio_free = free;
268
static void cs_reset_voices (CSState *s, uint32_t val)
274
if (val == 0 || val == 32)
275
val = (1 << 4) | (1 << 5);
279
as.freq = freqs[xtal][(val >> 1) & 7];
282
lerr ("unsupported frequency (val=%#x)\n", val);
286
as.nchannels = (val & (1 << 4)) ? 2 : 1;
290
switch ((val >> 5) & ((s->dregs[MODE_And_ID] & MODE2) ? 7 : 3)) {
293
s->shift = as.nchannels == 2;
297
s->tab = MuLawDecompressTable;
300
s->tab = ALawDecompressTable;
302
as.fmt = AUD_FMT_S16;
303
as.endianness = AUDIO_HOST_ENDIANNESS;
304
s->shift = as.nchannels == 2;
310
as.fmt = AUD_FMT_S16;
311
s->shift = as.nchannels;
316
lerr ("attempt to use reserved format value (%#x)\n", val);
320
lerr ("ADPCM 4 bit IMA compatible format is not supported\n");
324
s->voice = AUD_open_out (
333
if (s->dregs[Interface_Configuration] & PEN) {
334
if (!s->dma_running) {
335
DMA_hold_DREQ (s->dma);
336
AUD_set_active_out (s->voice, 1);
342
if (s->dma_running) {
343
DMA_release_DREQ (s->dma);
344
AUD_set_active_out (s->voice, 0);
351
if (s->dma_running) {
352
DMA_release_DREQ (s->dma);
353
AUD_set_active_out (s->voice, 0);
357
IO_READ_PROTO (cs_read)
360
uint32_t saddr, iaddr, ret;
362
saddr = GET_SADDR (addr);
367
ret = s->regs[saddr] & ~0x80;
371
if (!(s->dregs[MODE_And_ID] & MODE2))
372
iaddr = s->regs[Index_Address] & 0x0f;
374
iaddr = s->regs[Index_Address] & 0x1f;
376
ret = s->dregs[iaddr];
377
if (iaddr == Error_Status_And_Initialization) {
378
/* keep SEAL happy */
379
if (s->aci_counter) {
387
ret = s->regs[saddr];
390
dolog ("read %d:%d -> %d\n", saddr, iaddr, ret);
394
IO_WRITE_PROTO (cs_write)
397
uint32_t saddr, iaddr;
399
saddr = GET_SADDR (addr);
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);
411
if (!(s->dregs[MODE_And_ID] & MODE2))
412
iaddr = s->regs[Index_Address] & 0x0f;
414
iaddr = s->regs[Index_Address] & 0x1f;
420
lwarn ("attempt to write %#x to reserved indirect register %d\n",
424
case FS_And_Playback_Data_Format:
425
if (s->regs[Index_Address] & MCE) {
426
cs_reset_voices (s, val);
429
if (s->dregs[Alternate_Feature_Status] & PMCE) {
430
val = (val & ~0x0f) | (s->dregs[iaddr] & 0x0f);
431
cs_reset_voices (s, val);
434
lwarn ("[P]MCE(%#x, %#x) is not set, val=%#x\n",
435
s->regs[Index_Address],
436
s->dregs[Alternate_Feature_Status],
441
s->dregs[iaddr] = val;
444
case Interface_Configuration:
445
val &= ~(1 << 5); /* D5 is reserved */
446
s->dregs[iaddr] = val;
448
lwarn ("PIO is not supported (%#x)\n", val);
452
if (!s->dma_running) {
453
cs_reset_voices (s, s->dregs[FS_And_Playback_Data_Format]);
457
if (s->dma_running) {
458
DMA_release_DREQ (s->dma);
459
AUD_set_active_out (s->voice, 0);
465
case Error_Status_And_Initialization:
466
lwarn ("attempt to write to read only register %d\n", iaddr);
470
dolog ("val=%#x\n", val);
472
s->dregs[iaddr] |= MODE2;
474
s->dregs[iaddr] &= ~MODE2;
477
case Alternate_Feature_Enable_I:
479
lerr ("timer is not yet supported\n");
480
s->dregs[iaddr] = val;
483
case Alternate_Feature_Status:
484
if ((s->dregs[iaddr] & PI) && !(val & PI)) {
486
qemu_irq_lower (s->pic[s->irq]);
487
s->regs[Status] &= ~INT;
489
s->dregs[iaddr] = val;
492
case Version_Chip_ID:
493
lwarn ("write to Version_Chip_ID register %#x\n", val);
494
s->dregs[iaddr] = val;
498
s->dregs[iaddr] = val;
501
dolog ("written value %#x to indirect register %d\n", val, iaddr);
505
if (s->regs[Status] & INT) {
506
qemu_irq_lower (s->pic[s->irq]);
508
s->regs[Status] &= ~INT;
509
s->dregs[Alternate_Feature_Status] &= ~(PI | CI | TI);
513
lwarn ("attempt to write value %#x to PIO register\n", val);
518
static int cs_write_audio (CSState *s, int nchan, int dma_pos,
519
int dma_len, int len)
522
uint8_t tmpbuf[4096];
528
int left = dma_len - dma_pos;
532
to_copy = audio_MIN (temp, left);
533
if (to_copy > sizeof (tmpbuf)) {
534
to_copy = sizeof (tmpbuf);
537
copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
540
int16_t linbuf[4096];
542
for (i = 0; i < copied; ++i)
543
linbuf[i] = s->tab[tmpbuf[i]];
544
copied = AUD_write (s->voice, linbuf, copied << 1);
548
copied = AUD_write (s->voice, tmpbuf, copied);
552
dma_pos = (dma_pos + copied) % dma_len;
563
static int cs_dma_read (void *opaque, int nchan, int dma_pos, int dma_len)
569
copy = s->voice ? (s->audio_free >> (s->tab != NULL)) : dma_len;
571
if (s->dregs[Pin_Control] & IEN) {
572
till = (s->dregs[Playback_Lower_Base_Count]
573
| (s->dregs[Playback_Upper_Base_Count] << 8)) << s->shift;
574
till -= s->transferred;
575
copy = audio_MIN (till, copy);
578
if ((copy <= 0) || (dma_len <= 0)) {
582
written = cs_write_audio (s, nchan, dma_pos, dma_len, copy);
584
dma_pos = (dma_pos + written) % dma_len;
585
s->audio_free -= (written << (s->tab != NULL));
587
if (written == till) {
588
s->regs[Status] |= INT;
589
s->dregs[Alternate_Feature_Status] |= PI;
591
qemu_irq_raise (s->pic[s->irq]);
594
s->transferred += written;
600
static void cs_save(QEMUFile *f, void *opaque)
606
for (i = 0; i < CS_REGS; i++)
607
qemu_put_be32s(f, &s->regs[i]);
609
qemu_put_buffer(f, s->dregs, CS_DREGS);
610
val = s->dma_running; qemu_put_be32s(f, &val);
611
val = s->audio_free; qemu_put_be32s(f, &val);
612
val = s->transferred; qemu_put_be32s(f, &val);
613
val = s->aci_counter; qemu_put_be32s(f, &val);
616
static int cs_load(QEMUFile *f, void *opaque, int version_id)
620
uint32_t val, dma_running;
625
for (i = 0; i < CS_REGS; i++)
626
qemu_get_be32s(f, &s->regs[i]);
628
qemu_get_buffer(f, s->dregs, CS_DREGS);
630
qemu_get_be32s(f, &dma_running);
631
qemu_get_be32s(f, &val); s->audio_free = val;
632
qemu_get_be32s(f, &val); s->transferred = val;
633
qemu_get_be32s(f, &val); s->aci_counter = val;
634
if (dma_running && (s->dregs[Interface_Configuration] & PEN))
635
cs_reset_voices (s, s->dregs[FS_And_Playback_Data_Format]);
639
int cs4231a_init (AudioState *audio, qemu_irq *pic)
645
lerr ("No audio state\n");
649
s = qemu_mallocz (sizeof (*s));
651
lerr ("Could not allocate memory for cs4231a (%zu bytes)\n",
661
for (i = 0; i < 4; i++) {
662
register_ioport_write (s->port + i, 1, 1, cs_write, s);
663
register_ioport_read (s->port + i, 1, 1, cs_read, s);
666
DMA_register_channel (s->dma, cs_dma_read, s);
668
register_savevm ("cs4231a", 0, 1, cs_save, cs_load, s);
669
qemu_register_reset (cs_reset, s);
672
AUD_register_card (audio,"cs4231a", &s->card);