Import 2.3.18pre1
[davej-history.git] / drivers / sound / sys_timer.c
blobe7ca0c84b3acc2a663db4b226e39bf7fd649dc79
1 /*
2 * sound/sys_timer.c
4 * The default timer for the Level 2 sequencer interface
5 * Uses the (1/HZ sec) timer of kernel.
6 */
7 /*
8 * Copyright (C) by Hannu Savolainen 1993-1997
10 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
11 * Version 2 (June 1991). See the "COPYING" file distributed with this software
12 * for more info.
15 * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
16 * Andrew Veliath : adapted tmr2ticks from level 1 sequencer (avoid overflow)
18 #include <linux/config.h>
21 #include "sound_config.h"
23 #ifdef CONFIG_SEQUENCER
25 static volatile int opened = 0, tmr_running = 0;
26 static volatile time_t tmr_offs, tmr_ctr;
27 static volatile unsigned long ticks_offs;
28 static volatile int curr_tempo, curr_timebase;
29 static volatile unsigned long curr_ticks;
30 static volatile unsigned long next_event_time;
31 static unsigned long prev_event_time;
33 static void poll_def_tmr(unsigned long dummy);
36 static struct timer_list def_tmr =
37 {NULL, NULL, 0, 0, poll_def_tmr};
39 static unsigned long
40 tmr2ticks(int tmr_value)
43 * Convert timer ticks to MIDI ticks
46 unsigned long tmp;
47 unsigned long scale;
49 /* tmr_value (ticks per sec) *
50 1000000 (usecs per sec) / HZ (ticks per sec) -=> usecs */
51 tmp = tmr_value * (1000000 / HZ);
52 scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */
53 return (tmp + scale / 2) / scale;
56 static void
57 poll_def_tmr(unsigned long dummy)
60 if (opened)
64 def_tmr.expires = (1) + jiffies;
65 add_timer(&def_tmr);
68 if (tmr_running)
70 tmr_ctr++;
71 curr_ticks = ticks_offs + tmr2ticks(tmr_ctr);
73 if (curr_ticks >= next_event_time)
75 next_event_time = (unsigned long) -1;
76 sequencer_timer(0);
82 static void
83 tmr_reset(void)
85 unsigned long flags;
87 save_flags(flags);
88 cli();
89 tmr_offs = 0;
90 ticks_offs = 0;
91 tmr_ctr = 0;
92 next_event_time = (unsigned long) -1;
93 prev_event_time = 0;
94 curr_ticks = 0;
95 restore_flags(flags);
98 static int
99 def_tmr_open(int dev, int mode)
101 if (opened)
102 return -EBUSY;
104 tmr_reset();
105 curr_tempo = 60;
106 curr_timebase = 100;
107 opened = 1;
112 def_tmr.expires = (1) + jiffies;
113 add_timer(&def_tmr);
116 return 0;
119 static void
120 def_tmr_close(int dev)
122 opened = tmr_running = 0;
123 del_timer(&def_tmr);;
126 static int
127 def_tmr_event(int dev, unsigned char *event)
129 unsigned char cmd = event[1];
130 unsigned long parm = *(int *) &event[4];
132 switch (cmd)
134 case TMR_WAIT_REL:
135 parm += prev_event_time;
136 case TMR_WAIT_ABS:
137 if (parm > 0)
139 long time;
141 if (parm <= curr_ticks) /* It's the time */
142 return TIMER_NOT_ARMED;
144 time = parm;
145 next_event_time = prev_event_time = time;
147 return TIMER_ARMED;
149 break;
151 case TMR_START:
152 tmr_reset();
153 tmr_running = 1;
154 break;
156 case TMR_STOP:
157 tmr_running = 0;
158 break;
160 case TMR_CONTINUE:
161 tmr_running = 1;
162 break;
164 case TMR_TEMPO:
165 if (parm)
167 if (parm < 8)
168 parm = 8;
169 if (parm > 360)
170 parm = 360;
171 tmr_offs = tmr_ctr;
172 ticks_offs += tmr2ticks(tmr_ctr);
173 tmr_ctr = 0;
174 curr_tempo = parm;
176 break;
178 case TMR_ECHO:
179 seq_copy_to_input(event, 8);
180 break;
182 default:;
185 return TIMER_NOT_ARMED;
188 static unsigned long
189 def_tmr_get_time(int dev)
191 if (!opened)
192 return 0;
194 return curr_ticks;
197 /* same as sound_timer.c:timer_ioctl!? */
198 static int def_tmr_ioctl(int dev, unsigned int cmd, caddr_t arg)
200 int val;
202 switch (cmd) {
203 case SNDCTL_TMR_SOURCE:
204 return __put_user(TMR_INTERNAL, (int *)arg);
206 case SNDCTL_TMR_START:
207 tmr_reset();
208 tmr_running = 1;
209 return 0;
211 case SNDCTL_TMR_STOP:
212 tmr_running = 0;
213 return 0;
215 case SNDCTL_TMR_CONTINUE:
216 tmr_running = 1;
217 return 0;
219 case SNDCTL_TMR_TIMEBASE:
220 if (__get_user(val, (int *)arg))
221 return -EFAULT;
222 if (val) {
223 if (val < 1)
224 val = 1;
225 if (val > 1000)
226 val = 1000;
227 curr_timebase = val;
229 return __put_user(curr_timebase, (int *)arg);
231 case SNDCTL_TMR_TEMPO:
232 if (__get_user(val, (int *)arg))
233 return -EFAULT;
234 if (val) {
235 if (val < 8)
236 val = 8;
237 if (val > 250)
238 val = 250;
239 tmr_offs = tmr_ctr;
240 ticks_offs += tmr2ticks(tmr_ctr);
241 tmr_ctr = 0;
242 curr_tempo = val;
243 reprogram_timer();
245 return __put_user(curr_tempo, (int *)arg);
247 case SNDCTL_SEQ_CTRLRATE:
248 if (__get_user(val, (int *)arg))
249 return -EFAULT;
250 if (val != 0) /* Can't change */
251 return -EINVAL;
252 val = ((curr_tempo * curr_timebase) + 30) / 60;
253 return __put_user(val, (int *)arg);
255 case SNDCTL_SEQ_GETTIME:
256 return __put_user(curr_ticks, (int *)arg);
258 case SNDCTL_TMR_METRONOME:
259 /* NOP */
260 break;
262 default:;
264 return -EINVAL;
267 static void
268 def_tmr_arm(int dev, long time)
270 if (time < 0)
271 time = curr_ticks + 1;
272 else if (time <= curr_ticks) /* It's the time */
273 return;
275 next_event_time = prev_event_time = time;
277 return;
280 struct sound_timer_operations default_sound_timer =
282 {"System clock", 0},
283 0, /* Priority */
284 0, /* Local device link */
285 def_tmr_open,
286 def_tmr_close,
287 def_tmr_event,
288 def_tmr_get_time,
289 def_tmr_ioctl,
290 def_tmr_arm
293 #endif