2 * Routines for Gravis UltraSound soundcards - Timers
3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
5 * GUS have similar timers as AdLib (OPL2/OPL3 chips).
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <linux/time.h>
25 #include <sound/core.h>
26 #include <sound/gus.h>
32 static int snd_gf1_timer1_start(struct snd_timer
* timer
)
37 struct snd_gus_card
*gus
;
39 gus
= snd_timer_chip(timer
);
40 spin_lock_irqsave(&gus
->reg_lock
, flags
);
41 ticks
= timer
->sticks
;
42 tmp
= (gus
->gf1
.timer_enabled
|= 4);
43 snd_gf1_write8(gus
, SNDRV_GF1_GB_ADLIB_TIMER_1
, 256 - ticks
); /* timer 1 count */
44 snd_gf1_write8(gus
, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL
, tmp
); /* enable timer 1 IRQ */
45 snd_gf1_adlib_write(gus
, 0x04, tmp
>> 2); /* timer 2 start */
46 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
50 static int snd_gf1_timer1_stop(struct snd_timer
* timer
)
54 struct snd_gus_card
*gus
;
56 gus
= snd_timer_chip(timer
);
57 spin_lock_irqsave(&gus
->reg_lock
, flags
);
58 tmp
= (gus
->gf1
.timer_enabled
&= ~4);
59 snd_gf1_write8(gus
, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL
, tmp
); /* disable timer #1 */
60 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
68 static int snd_gf1_timer2_start(struct snd_timer
* timer
)
73 struct snd_gus_card
*gus
;
75 gus
= snd_timer_chip(timer
);
76 spin_lock_irqsave(&gus
->reg_lock
, flags
);
77 ticks
= timer
->sticks
;
78 tmp
= (gus
->gf1
.timer_enabled
|= 8);
79 snd_gf1_write8(gus
, SNDRV_GF1_GB_ADLIB_TIMER_2
, 256 - ticks
); /* timer 2 count */
80 snd_gf1_write8(gus
, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL
, tmp
); /* enable timer 2 IRQ */
81 snd_gf1_adlib_write(gus
, 0x04, tmp
>> 2); /* timer 2 start */
82 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
86 static int snd_gf1_timer2_stop(struct snd_timer
* timer
)
90 struct snd_gus_card
*gus
;
92 gus
= snd_timer_chip(timer
);
93 spin_lock_irqsave(&gus
->reg_lock
, flags
);
94 tmp
= (gus
->gf1
.timer_enabled
&= ~8);
95 snd_gf1_write8(gus
, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL
, tmp
); /* disable timer #1 */
96 spin_unlock_irqrestore(&gus
->reg_lock
, flags
);
104 static void snd_gf1_interrupt_timer1(struct snd_gus_card
* gus
)
106 struct snd_timer
*timer
= gus
->gf1
.timer1
;
110 snd_timer_interrupt(timer
, timer
->sticks
);
113 static void snd_gf1_interrupt_timer2(struct snd_gus_card
* gus
)
115 struct snd_timer
*timer
= gus
->gf1
.timer2
;
119 snd_timer_interrupt(timer
, timer
->sticks
);
126 static struct snd_timer_hardware snd_gf1_timer1
=
128 .flags
= SNDRV_TIMER_HW_STOP
,
131 .start
= snd_gf1_timer1_start
,
132 .stop
= snd_gf1_timer1_stop
,
135 static struct snd_timer_hardware snd_gf1_timer2
=
137 .flags
= SNDRV_TIMER_HW_STOP
,
138 .resolution
= 320000,
140 .start
= snd_gf1_timer2_start
,
141 .stop
= snd_gf1_timer2_stop
,
144 static void snd_gf1_timer1_free(struct snd_timer
*timer
)
146 struct snd_gus_card
*gus
= timer
->private_data
;
147 gus
->gf1
.timer1
= NULL
;
150 static void snd_gf1_timer2_free(struct snd_timer
*timer
)
152 struct snd_gus_card
*gus
= timer
->private_data
;
153 gus
->gf1
.timer2
= NULL
;
156 void snd_gf1_timers_init(struct snd_gus_card
* gus
)
158 struct snd_timer
*timer
;
159 struct snd_timer_id tid
;
161 if (gus
->gf1
.timer1
!= NULL
|| gus
->gf1
.timer2
!= NULL
)
164 gus
->gf1
.interrupt_handler_timer1
= snd_gf1_interrupt_timer1
;
165 gus
->gf1
.interrupt_handler_timer2
= snd_gf1_interrupt_timer2
;
167 tid
.dev_class
= SNDRV_TIMER_CLASS_CARD
;
168 tid
.dev_sclass
= SNDRV_TIMER_SCLASS_NONE
;
169 tid
.card
= gus
->card
->number
;
170 tid
.device
= gus
->timer_dev
;
173 if (snd_timer_new(gus
->card
, "GF1 timer", &tid
, &timer
) >= 0) {
174 strcpy(timer
->name
, "GF1 timer #1");
175 timer
->private_data
= gus
;
176 timer
->private_free
= snd_gf1_timer1_free
;
177 timer
->hw
= snd_gf1_timer1
;
179 gus
->gf1
.timer1
= timer
;
183 if (snd_timer_new(gus
->card
, "GF1 timer", &tid
, &timer
) >= 0) {
184 strcpy(timer
->name
, "GF1 timer #2");
185 timer
->private_data
= gus
;
186 timer
->private_free
= snd_gf1_timer2_free
;
187 timer
->hw
= snd_gf1_timer2
;
189 gus
->gf1
.timer2
= timer
;
192 void snd_gf1_timers_done(struct snd_gus_card
* gus
)
194 snd_gf1_set_default_handlers(gus
, SNDRV_GF1_HANDLER_TIMER1
| SNDRV_GF1_HANDLER_TIMER2
);
195 if (gus
->gf1
.timer1
) {
196 snd_device_free(gus
->card
, gus
->gf1
.timer1
);
197 gus
->gf1
.timer1
= NULL
;
199 if (gus
->gf1
.timer2
) {
200 snd_device_free(gus
->card
, gus
->gf1
.timer2
);
201 gus
->gf1
.timer2
= NULL
;