0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/init.h>
0012 #include <linux/jiffies.h>
0013 #include <linux/slab.h>
0014 #include <linux/time.h>
0015 #include <linux/wait.h>
0016 #include <linux/module.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/firmware.h>
0019 #include <linux/timer.h>
0020 #include <linux/delay.h>
0021 #include <linux/workqueue.h>
0022 #include <linux/io.h>
0023 #include <sound/core.h>
0024 #include <sound/control.h>
0025 #include <sound/pcm.h>
0026 #include <sound/initval.h>
0027 #include <sound/info.h>
0028 #include <asm/dma.h>
0029 #include <mach/sysasic.h>
0030 #include "aica.h"
0031
0032 MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>");
0033 MODULE_DESCRIPTION("Dreamcast AICA sound (pcm) driver");
0034 MODULE_LICENSE("GPL");
0035 MODULE_FIRMWARE("aica_firmware.bin");
0036
0037
0038 #define CARD_NAME "AICA"
0039 static int index = -1;
0040 static char *id;
0041 static bool enable = 1;
0042 module_param(index, int, 0444);
0043 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
0044 module_param(id, charp, 0444);
0045 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
0046 module_param(enable, bool, 0644);
0047 MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
0048
0049
0050 static struct platform_device *pd;
0051 static struct resource aica_memory_space[2] = {
0052 {
0053 .name = "AICA ARM CONTROL",
0054 .start = ARM_RESET_REGISTER,
0055 .flags = IORESOURCE_MEM,
0056 .end = ARM_RESET_REGISTER + 3,
0057 },
0058 {
0059 .name = "AICA Sound RAM",
0060 .start = SPU_MEMORY_BASE,
0061 .flags = IORESOURCE_MEM,
0062 .end = SPU_MEMORY_BASE + 0x200000 - 1,
0063 },
0064 };
0065
0066
0067
0068 static void spu_write_wait(void)
0069 {
0070 int time_count;
0071 time_count = 0;
0072 while (1) {
0073 if (!(readl(G2_FIFO) & 0x11))
0074 break;
0075
0076 time_count++;
0077 if (time_count > 0x10000) {
0078 snd_printk
0079 ("WARNING: G2 FIFO appears to be blocked.\n");
0080 break;
0081 }
0082 }
0083 }
0084
0085
0086 static void spu_memset(u32 toi, u32 what, int length)
0087 {
0088 int i;
0089 unsigned long flags;
0090 if (snd_BUG_ON(length % 4))
0091 return;
0092 for (i = 0; i < length; i++) {
0093 if (!(i % 8))
0094 spu_write_wait();
0095 local_irq_save(flags);
0096 writel(what, toi + SPU_MEMORY_BASE);
0097 local_irq_restore(flags);
0098 toi++;
0099 }
0100 }
0101
0102
0103 static void spu_memload(u32 toi, const void *from, int length)
0104 {
0105 unsigned long flags;
0106 const u32 *froml = from;
0107 u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi);
0108 int i;
0109 u32 val;
0110 length = DIV_ROUND_UP(length, 4);
0111 spu_write_wait();
0112 for (i = 0; i < length; i++) {
0113 if (!(i % 8))
0114 spu_write_wait();
0115 val = *froml;
0116 local_irq_save(flags);
0117 writel(val, to);
0118 local_irq_restore(flags);
0119 froml++;
0120 to++;
0121 }
0122 }
0123
0124
0125 static void spu_disable(void)
0126 {
0127 int i;
0128 unsigned long flags;
0129 u32 regval;
0130 spu_write_wait();
0131 regval = readl(ARM_RESET_REGISTER);
0132 regval |= 1;
0133 spu_write_wait();
0134 local_irq_save(flags);
0135 writel(regval, ARM_RESET_REGISTER);
0136 local_irq_restore(flags);
0137 for (i = 0; i < 64; i++) {
0138 spu_write_wait();
0139 regval = readl(SPU_REGISTER_BASE + (i * 0x80));
0140 regval = (regval & ~0x4000) | 0x8000;
0141 spu_write_wait();
0142 local_irq_save(flags);
0143 writel(regval, SPU_REGISTER_BASE + (i * 0x80));
0144 local_irq_restore(flags);
0145 }
0146 }
0147
0148
0149 static void spu_enable(void)
0150 {
0151 unsigned long flags;
0152 u32 regval = readl(ARM_RESET_REGISTER);
0153 regval &= ~1;
0154 spu_write_wait();
0155 local_irq_save(flags);
0156 writel(regval, ARM_RESET_REGISTER);
0157 local_irq_restore(flags);
0158 }
0159
0160
0161
0162
0163
0164 static void spu_reset(void)
0165 {
0166 unsigned long flags;
0167 spu_disable();
0168 spu_memset(0, 0, 0x200000 / 4);
0169
0170 local_irq_save(flags);
0171 __raw_writel(0xea000002, SPU_MEMORY_BASE);
0172 local_irq_restore(flags);
0173 spu_enable();
0174 }
0175
0176
0177 static void aica_chn_start(void)
0178 {
0179 unsigned long flags;
0180 spu_write_wait();
0181 local_irq_save(flags);
0182 writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT);
0183 local_irq_restore(flags);
0184 }
0185
0186
0187 static void aica_chn_halt(void)
0188 {
0189 unsigned long flags;
0190 spu_write_wait();
0191 local_irq_save(flags);
0192 writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT);
0193 local_irq_restore(flags);
0194 }
0195
0196
0197 static const struct snd_pcm_hardware snd_pcm_aica_playback_hw = {
0198 .info = (SNDRV_PCM_INFO_NONINTERLEAVED),
0199 .formats =
0200 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
0201 SNDRV_PCM_FMTBIT_IMA_ADPCM),
0202 .rates = SNDRV_PCM_RATE_8000_48000,
0203 .rate_min = 8000,
0204 .rate_max = 48000,
0205 .channels_min = 1,
0206 .channels_max = 2,
0207 .buffer_bytes_max = AICA_BUFFER_SIZE,
0208 .period_bytes_min = AICA_PERIOD_SIZE,
0209 .period_bytes_max = AICA_PERIOD_SIZE,
0210 .periods_min = AICA_PERIOD_NUMBER,
0211 .periods_max = AICA_PERIOD_NUMBER,
0212 };
0213
0214 static int aica_dma_transfer(int channels, int buffer_size,
0215 struct snd_pcm_substream *substream)
0216 {
0217 int q, err, period_offset;
0218 struct snd_card_aica *dreamcastcard;
0219 struct snd_pcm_runtime *runtime;
0220 unsigned long flags;
0221 err = 0;
0222 dreamcastcard = substream->pcm->private_data;
0223 period_offset = dreamcastcard->clicks;
0224 period_offset %= (AICA_PERIOD_NUMBER / channels);
0225 runtime = substream->runtime;
0226 for (q = 0; q < channels; q++) {
0227 local_irq_save(flags);
0228 err = dma_xfer(AICA_DMA_CHANNEL,
0229 (unsigned long) (runtime->dma_area +
0230 (AICA_BUFFER_SIZE * q) /
0231 channels +
0232 AICA_PERIOD_SIZE *
0233 period_offset),
0234 AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET +
0235 AICA_PERIOD_SIZE * period_offset,
0236 buffer_size / channels, AICA_DMA_MODE);
0237 if (unlikely(err < 0)) {
0238 local_irq_restore(flags);
0239 break;
0240 }
0241 dma_wait_for_completion(AICA_DMA_CHANNEL);
0242 local_irq_restore(flags);
0243 }
0244 return err;
0245 }
0246
0247 static void startup_aica(struct snd_card_aica *dreamcastcard)
0248 {
0249 spu_memload(AICA_CHANNEL0_CONTROL_OFFSET,
0250 dreamcastcard->channel, sizeof(struct aica_channel));
0251 aica_chn_start();
0252 }
0253
0254 static void run_spu_dma(struct work_struct *work)
0255 {
0256 int buffer_size;
0257 struct snd_pcm_runtime *runtime;
0258 struct snd_card_aica *dreamcastcard;
0259 dreamcastcard =
0260 container_of(work, struct snd_card_aica, spu_dma_work);
0261 runtime = dreamcastcard->substream->runtime;
0262 if (unlikely(dreamcastcard->dma_check == 0)) {
0263 buffer_size =
0264 frames_to_bytes(runtime, runtime->buffer_size);
0265 if (runtime->channels > 1)
0266 dreamcastcard->channel->flags |= 0x01;
0267 aica_dma_transfer(runtime->channels, buffer_size,
0268 dreamcastcard->substream);
0269 startup_aica(dreamcastcard);
0270 dreamcastcard->clicks =
0271 buffer_size / (AICA_PERIOD_SIZE * runtime->channels);
0272 return;
0273 } else {
0274 aica_dma_transfer(runtime->channels,
0275 AICA_PERIOD_SIZE * runtime->channels,
0276 dreamcastcard->substream);
0277 snd_pcm_period_elapsed(dreamcastcard->substream);
0278 dreamcastcard->clicks++;
0279 if (unlikely(dreamcastcard->clicks >= AICA_PERIOD_NUMBER))
0280 dreamcastcard->clicks %= AICA_PERIOD_NUMBER;
0281 mod_timer(&dreamcastcard->timer, jiffies + 1);
0282 }
0283 }
0284
0285 static void aica_period_elapsed(struct timer_list *t)
0286 {
0287 struct snd_card_aica *dreamcastcard = from_timer(dreamcastcard,
0288 t, timer);
0289 struct snd_pcm_substream *substream = dreamcastcard->substream;
0290
0291 int play_period;
0292 struct snd_pcm_runtime *runtime;
0293 runtime = substream->runtime;
0294 dreamcastcard = substream->pcm->private_data;
0295
0296 play_period =
0297 frames_to_bytes(runtime,
0298 readl
0299 (AICA_CONTROL_CHANNEL_SAMPLE_NUMBER)) /
0300 AICA_PERIOD_SIZE;
0301 if (play_period == dreamcastcard->current_period) {
0302
0303 mod_timer(&(dreamcastcard->timer), jiffies + 1);
0304 return;
0305 }
0306 if (runtime->channels > 1)
0307 dreamcastcard->current_period = play_period;
0308 if (unlikely(dreamcastcard->dma_check == 0))
0309 dreamcastcard->dma_check = 1;
0310 schedule_work(&(dreamcastcard->spu_dma_work));
0311 }
0312
0313 static void spu_begin_dma(struct snd_pcm_substream *substream)
0314 {
0315 struct snd_card_aica *dreamcastcard;
0316 struct snd_pcm_runtime *runtime;
0317 runtime = substream->runtime;
0318 dreamcastcard = substream->pcm->private_data;
0319
0320 schedule_work(&(dreamcastcard->spu_dma_work));
0321 mod_timer(&dreamcastcard->timer, jiffies + 4);
0322 }
0323
0324 static int snd_aicapcm_pcm_open(struct snd_pcm_substream
0325 *substream)
0326 {
0327 struct snd_pcm_runtime *runtime;
0328 struct aica_channel *channel;
0329 struct snd_card_aica *dreamcastcard;
0330 if (!enable)
0331 return -ENOENT;
0332 dreamcastcard = substream->pcm->private_data;
0333 channel = kmalloc(sizeof(struct aica_channel), GFP_KERNEL);
0334 if (!channel)
0335 return -ENOMEM;
0336
0337 channel->sfmt = SM_8BIT;
0338 channel->cmd = AICA_CMD_START;
0339 channel->vol = dreamcastcard->master_volume;
0340 channel->pan = 0x80;
0341 channel->pos = 0;
0342 channel->flags = 0;
0343 dreamcastcard->channel = channel;
0344 runtime = substream->runtime;
0345 runtime->hw = snd_pcm_aica_playback_hw;
0346 spu_enable();
0347 dreamcastcard->clicks = 0;
0348 dreamcastcard->current_period = 0;
0349 dreamcastcard->dma_check = 0;
0350 return 0;
0351 }
0352
0353 static int snd_aicapcm_pcm_close(struct snd_pcm_substream
0354 *substream)
0355 {
0356 struct snd_card_aica *dreamcastcard = substream->pcm->private_data;
0357 flush_work(&(dreamcastcard->spu_dma_work));
0358 del_timer(&dreamcastcard->timer);
0359 dreamcastcard->substream = NULL;
0360 kfree(dreamcastcard->channel);
0361 spu_disable();
0362 return 0;
0363 }
0364
0365 static int snd_aicapcm_pcm_prepare(struct snd_pcm_substream
0366 *substream)
0367 {
0368 struct snd_card_aica *dreamcastcard = substream->pcm->private_data;
0369 if ((substream->runtime)->format == SNDRV_PCM_FORMAT_S16_LE)
0370 dreamcastcard->channel->sfmt = SM_16BIT;
0371 dreamcastcard->channel->freq = substream->runtime->rate;
0372 dreamcastcard->substream = substream;
0373 return 0;
0374 }
0375
0376 static int snd_aicapcm_pcm_trigger(struct snd_pcm_substream
0377 *substream, int cmd)
0378 {
0379 switch (cmd) {
0380 case SNDRV_PCM_TRIGGER_START:
0381 spu_begin_dma(substream);
0382 break;
0383 case SNDRV_PCM_TRIGGER_STOP:
0384 aica_chn_halt();
0385 break;
0386 default:
0387 return -EINVAL;
0388 }
0389 return 0;
0390 }
0391
0392 static unsigned long snd_aicapcm_pcm_pointer(struct snd_pcm_substream
0393 *substream)
0394 {
0395 return readl(AICA_CONTROL_CHANNEL_SAMPLE_NUMBER);
0396 }
0397
0398 static const struct snd_pcm_ops snd_aicapcm_playback_ops = {
0399 .open = snd_aicapcm_pcm_open,
0400 .close = snd_aicapcm_pcm_close,
0401 .prepare = snd_aicapcm_pcm_prepare,
0402 .trigger = snd_aicapcm_pcm_trigger,
0403 .pointer = snd_aicapcm_pcm_pointer,
0404 };
0405
0406
0407 static int __init snd_aicapcmchip(struct snd_card_aica
0408 *dreamcastcard, int pcm_index)
0409 {
0410 struct snd_pcm *pcm;
0411 int err;
0412
0413 err =
0414 snd_pcm_new(dreamcastcard->card, "AICA PCM", pcm_index, 1, 0,
0415 &pcm);
0416 if (unlikely(err < 0))
0417 return err;
0418 pcm->private_data = dreamcastcard;
0419 strcpy(pcm->name, "AICA PCM");
0420 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
0421 &snd_aicapcm_playback_ops);
0422
0423 snd_pcm_set_managed_buffer_all(pcm,
0424 SNDRV_DMA_TYPE_CONTINUOUS,
0425 NULL,
0426 AICA_BUFFER_SIZE,
0427 AICA_BUFFER_SIZE);
0428 return 0;
0429 }
0430
0431
0432 #define aica_pcmswitch_info snd_ctl_boolean_mono_info
0433
0434 static int aica_pcmswitch_get(struct snd_kcontrol *kcontrol,
0435 struct snd_ctl_elem_value *ucontrol)
0436 {
0437 ucontrol->value.integer.value[0] = 1;
0438 return 0;
0439 }
0440
0441 static int aica_pcmswitch_put(struct snd_kcontrol *kcontrol,
0442 struct snd_ctl_elem_value *ucontrol)
0443 {
0444 if (ucontrol->value.integer.value[0] == 1)
0445 return 0;
0446 else
0447 aica_chn_halt();
0448 return 0;
0449 }
0450
0451 static int aica_pcmvolume_info(struct snd_kcontrol *kcontrol,
0452 struct snd_ctl_elem_info *uinfo)
0453 {
0454 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0455 uinfo->count = 1;
0456 uinfo->value.integer.min = 0;
0457 uinfo->value.integer.max = 0xFF;
0458 return 0;
0459 }
0460
0461 static int aica_pcmvolume_get(struct snd_kcontrol *kcontrol,
0462 struct snd_ctl_elem_value *ucontrol)
0463 {
0464 struct snd_card_aica *dreamcastcard;
0465 dreamcastcard = kcontrol->private_data;
0466 if (unlikely(!dreamcastcard->channel))
0467 return -ETXTBSY;
0468 ucontrol->value.integer.value[0] = dreamcastcard->channel->vol;
0469 return 0;
0470 }
0471
0472 static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol,
0473 struct snd_ctl_elem_value *ucontrol)
0474 {
0475 struct snd_card_aica *dreamcastcard;
0476 unsigned int vol;
0477 dreamcastcard = kcontrol->private_data;
0478 if (unlikely(!dreamcastcard->channel))
0479 return -ETXTBSY;
0480 vol = ucontrol->value.integer.value[0];
0481 if (vol > 0xff)
0482 return -EINVAL;
0483 if (unlikely(dreamcastcard->channel->vol == vol))
0484 return 0;
0485 dreamcastcard->channel->vol = ucontrol->value.integer.value[0];
0486 dreamcastcard->master_volume = ucontrol->value.integer.value[0];
0487 spu_memload(AICA_CHANNEL0_CONTROL_OFFSET,
0488 dreamcastcard->channel, sizeof(struct aica_channel));
0489 return 1;
0490 }
0491
0492 static const struct snd_kcontrol_new snd_aica_pcmswitch_control = {
0493 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0494 .name = "PCM Playback Switch",
0495 .index = 0,
0496 .info = aica_pcmswitch_info,
0497 .get = aica_pcmswitch_get,
0498 .put = aica_pcmswitch_put
0499 };
0500
0501 static const struct snd_kcontrol_new snd_aica_pcmvolume_control = {
0502 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0503 .name = "PCM Playback Volume",
0504 .index = 0,
0505 .info = aica_pcmvolume_info,
0506 .get = aica_pcmvolume_get,
0507 .put = aica_pcmvolume_put
0508 };
0509
0510 static int load_aica_firmware(void)
0511 {
0512 int err;
0513 const struct firmware *fw_entry;
0514 spu_reset();
0515 err = request_firmware(&fw_entry, "aica_firmware.bin", &pd->dev);
0516 if (unlikely(err))
0517 return err;
0518
0519 spu_disable();
0520 spu_memload(0, fw_entry->data, fw_entry->size);
0521 spu_enable();
0522 release_firmware(fw_entry);
0523 return err;
0524 }
0525
0526 static int add_aicamixer_controls(struct snd_card_aica *dreamcastcard)
0527 {
0528 int err;
0529 err = snd_ctl_add
0530 (dreamcastcard->card,
0531 snd_ctl_new1(&snd_aica_pcmvolume_control, dreamcastcard));
0532 if (unlikely(err < 0))
0533 return err;
0534 err = snd_ctl_add
0535 (dreamcastcard->card,
0536 snd_ctl_new1(&snd_aica_pcmswitch_control, dreamcastcard));
0537 if (unlikely(err < 0))
0538 return err;
0539 return 0;
0540 }
0541
0542 static int snd_aica_remove(struct platform_device *devptr)
0543 {
0544 struct snd_card_aica *dreamcastcard;
0545 dreamcastcard = platform_get_drvdata(devptr);
0546 if (unlikely(!dreamcastcard))
0547 return -ENODEV;
0548 snd_card_free(dreamcastcard->card);
0549 kfree(dreamcastcard);
0550 return 0;
0551 }
0552
0553 static int snd_aica_probe(struct platform_device *devptr)
0554 {
0555 int err;
0556 struct snd_card_aica *dreamcastcard;
0557 dreamcastcard = kzalloc(sizeof(struct snd_card_aica), GFP_KERNEL);
0558 if (unlikely(!dreamcastcard))
0559 return -ENOMEM;
0560 err = snd_card_new(&devptr->dev, index, SND_AICA_DRIVER,
0561 THIS_MODULE, 0, &dreamcastcard->card);
0562 if (unlikely(err < 0)) {
0563 kfree(dreamcastcard);
0564 return err;
0565 }
0566 strcpy(dreamcastcard->card->driver, "snd_aica");
0567 strcpy(dreamcastcard->card->shortname, SND_AICA_DRIVER);
0568 strcpy(dreamcastcard->card->longname,
0569 "Yamaha AICA Super Intelligent Sound Processor for SEGA Dreamcast");
0570
0571 INIT_WORK(&(dreamcastcard->spu_dma_work), run_spu_dma);
0572 timer_setup(&dreamcastcard->timer, aica_period_elapsed, 0);
0573
0574 err = snd_aicapcmchip(dreamcastcard, 0);
0575 if (unlikely(err < 0))
0576 goto freedreamcast;
0577
0578 err = add_aicamixer_controls(dreamcastcard);
0579 if (unlikely(err < 0))
0580 goto freedreamcast;
0581
0582 err = snd_card_register(dreamcastcard->card);
0583 if (unlikely(err < 0))
0584 goto freedreamcast;
0585 platform_set_drvdata(devptr, dreamcastcard);
0586 snd_printk
0587 ("ALSA Driver for Yamaha AICA Super Intelligent Sound Processor\n");
0588 return 0;
0589 freedreamcast:
0590 snd_card_free(dreamcastcard->card);
0591 kfree(dreamcastcard);
0592 return err;
0593 }
0594
0595 static struct platform_driver snd_aica_driver = {
0596 .probe = snd_aica_probe,
0597 .remove = snd_aica_remove,
0598 .driver = {
0599 .name = SND_AICA_DRIVER,
0600 },
0601 };
0602
0603 static int __init aica_init(void)
0604 {
0605 int err;
0606 err = platform_driver_register(&snd_aica_driver);
0607 if (unlikely(err < 0))
0608 return err;
0609 pd = platform_device_register_simple(SND_AICA_DRIVER, -1,
0610 aica_memory_space, 2);
0611 if (IS_ERR(pd)) {
0612 platform_driver_unregister(&snd_aica_driver);
0613 return PTR_ERR(pd);
0614 }
0615
0616 return load_aica_firmware();
0617 }
0618
0619 static void __exit aica_exit(void)
0620 {
0621 platform_device_unregister(pd);
0622 platform_driver_unregister(&snd_aica_driver);
0623
0624 spu_reset();
0625 }
0626
0627 module_init(aica_init);
0628 module_exit(aica_exit);