29 #include <linux/slab.h>
30 #include <linux/time.h>
31 #include <linux/wait.h>
32 #include <linux/module.h>
55 #define CARD_NAME "AICA"
56 static int index = -1;
71 static struct resource aica_memory_space[2] = {
73 .name =
"AICA ARM CONTROL",
79 .name =
"AICA Sound RAM",
88 static void spu_write_wait(
void)
97 if (time_count > 0x10000) {
99 (
"WARNING: G2 FIFO appears to be blocked.\n");
112 for (i = 0; i <
length; i++) {
123 static void spu_memload(
u32 toi,
void *
from,
int length)
132 for (i = 0; i <
length; i++) {
145 static void spu_disable(
void)
157 for (i = 0; i < 64; i++) {
160 regval = (regval & ~0x4000) | 0x8000;
169 static void spu_enable(
void)
184 static void spu_reset(
void)
188 spu_memset(0, 0, 0x200000 / 4);
197 static void aica_chn_start(
void)
207 static void aica_chn_halt(
void)
234 static int aica_dma_transfer(
int channels,
int buffer_size,
237 int q,
err, period_offset;
242 dreamcastcard = substream->
pcm->private_data;
243 period_offset = dreamcastcard->
clicks;
249 (
unsigned long) (runtime->
dma_area +
267 static void startup_aica(
struct snd_card_aica *dreamcastcard)
281 runtime = dreamcastcard->
substream->runtime;
286 dreamcastcard->
channel->flags |= 0x01;
287 aica_dma_transfer(runtime->
channels, buffer_size,
289 startup_aica(dreamcastcard);
294 aica_dma_transfer(runtime->
channels,
305 static void aica_period_elapsed(
unsigned long timer_var)
314 dreamcastcard = substream->
pcm->private_data;
317 frames_to_bytes(runtime,
338 dreamcastcard = substream->
pcm->private_data;
347 dreamcastcard->
timer.data = (
unsigned long) substream;
348 dreamcastcard->
timer.function = aica_period_elapsed;
361 dreamcastcard = substream->
pcm->private_data;
374 runtime->
hw = snd_pcm_aica_playback_hw;
376 dreamcastcard->
clicks = 0;
387 if (dreamcastcard->
timer.data)
427 spu_begin_dma(substream);
444 static struct snd_pcm_ops snd_aicapcm_playback_ops = {
445 .open = snd_aicapcm_pcm_open,
446 .close = snd_aicapcm_pcm_close,
448 .hw_params = snd_aicapcm_pcm_hw_params,
449 .hw_free = snd_aicapcm_pcm_hw_free,
450 .prepare = snd_aicapcm_pcm_prepare,
451 .trigger = snd_aicapcm_pcm_trigger,
452 .pointer = snd_aicapcm_pcm_pointer,
457 *dreamcastcard,
int pcm_index)
470 &snd_aicapcm_playback_ops);
483 #define aica_pcmswitch_info snd_ctl_boolean_mono_info
485 static int aica_pcmswitch_get(
struct snd_kcontrol *kcontrol,
488 ucontrol->
value.integer.value[0] = 1;
492 static int aica_pcmswitch_put(
struct snd_kcontrol *kcontrol,
495 if (ucontrol->
value.integer.value[0] == 1)
502 static int aica_pcmvolume_info(
struct snd_kcontrol *kcontrol,
512 static int aica_pcmvolume_get(
struct snd_kcontrol *kcontrol,
519 ucontrol->
value.integer.value[0] = dreamcastcard->
channel->vol;
523 static int aica_pcmvolume_put(
struct snd_kcontrol *kcontrol,
531 vol = ucontrol->
value.integer.value[0];
536 dreamcastcard->
channel->vol = ucontrol->
value.integer.value[0];
545 .name =
"PCM Playback Switch",
548 .get = aica_pcmswitch_get,
549 .put = aica_pcmswitch_put
554 .name =
"PCM Playback Volume",
556 .info = aica_pcmvolume_info,
557 .get = aica_pcmvolume_get,
558 .put = aica_pcmvolume_put
561 static int load_aica_firmware(
void)
571 spu_memload(0, fw_entry->
data, fw_entry->
size);
582 (dreamcastcard->
card,
583 snd_ctl_new1(&snd_aica_pcmvolume_control, dreamcastcard));
587 (dreamcastcard->
card,
588 snd_ctl_new1(&snd_aica_pcmswitch_control, dreamcastcard));
597 dreamcastcard = platform_get_drvdata(devptr);
601 kfree(dreamcastcard);
602 platform_set_drvdata(devptr,
NULL);
614 &dreamcastcard->
card);
616 kfree(dreamcastcard);
619 strcpy(dreamcastcard->
card->driver,
"snd_aica");
622 "Yamaha AICA Super Intelligent Sound Processor for SEGA Dreamcast");
626 err = snd_aicapcmchip(dreamcastcard, 0);
630 dreamcastcard->
timer.data = 0;
633 err = add_aicamixer_controls(dreamcastcard);
640 platform_set_drvdata(devptr, dreamcastcard);
645 (
"ALSA Driver for Yamaha AICA Super Intelligent Sound Processor\n");
649 kfree(dreamcastcard);
654 .probe = snd_aica_probe,
662 static int __init aica_init(
void)
669 aica_memory_space, 2);
675 return load_aica_firmware();
678 static void __exit aica_exit(
void)