diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
commit | beb116954b9b7f3bb56412b2494b562f02b864b1 (patch) | |
tree | 120e997879884e1b9d93b265221b939d2ef1ade1 /drivers/sound/sound_timer.c | |
parent | 908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff) |
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'drivers/sound/sound_timer.c')
-rw-r--r-- | drivers/sound/sound_timer.c | 236 |
1 files changed, 86 insertions, 150 deletions
diff --git a/drivers/sound/sound_timer.c b/drivers/sound/sound_timer.c index c6544c82a..eea01c3fe 100644 --- a/drivers/sound/sound_timer.c +++ b/drivers/sound/sound_timer.c @@ -1,39 +1,20 @@ /* * sound/sound_timer.c + */ +/* + * Copyright (C) by Hannu Savolainen 1993-1996 * - * Timer for the level 2 interface of the /dev/sequencer. Uses the - * 80 and 320 usec timers of OPL-3 (PAS16 only) and GUS. - * - * Copyright by Hannu Savolainen 1993 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * + * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) + * Version 2 (June 1991). See the "COPYING" file distributed with this software + * for more info. */ +#include <linux/config.h> + #define SEQUENCER_C #include "sound_config.h" -#ifdef CONFIGURE_SOUNDCARD - -#if !defined(EXCLUDE_SEQUENCER) && (!defined(EXCLUDE_GUS) || (!defined(EXCLUDE_PAS) && !defined(EXCLUDE_YM3812))) +#if defined(CONFIG_SEQUENCER) static volatile int initialized = 0, opened = 0, tmr_running = 0; static volatile time_t tmr_offs, tmr_ctr; @@ -42,53 +23,16 @@ static volatile int curr_tempo, curr_timebase; static volatile unsigned long curr_ticks; static volatile unsigned long next_event_time; static unsigned long prev_event_time; -static volatile int select_addr, data_addr; -static volatile int curr_timer = 0; static volatile unsigned long usecs_per_tmr; /* Length of the current interval */ - -static void -timer_command (unsigned int addr, unsigned int val) -{ - int i; - - OUTB ((unsigned char) (addr & 0xff), select_addr); - - for (i = 0; i < 2; i++) - INB (select_addr); - - OUTB ((unsigned char) (val & 0xff), data_addr); - - for (i = 0; i < 2; i++) - INB (select_addr); -} - -static void -arm_timer (int timer, unsigned int interval) -{ - - curr_timer = timer; - - if (timer == 1) - { - gus_write8 (0x46, 256 - interval); /* Set counter for timer 1 */ - gus_write8 (0x45, 0x04); /* Enable timer 1 IRQ */ - timer_command (0x04, 0x01); /* Start timer 1 */ - } - else - { - gus_write8 (0x47, 256 - interval); /* Set counter for timer 2 */ - gus_write8 (0x45, 0x08); /* Enable timer 2 IRQ */ - timer_command (0x04, 0x02); /* Start timer 2 */ - } -} +static struct sound_lowlev_timer *tmr = NULL; static unsigned long tmr2ticks (int tmr_value) { /* - * Convert timer ticks to MIDI ticks - */ + * Convert timer ticks to MIDI ticks + */ unsigned long tmp; unsigned long scale; @@ -104,32 +48,30 @@ static void reprogram_timer (void) { unsigned long usecs_per_tick; - int timer_no, resolution; - int divisor; usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase); /* - * Don't kill the system by setting too high timer rate - */ + * Don't kill the system by setting too high timer rate + */ if (usecs_per_tick < 2000) usecs_per_tick = 2000; - if (usecs_per_tick > (256 * 80)) - { - timer_no = 2; - resolution = 320; /* usec */ - } - else - { - timer_no = 1; - resolution = 80; /* usec */ - } + usecs_per_tmr = tmr->tmr_start (tmr->dev, usecs_per_tick); +} - divisor = (usecs_per_tick + (resolution / 2)) / resolution; - usecs_per_tmr = divisor * resolution; +void +sound_timer_syncinterval (unsigned int new_usecs) +{ +/* + * This routine is called by the hardware level if + * the clock frequency has changed for some reason. + */ + tmr_offs = tmr_ctr; + ticks_offs += tmr2ticks (tmr_ctr); + tmr_ctr = 0; - arm_timer (timer_no, divisor); + usecs_per_tmr = new_usecs; } static void @@ -137,25 +79,26 @@ tmr_reset (void) { unsigned long flags; - DISABLE_INTR (flags); + save_flags (flags); + cli (); tmr_offs = 0; ticks_offs = 0; tmr_ctr = 0; - next_event_time = 0xffffffff; + next_event_time = (unsigned long) -1; prev_event_time = 0; curr_ticks = 0; - RESTORE_INTR (flags); + restore_flags (flags); } static int timer_open (int dev, int mode) { if (opened) - return RET_ERROR (EBUSY); + return -EBUSY; tmr_reset (); curr_tempo = 60; - curr_timebase = HZ; + curr_timebase = 100; opened = 1; reprogram_timer (); @@ -166,7 +109,7 @@ static void timer_close (int dev) { opened = tmr_running = 0; - gus_write8 (0x45, 0); /* Disable both timers */ + tmr->tmr_disable (tmr->dev); } static int @@ -245,12 +188,14 @@ timer_get_time (int dev) static int timer_ioctl (int dev, - unsigned int cmd, unsigned int arg) + unsigned int cmd, caddr_t arg) { + int val; + switch (cmd) { case SNDCTL_TMR_SOURCE: - return IOCTL_OUT (arg, TMR_INTERNAL); + return ioctl_out (arg, TMR_INTERNAL); break; case SNDCTL_TMR_START: @@ -270,58 +215,60 @@ timer_ioctl (int dev, break; case SNDCTL_TMR_TIMEBASE: - { - int val = IOCTL_IN (arg); - - if (val) - { - if (val < 1) - val = 1; - if (val > 1000) - val = 1000; - curr_timebase = val; - } - - return IOCTL_OUT (arg, curr_timebase); - } + get_user (val, (int *) arg); + + if (val) + { + if (val < 1) + val = 1; + if (val > 1000) + val = 1000; + curr_timebase = val; + } + + return ioctl_out (arg, curr_timebase); break; case SNDCTL_TMR_TEMPO: - { - int val = IOCTL_IN (arg); - - if (val) - { - if (val < 8) - val = 8; - if (val > 250) - val = 250; - tmr_offs = tmr_ctr; - ticks_offs += tmr2ticks (tmr_ctr); - tmr_ctr = 0; - curr_tempo = val; - reprogram_timer (); - } - - return IOCTL_OUT (arg, curr_tempo); - } + get_user (val, (int *) arg); + + if (val) + { + if (val < 8) + val = 8; + if (val > 250) + val = 250; + tmr_offs = tmr_ctr; + ticks_offs += tmr2ticks (tmr_ctr); + tmr_ctr = 0; + curr_tempo = val; + reprogram_timer (); + } + + return ioctl_out (arg, curr_tempo); break; case SNDCTL_SEQ_CTRLRATE: - if (IOCTL_IN (arg) != 0) /* Can't change */ - return RET_ERROR (EINVAL); + get_user (val, (int *) arg); + + if (val != 0) /* Can't change */ + return -EINVAL; + + return ioctl_out (arg, ((curr_tempo * curr_timebase) + 30) / 60); + break; - return IOCTL_OUT (arg, ((curr_tempo * curr_timebase) + 30) / 60); + case SNDCTL_SEQ_GETTIME: + return ioctl_out (arg, curr_ticks); break; case SNDCTL_TMR_METRONOME: /* NOP */ break; - default: + default:; } - return RET_ERROR (EINVAL); + return -EINVAL; } static void @@ -339,7 +286,7 @@ timer_arm (int dev, long time) static struct sound_timer_operations sound_timer = { - {"OPL-3/GUS Timer", 0}, + {"GUS Timer", 0}, 1, /* Priority */ 0, /* Local device link */ timer_open, @@ -353,16 +300,10 @@ static struct sound_timer_operations sound_timer = void sound_timer_interrupt (void) { - gus_write8 (0x45, 0); /* Ack IRQ */ - timer_command (4, 0x80); /* Reset IRQ flags */ - if (!opened) return; - if (curr_timer == 1) - gus_write8 (0x45, 0x04); /* Start timer 1 again */ - else - gus_write8 (0x45, 0x08); /* Start timer 2 again */ + tmr->tmr_restart (tmr->dev); if (!tmr_running) return; @@ -372,35 +313,30 @@ sound_timer_interrupt (void) if (curr_ticks >= next_event_time) { - next_event_time = 0xffffffff; - sequencer_timer (); + next_event_time = (unsigned long) -1; + sequencer_timer (0); } } void -sound_timer_init (int io_base) +sound_timer_init (struct sound_lowlev_timer *t, char *name) { int n; - if (initialized) + if (initialized || t == NULL) return; /* There is already a similar timer */ - select_addr = io_base; - data_addr = io_base + 1; - initialized = 1; + tmr = t; -#if 1 if (num_sound_timers >= MAX_TIMER_DEV) n = 0; /* Overwrite the system timer */ else n = num_sound_timers++; -#else - n = 0; -#endif + + strcpy (sound_timer.info.name, name); sound_timer_devs[n] = &sound_timer; } #endif -#endif |