root/sound/sh/aica.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. spu_write_wait
  2. spu_memset
  3. spu_memload
  4. spu_disable
  5. spu_enable
  6. spu_reset
  7. aica_chn_start
  8. aica_chn_halt
  9. aica_dma_transfer
  10. startup_aica
  11. run_spu_dma
  12. aica_period_elapsed
  13. spu_begin_dma
  14. snd_aicapcm_pcm_open
  15. snd_aicapcm_pcm_close
  16. snd_aicapcm_pcm_hw_free
  17. snd_aicapcm_pcm_hw_params
  18. snd_aicapcm_pcm_prepare
  19. snd_aicapcm_pcm_trigger
  20. snd_aicapcm_pcm_pointer
  21. snd_aicapcmchip
  22. aica_pcmswitch_get
  23. aica_pcmswitch_put
  24. aica_pcmvolume_info
  25. aica_pcmvolume_get
  26. aica_pcmvolume_put
  27. load_aica_firmware
  28. add_aicamixer_controls
  29. snd_aica_remove
  30. snd_aica_probe
  31. aica_init
  32. aica_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3 *
   4 * Copyright Adrian McMenamin 2005, 2006, 2007
   5 * <adrian@mcmen.demon.co.uk>
   6 * Requires firmware (BSD licenced) available from:
   7 * http://linuxdc.cvs.sourceforge.net/linuxdc/linux-sh-dc/sound/oss/aica/firmware/
   8 * or the maintainer
   9 */
  10 
  11 #include <linux/init.h>
  12 #include <linux/jiffies.h>
  13 #include <linux/slab.h>
  14 #include <linux/time.h>
  15 #include <linux/wait.h>
  16 #include <linux/module.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/firmware.h>
  19 #include <linux/timer.h>
  20 #include <linux/delay.h>
  21 #include <linux/workqueue.h>
  22 #include <linux/io.h>
  23 #include <sound/core.h>
  24 #include <sound/control.h>
  25 #include <sound/pcm.h>
  26 #include <sound/initval.h>
  27 #include <sound/info.h>
  28 #include <asm/dma.h>
  29 #include <mach/sysasic.h>
  30 #include "aica.h"
  31 
  32 MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>");
  33 MODULE_DESCRIPTION("Dreamcast AICA sound (pcm) driver");
  34 MODULE_LICENSE("GPL");
  35 MODULE_SUPPORTED_DEVICE("{{Yamaha/SEGA, AICA}}");
  36 MODULE_FIRMWARE("aica_firmware.bin");
  37 
  38 /* module parameters */
  39 #define CARD_NAME "AICA"
  40 static int index = -1;
  41 static char *id;
  42 static bool enable = 1;
  43 module_param(index, int, 0444);
  44 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
  45 module_param(id, charp, 0444);
  46 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
  47 module_param(enable, bool, 0644);
  48 MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
  49 
  50 /* Simple platform device */
  51 static struct platform_device *pd;
  52 static struct resource aica_memory_space[2] = {
  53         {
  54          .name = "AICA ARM CONTROL",
  55          .start = ARM_RESET_REGISTER,
  56          .flags = IORESOURCE_MEM,
  57          .end = ARM_RESET_REGISTER + 3,
  58          },
  59         {
  60          .name = "AICA Sound RAM",
  61          .start = SPU_MEMORY_BASE,
  62          .flags = IORESOURCE_MEM,
  63          .end = SPU_MEMORY_BASE + 0x200000 - 1,
  64          },
  65 };
  66 
  67 /* SPU specific functions */
  68 /* spu_write_wait - wait for G2-SH FIFO to clear */
  69 static void spu_write_wait(void)
  70 {
  71         int time_count;
  72         time_count = 0;
  73         while (1) {
  74                 if (!(readl(G2_FIFO) & 0x11))
  75                         break;
  76                 /* To ensure hardware failure doesn't wedge kernel */
  77                 time_count++;
  78                 if (time_count > 0x10000) {
  79                         snd_printk
  80                             ("WARNING: G2 FIFO appears to be blocked.\n");
  81                         break;
  82                 }
  83         }
  84 }
  85 
  86 /* spu_memset - write to memory in SPU address space */
  87 static void spu_memset(u32 toi, u32 what, int length)
  88 {
  89         int i;
  90         unsigned long flags;
  91         if (snd_BUG_ON(length % 4))
  92                 return;
  93         for (i = 0; i < length; i++) {
  94                 if (!(i % 8))
  95                         spu_write_wait();
  96                 local_irq_save(flags);
  97                 writel(what, toi + SPU_MEMORY_BASE);
  98                 local_irq_restore(flags);
  99                 toi++;
 100         }
 101 }
 102 
 103 /* spu_memload - write to SPU address space */
 104 static void spu_memload(u32 toi, const void *from, int length)
 105 {
 106         unsigned long flags;
 107         const u32 *froml = from;
 108         u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi);
 109         int i;
 110         u32 val;
 111         length = DIV_ROUND_UP(length, 4);
 112         spu_write_wait();
 113         for (i = 0; i < length; i++) {
 114                 if (!(i % 8))
 115                         spu_write_wait();
 116                 val = *froml;
 117                 local_irq_save(flags);
 118                 writel(val, to);
 119                 local_irq_restore(flags);
 120                 froml++;
 121                 to++;
 122         }
 123 }
 124 
 125 /* spu_disable - set spu registers to stop sound output */
 126 static void spu_disable(void)
 127 {
 128         int i;
 129         unsigned long flags;
 130         u32 regval;
 131         spu_write_wait();
 132         regval = readl(ARM_RESET_REGISTER);
 133         regval |= 1;
 134         spu_write_wait();
 135         local_irq_save(flags);
 136         writel(regval, ARM_RESET_REGISTER);
 137         local_irq_restore(flags);
 138         for (i = 0; i < 64; i++) {
 139                 spu_write_wait();
 140                 regval = readl(SPU_REGISTER_BASE + (i * 0x80));
 141                 regval = (regval & ~0x4000) | 0x8000;
 142                 spu_write_wait();
 143                 local_irq_save(flags);
 144                 writel(regval, SPU_REGISTER_BASE + (i * 0x80));
 145                 local_irq_restore(flags);
 146         }
 147 }
 148 
 149 /* spu_enable - set spu registers to enable sound output */
 150 static void spu_enable(void)
 151 {
 152         unsigned long flags;
 153         u32 regval = readl(ARM_RESET_REGISTER);
 154         regval &= ~1;
 155         spu_write_wait();
 156         local_irq_save(flags);
 157         writel(regval, ARM_RESET_REGISTER);
 158         local_irq_restore(flags);
 159 }
 160 
 161 /* 
 162  * Halt the sound processor, clear the memory,
 163  * load some default ARM7 code, and then restart ARM7
 164 */
 165 static void spu_reset(void)
 166 {
 167         unsigned long flags;
 168         spu_disable();
 169         spu_memset(0, 0, 0x200000 / 4);
 170         /* Put ARM7 in endless loop */
 171         local_irq_save(flags);
 172         __raw_writel(0xea000002, SPU_MEMORY_BASE);
 173         local_irq_restore(flags);
 174         spu_enable();
 175 }
 176 
 177 /* aica_chn_start - write to spu to start playback */
 178 static void aica_chn_start(void)
 179 {
 180         unsigned long flags;
 181         spu_write_wait();
 182         local_irq_save(flags);
 183         writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT);
 184         local_irq_restore(flags);
 185 }
 186 
 187 /* aica_chn_halt - write to spu to halt playback */
 188 static void aica_chn_halt(void)
 189 {
 190         unsigned long flags;
 191         spu_write_wait();
 192         local_irq_save(flags);
 193         writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT);
 194         local_irq_restore(flags);
 195 }
 196 
 197 /* ALSA code below */
 198 static const struct snd_pcm_hardware snd_pcm_aica_playback_hw = {
 199         .info = (SNDRV_PCM_INFO_NONINTERLEAVED),
 200         .formats =
 201             (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
 202              SNDRV_PCM_FMTBIT_IMA_ADPCM),
 203         .rates = SNDRV_PCM_RATE_8000_48000,
 204         .rate_min = 8000,
 205         .rate_max = 48000,
 206         .channels_min = 1,
 207         .channels_max = 2,
 208         .buffer_bytes_max = AICA_BUFFER_SIZE,
 209         .period_bytes_min = AICA_PERIOD_SIZE,
 210         .period_bytes_max = AICA_PERIOD_SIZE,
 211         .periods_min = AICA_PERIOD_NUMBER,
 212         .periods_max = AICA_PERIOD_NUMBER,
 213 };
 214 
 215 static int aica_dma_transfer(int channels, int buffer_size,
 216                              struct snd_pcm_substream *substream)
 217 {
 218         int q, err, period_offset;
 219         struct snd_card_aica *dreamcastcard;
 220         struct snd_pcm_runtime *runtime;
 221         unsigned long flags;
 222         err = 0;
 223         dreamcastcard = substream->pcm->private_data;
 224         period_offset = dreamcastcard->clicks;
 225         period_offset %= (AICA_PERIOD_NUMBER / channels);
 226         runtime = substream->runtime;
 227         for (q = 0; q < channels; q++) {
 228                 local_irq_save(flags);
 229                 err = dma_xfer(AICA_DMA_CHANNEL,
 230                                (unsigned long) (runtime->dma_area +
 231                                                 (AICA_BUFFER_SIZE * q) /
 232                                                 channels +
 233                                                 AICA_PERIOD_SIZE *
 234                                                 period_offset),
 235                                AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET +
 236                                AICA_PERIOD_SIZE * period_offset,
 237                                buffer_size / channels, AICA_DMA_MODE);
 238                 if (unlikely(err < 0)) {
 239                         local_irq_restore(flags);
 240                         break;
 241                 }
 242                 dma_wait_for_completion(AICA_DMA_CHANNEL);
 243                 local_irq_restore(flags);
 244         }
 245         return err;
 246 }
 247 
 248 static void startup_aica(struct snd_card_aica *dreamcastcard)
 249 {
 250         spu_memload(AICA_CHANNEL0_CONTROL_OFFSET,
 251                     dreamcastcard->channel, sizeof(struct aica_channel));
 252         aica_chn_start();
 253 }
 254 
 255 static void run_spu_dma(struct work_struct *work)
 256 {
 257         int buffer_size;
 258         struct snd_pcm_runtime *runtime;
 259         struct snd_card_aica *dreamcastcard;
 260         dreamcastcard =
 261             container_of(work, struct snd_card_aica, spu_dma_work);
 262         runtime = dreamcastcard->substream->runtime;
 263         if (unlikely(dreamcastcard->dma_check == 0)) {
 264                 buffer_size =
 265                     frames_to_bytes(runtime, runtime->buffer_size);
 266                 if (runtime->channels > 1)
 267                         dreamcastcard->channel->flags |= 0x01;
 268                 aica_dma_transfer(runtime->channels, buffer_size,
 269                                   dreamcastcard->substream);
 270                 startup_aica(dreamcastcard);
 271                 dreamcastcard->clicks =
 272                     buffer_size / (AICA_PERIOD_SIZE * runtime->channels);
 273                 return;
 274         } else {
 275                 aica_dma_transfer(runtime->channels,
 276                                   AICA_PERIOD_SIZE * runtime->channels,
 277                                   dreamcastcard->substream);
 278                 snd_pcm_period_elapsed(dreamcastcard->substream);
 279                 dreamcastcard->clicks++;
 280                 if (unlikely(dreamcastcard->clicks >= AICA_PERIOD_NUMBER))
 281                         dreamcastcard->clicks %= AICA_PERIOD_NUMBER;
 282                 mod_timer(&dreamcastcard->timer, jiffies + 1);
 283         }
 284 }
 285 
 286 static void aica_period_elapsed(struct timer_list *t)
 287 {
 288         struct snd_card_aica *dreamcastcard = from_timer(dreamcastcard,
 289                                                               t, timer);
 290         struct snd_pcm_substream *substream = dreamcastcard->substream;
 291         /*timer function - so cannot sleep */
 292         int play_period;
 293         struct snd_pcm_runtime *runtime;
 294         runtime = substream->runtime;
 295         dreamcastcard = substream->pcm->private_data;
 296         /* Have we played out an additional period? */
 297         play_period =
 298             frames_to_bytes(runtime,
 299                             readl
 300                             (AICA_CONTROL_CHANNEL_SAMPLE_NUMBER)) /
 301             AICA_PERIOD_SIZE;
 302         if (play_period == dreamcastcard->current_period) {
 303                 /* reschedule the timer */
 304                 mod_timer(&(dreamcastcard->timer), jiffies + 1);
 305                 return;
 306         }
 307         if (runtime->channels > 1)
 308                 dreamcastcard->current_period = play_period;
 309         if (unlikely(dreamcastcard->dma_check == 0))
 310                 dreamcastcard->dma_check = 1;
 311         schedule_work(&(dreamcastcard->spu_dma_work));
 312 }
 313 
 314 static void spu_begin_dma(struct snd_pcm_substream *substream)
 315 {
 316         struct snd_card_aica *dreamcastcard;
 317         struct snd_pcm_runtime *runtime;
 318         runtime = substream->runtime;
 319         dreamcastcard = substream->pcm->private_data;
 320         /*get the queue to do the work */
 321         schedule_work(&(dreamcastcard->spu_dma_work));
 322         mod_timer(&dreamcastcard->timer, jiffies + 4);
 323 }
 324 
 325 static int snd_aicapcm_pcm_open(struct snd_pcm_substream
 326                                 *substream)
 327 {
 328         struct snd_pcm_runtime *runtime;
 329         struct aica_channel *channel;
 330         struct snd_card_aica *dreamcastcard;
 331         if (!enable)
 332                 return -ENOENT;
 333         dreamcastcard = substream->pcm->private_data;
 334         channel = kmalloc(sizeof(struct aica_channel), GFP_KERNEL);
 335         if (!channel)
 336                 return -ENOMEM;
 337         /* set defaults for channel */
 338         channel->sfmt = SM_8BIT;
 339         channel->cmd = AICA_CMD_START;
 340         channel->vol = dreamcastcard->master_volume;
 341         channel->pan = 0x80;
 342         channel->pos = 0;
 343         channel->flags = 0;     /* default to mono */
 344         dreamcastcard->channel = channel;
 345         runtime = substream->runtime;
 346         runtime->hw = snd_pcm_aica_playback_hw;
 347         spu_enable();
 348         dreamcastcard->clicks = 0;
 349         dreamcastcard->current_period = 0;
 350         dreamcastcard->dma_check = 0;
 351         return 0;
 352 }
 353 
 354 static int snd_aicapcm_pcm_close(struct snd_pcm_substream
 355                                  *substream)
 356 {
 357         struct snd_card_aica *dreamcastcard = substream->pcm->private_data;
 358         flush_work(&(dreamcastcard->spu_dma_work));
 359         del_timer(&dreamcastcard->timer);
 360         dreamcastcard->substream = NULL;
 361         kfree(dreamcastcard->channel);
 362         spu_disable();
 363         return 0;
 364 }
 365 
 366 static int snd_aicapcm_pcm_hw_free(struct snd_pcm_substream
 367                                    *substream)
 368 {
 369         /* Free the DMA buffer */
 370         return snd_pcm_lib_free_pages(substream);
 371 }
 372 
 373 static int snd_aicapcm_pcm_hw_params(struct snd_pcm_substream
 374                                      *substream, struct snd_pcm_hw_params
 375                                      *hw_params)
 376 {
 377         /* Allocate a DMA buffer using ALSA built-ins */
 378         return
 379             snd_pcm_lib_malloc_pages(substream,
 380                                      params_buffer_bytes(hw_params));
 381 }
 382 
 383 static int snd_aicapcm_pcm_prepare(struct snd_pcm_substream
 384                                    *substream)
 385 {
 386         struct snd_card_aica *dreamcastcard = substream->pcm->private_data;
 387         if ((substream->runtime)->format == SNDRV_PCM_FORMAT_S16_LE)
 388                 dreamcastcard->channel->sfmt = SM_16BIT;
 389         dreamcastcard->channel->freq = substream->runtime->rate;
 390         dreamcastcard->substream = substream;
 391         return 0;
 392 }
 393 
 394 static int snd_aicapcm_pcm_trigger(struct snd_pcm_substream
 395                                    *substream, int cmd)
 396 {
 397         switch (cmd) {
 398         case SNDRV_PCM_TRIGGER_START:
 399                 spu_begin_dma(substream);
 400                 break;
 401         case SNDRV_PCM_TRIGGER_STOP:
 402                 aica_chn_halt();
 403                 break;
 404         default:
 405                 return -EINVAL;
 406         }
 407         return 0;
 408 }
 409 
 410 static unsigned long snd_aicapcm_pcm_pointer(struct snd_pcm_substream
 411                                              *substream)
 412 {
 413         return readl(AICA_CONTROL_CHANNEL_SAMPLE_NUMBER);
 414 }
 415 
 416 static const struct snd_pcm_ops snd_aicapcm_playback_ops = {
 417         .open = snd_aicapcm_pcm_open,
 418         .close = snd_aicapcm_pcm_close,
 419         .ioctl = snd_pcm_lib_ioctl,
 420         .hw_params = snd_aicapcm_pcm_hw_params,
 421         .hw_free = snd_aicapcm_pcm_hw_free,
 422         .prepare = snd_aicapcm_pcm_prepare,
 423         .trigger = snd_aicapcm_pcm_trigger,
 424         .pointer = snd_aicapcm_pcm_pointer,
 425 };
 426 
 427 /* TO DO: set up to handle more than one pcm instance */
 428 static int __init snd_aicapcmchip(struct snd_card_aica
 429                                   *dreamcastcard, int pcm_index)
 430 {
 431         struct snd_pcm *pcm;
 432         int err;
 433         /* AICA has no capture ability */
 434         err =
 435             snd_pcm_new(dreamcastcard->card, "AICA PCM", pcm_index, 1, 0,
 436                         &pcm);
 437         if (unlikely(err < 0))
 438                 return err;
 439         pcm->private_data = dreamcastcard;
 440         strcpy(pcm->name, "AICA PCM");
 441         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 442                         &snd_aicapcm_playback_ops);
 443         /* Allocate the DMA buffers */
 444         snd_pcm_lib_preallocate_pages_for_all(pcm,
 445                                               SNDRV_DMA_TYPE_CONTINUOUS,
 446                                               snd_dma_continuous_data(GFP_KERNEL),
 447                                               AICA_BUFFER_SIZE,
 448                                               AICA_BUFFER_SIZE);
 449         return 0;
 450 }
 451 
 452 /* Mixer controls */
 453 #define aica_pcmswitch_info             snd_ctl_boolean_mono_info
 454 
 455 static int aica_pcmswitch_get(struct snd_kcontrol *kcontrol,
 456                               struct snd_ctl_elem_value *ucontrol)
 457 {
 458         ucontrol->value.integer.value[0] = 1;   /* TO DO: Fix me */
 459         return 0;
 460 }
 461 
 462 static int aica_pcmswitch_put(struct snd_kcontrol *kcontrol,
 463                               struct snd_ctl_elem_value *ucontrol)
 464 {
 465         if (ucontrol->value.integer.value[0] == 1)
 466                 return 0;       /* TO DO: Fix me */
 467         else
 468                 aica_chn_halt();
 469         return 0;
 470 }
 471 
 472 static int aica_pcmvolume_info(struct snd_kcontrol *kcontrol,
 473                                struct snd_ctl_elem_info *uinfo)
 474 {
 475         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 476         uinfo->count = 1;
 477         uinfo->value.integer.min = 0;
 478         uinfo->value.integer.max = 0xFF;
 479         return 0;
 480 }
 481 
 482 static int aica_pcmvolume_get(struct snd_kcontrol *kcontrol,
 483                               struct snd_ctl_elem_value *ucontrol)
 484 {
 485         struct snd_card_aica *dreamcastcard;
 486         dreamcastcard = kcontrol->private_data;
 487         if (unlikely(!dreamcastcard->channel))
 488                 return -ETXTBSY;        /* we've not yet been set up */
 489         ucontrol->value.integer.value[0] = dreamcastcard->channel->vol;
 490         return 0;
 491 }
 492 
 493 static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol,
 494                               struct snd_ctl_elem_value *ucontrol)
 495 {
 496         struct snd_card_aica *dreamcastcard;
 497         unsigned int vol;
 498         dreamcastcard = kcontrol->private_data;
 499         if (unlikely(!dreamcastcard->channel))
 500                 return -ETXTBSY;
 501         vol = ucontrol->value.integer.value[0];
 502         if (vol > 0xff)
 503                 return -EINVAL;
 504         if (unlikely(dreamcastcard->channel->vol == vol))
 505                 return 0;
 506         dreamcastcard->channel->vol = ucontrol->value.integer.value[0];
 507         dreamcastcard->master_volume = ucontrol->value.integer.value[0];
 508         spu_memload(AICA_CHANNEL0_CONTROL_OFFSET,
 509                     dreamcastcard->channel, sizeof(struct aica_channel));
 510         return 1;
 511 }
 512 
 513 static const struct snd_kcontrol_new snd_aica_pcmswitch_control = {
 514         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 515         .name = "PCM Playback Switch",
 516         .index = 0,
 517         .info = aica_pcmswitch_info,
 518         .get = aica_pcmswitch_get,
 519         .put = aica_pcmswitch_put
 520 };
 521 
 522 static const struct snd_kcontrol_new snd_aica_pcmvolume_control = {
 523         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 524         .name = "PCM Playback Volume",
 525         .index = 0,
 526         .info = aica_pcmvolume_info,
 527         .get = aica_pcmvolume_get,
 528         .put = aica_pcmvolume_put
 529 };
 530 
 531 static int load_aica_firmware(void)
 532 {
 533         int err;
 534         const struct firmware *fw_entry;
 535         spu_reset();
 536         err = request_firmware(&fw_entry, "aica_firmware.bin", &pd->dev);
 537         if (unlikely(err))
 538                 return err;
 539         /* write firmware into memory */
 540         spu_disable();
 541         spu_memload(0, fw_entry->data, fw_entry->size);
 542         spu_enable();
 543         release_firmware(fw_entry);
 544         return err;
 545 }
 546 
 547 static int add_aicamixer_controls(struct snd_card_aica *dreamcastcard)
 548 {
 549         int err;
 550         err = snd_ctl_add
 551             (dreamcastcard->card,
 552              snd_ctl_new1(&snd_aica_pcmvolume_control, dreamcastcard));
 553         if (unlikely(err < 0))
 554                 return err;
 555         err = snd_ctl_add
 556             (dreamcastcard->card,
 557              snd_ctl_new1(&snd_aica_pcmswitch_control, dreamcastcard));
 558         if (unlikely(err < 0))
 559                 return err;
 560         return 0;
 561 }
 562 
 563 static int snd_aica_remove(struct platform_device *devptr)
 564 {
 565         struct snd_card_aica *dreamcastcard;
 566         dreamcastcard = platform_get_drvdata(devptr);
 567         if (unlikely(!dreamcastcard))
 568                 return -ENODEV;
 569         snd_card_free(dreamcastcard->card);
 570         kfree(dreamcastcard);
 571         return 0;
 572 }
 573 
 574 static int snd_aica_probe(struct platform_device *devptr)
 575 {
 576         int err;
 577         struct snd_card_aica *dreamcastcard;
 578         dreamcastcard = kzalloc(sizeof(struct snd_card_aica), GFP_KERNEL);
 579         if (unlikely(!dreamcastcard))
 580                 return -ENOMEM;
 581         err = snd_card_new(&devptr->dev, index, SND_AICA_DRIVER,
 582                            THIS_MODULE, 0, &dreamcastcard->card);
 583         if (unlikely(err < 0)) {
 584                 kfree(dreamcastcard);
 585                 return err;
 586         }
 587         strcpy(dreamcastcard->card->driver, "snd_aica");
 588         strcpy(dreamcastcard->card->shortname, SND_AICA_DRIVER);
 589         strcpy(dreamcastcard->card->longname,
 590                "Yamaha AICA Super Intelligent Sound Processor for SEGA Dreamcast");
 591         /* Prepare to use the queue */
 592         INIT_WORK(&(dreamcastcard->spu_dma_work), run_spu_dma);
 593         timer_setup(&dreamcastcard->timer, aica_period_elapsed, 0);
 594         /* Load the PCM 'chip' */
 595         err = snd_aicapcmchip(dreamcastcard, 0);
 596         if (unlikely(err < 0))
 597                 goto freedreamcast;
 598         /* Add basic controls */
 599         err = add_aicamixer_controls(dreamcastcard);
 600         if (unlikely(err < 0))
 601                 goto freedreamcast;
 602         /* Register the card with ALSA subsystem */
 603         err = snd_card_register(dreamcastcard->card);
 604         if (unlikely(err < 0))
 605                 goto freedreamcast;
 606         platform_set_drvdata(devptr, dreamcastcard);
 607         snd_printk
 608             ("ALSA Driver for Yamaha AICA Super Intelligent Sound Processor\n");
 609         return 0;
 610       freedreamcast:
 611         snd_card_free(dreamcastcard->card);
 612         kfree(dreamcastcard);
 613         return err;
 614 }
 615 
 616 static struct platform_driver snd_aica_driver = {
 617         .probe = snd_aica_probe,
 618         .remove = snd_aica_remove,
 619         .driver = {
 620                 .name = SND_AICA_DRIVER,
 621         },
 622 };
 623 
 624 static int __init aica_init(void)
 625 {
 626         int err;
 627         err = platform_driver_register(&snd_aica_driver);
 628         if (unlikely(err < 0))
 629                 return err;
 630         pd = platform_device_register_simple(SND_AICA_DRIVER, -1,
 631                                              aica_memory_space, 2);
 632         if (IS_ERR(pd)) {
 633                 platform_driver_unregister(&snd_aica_driver);
 634                 return PTR_ERR(pd);
 635         }
 636         /* Load the firmware */
 637         return load_aica_firmware();
 638 }
 639 
 640 static void __exit aica_exit(void)
 641 {
 642         platform_device_unregister(pd);
 643         platform_driver_unregister(&snd_aica_driver);
 644         /* Kill any sound still playing and reset ARM7 to safe state */
 645         spu_reset();
 646 }
 647 
 648 module_init(aica_init);
 649 module_exit(aica_exit);

/* [<][>][^][v][top][bottom][index][help] */