X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=sound%2Fsh%2Faica.c;h=d49417bf78c693dc115390cd14d6c54d84fd8c7f;hb=5d69a029ab13ddef5bdad69174fabafada4a87fd;hp=739786529ca5e8b834425d809773629c296a3a13;hpb=2cb7e714229681408e323852bed939989faf6991;p=~andy%2Flinux diff --git a/sound/sh/aica.c b/sound/sh/aica.c index 739786529ca..d49417bf78c 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -106,11 +105,14 @@ static void spu_write_wait(void) static void spu_memset(u32 toi, u32 what, int length) { int i; + unsigned long flags; snd_assert(length % 4 == 0, return); for (i = 0; i < length; i++) { if (!(i % 8)) spu_write_wait(); + local_irq_save(flags); writel(what, toi + SPU_MEMORY_BASE); + local_irq_restore(flags); toi++; } } @@ -118,6 +120,7 @@ static void spu_memset(u32 toi, u32 what, int length) /* spu_memload - write to SPU address space */ static void spu_memload(u32 toi, void *from, int length) { + unsigned long flags; u32 *froml = from; u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi); int i; @@ -128,7 +131,9 @@ static void spu_memload(u32 toi, void *from, int length) if (!(i % 8)) spu_write_wait(); val = *froml; + local_irq_save(flags); writel(val, to); + local_irq_restore(flags); froml++; to++; } @@ -138,28 +143,36 @@ static void spu_memload(u32 toi, void *from, int length) static void spu_disable(void) { int i; + unsigned long flags; u32 regval; spu_write_wait(); regval = readl(ARM_RESET_REGISTER); regval |= 1; spu_write_wait(); + local_irq_save(flags); writel(regval, ARM_RESET_REGISTER); + local_irq_restore(flags); for (i = 0; i < 64; i++) { spu_write_wait(); regval = readl(SPU_REGISTER_BASE + (i * 0x80)); regval = (regval & ~0x4000) | 0x8000; spu_write_wait(); + local_irq_save(flags); writel(regval, SPU_REGISTER_BASE + (i * 0x80)); + local_irq_restore(flags); } } /* spu_enable - set spu registers to enable sound output */ static void spu_enable(void) { + unsigned long flags; u32 regval = readl(ARM_RESET_REGISTER); regval &= ~1; spu_write_wait(); + local_irq_save(flags); writel(regval, ARM_RESET_REGISTER); + local_irq_restore(flags); } /* @@ -168,25 +181,34 @@ static void spu_enable(void) */ static void spu_reset(void) { + unsigned long flags; spu_disable(); spu_memset(0, 0, 0x200000 / 4); /* Put ARM7 in endless loop */ + local_irq_save(flags); ctrl_outl(0xea000002, SPU_MEMORY_BASE); + local_irq_restore(flags); spu_enable(); } /* aica_chn_start - write to spu to start playback */ static void aica_chn_start(void) { + unsigned long flags; spu_write_wait(); + local_irq_save(flags); writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT); + local_irq_restore(flags); } /* aica_chn_halt - write to spu to halt playback */ static void aica_chn_halt(void) { + unsigned long flags; spu_write_wait(); + local_irq_save(flags); writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT); + local_irq_restore(flags); } /* ALSA code below */ @@ -213,12 +235,14 @@ static int aica_dma_transfer(int channels, int buffer_size, int q, err, period_offset; struct snd_card_aica *dreamcastcard; struct snd_pcm_runtime *runtime; + unsigned long flags; err = 0; dreamcastcard = substream->pcm->private_data; period_offset = dreamcastcard->clicks; period_offset %= (AICA_PERIOD_NUMBER / channels); runtime = substream->runtime; for (q = 0; q < channels; q++) { + local_irq_save(flags); err = dma_xfer(AICA_DMA_CHANNEL, (unsigned long) (runtime->dma_area + (AICA_BUFFER_SIZE * q) / @@ -228,9 +252,12 @@ static int aica_dma_transfer(int channels, int buffer_size, AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET + AICA_PERIOD_SIZE * period_offset, buffer_size / channels, AICA_DMA_MODE); - if (unlikely(err < 0)) + if (unlikely(err < 0)) { + local_irq_restore(flags); break; + } dma_wait_for_completion(AICA_DMA_CHANNEL); + local_irq_restore(flags); } return err; } @@ -451,15 +478,7 @@ static int __init snd_aicapcmchip(struct snd_card_aica } /* Mixer controls */ -static int aica_pcmswitch_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} +#define aica_pcmswitch_info snd_ctl_boolean_mono_info static int aica_pcmswitch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -503,11 +522,14 @@ static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_card_aica *dreamcastcard; + unsigned int vol; dreamcastcard = kcontrol->private_data; if (unlikely(!dreamcastcard->channel)) return -ETXTBSY; - if (unlikely(dreamcastcard->channel->vol == - ucontrol->value.integer.value[0])) + vol = ucontrol->value.integer.value[0]; + if (vol > 0xff) + return -EINVAL; + if (unlikely(dreamcastcard->channel->vol == vol)) return 0; dreamcastcard->channel->vol = ucontrol->value.integer.value[0]; dreamcastcard->master_volume = ucontrol->value.integer.value[0];