Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
sound
core
rtctimer.c
Go to the documentation of this file.
1
/*
2
* RTC based high-frequency timer
3
*
4
* Copyright (C) 2000 Takashi Iwai
5
* based on rtctimer.c by Steve Ratcliffe
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
*
21
*/
22
23
#include <
linux/init.h
>
24
#include <
linux/interrupt.h
>
25
#include <linux/module.h>
26
#include <
linux/log2.h
>
27
#include <
sound/core.h
>
28
#include <
sound/timer.h
>
29
30
#if defined(CONFIG_RTC) || defined(CONFIG_RTC_MODULE)
31
32
#include <
linux/mc146818rtc.h
>
33
34
#define RTC_FREQ 1024
/* default frequency */
35
#define NANO_SEC 1000000000L
/* 10^9 in sec */
36
37
/*
38
* prototypes
39
*/
40
static
int
rtctimer_open(
struct
snd_timer
*
t
);
41
static
int
rtctimer_close(
struct
snd_timer
*
t
);
42
static
int
rtctimer_start(
struct
snd_timer
*
t
);
43
static
int
rtctimer_stop(
struct
snd_timer
*
t
);
44
45
46
/*
47
* The hardware dependent description for this timer.
48
*/
49
static
struct
snd_timer_hardware
rtc_hw = {
50
.
flags
=
SNDRV_TIMER_HW_AUTO
|
51
SNDRV_TIMER_HW_FIRST
|
52
SNDRV_TIMER_HW_TASKLET
,
53
.ticks = 100000000
L
,
/* FIXME: XXX */
54
.open = rtctimer_open,
55
.close = rtctimer_close,
56
.start = rtctimer_start,
57
.stop = rtctimer_stop,
58
};
59
60
static
int
rtctimer_freq =
RTC_FREQ
;
/* frequency */
61
static
struct
snd_timer
*rtctimer;
62
static
struct
tasklet_struct
rtc_tasklet;
63
static
rtc_task_t
rtc_task
;
64
65
66
static
int
67
rtctimer_open(
struct
snd_timer
*
t
)
68
{
69
int
err
;
70
71
err =
rtc_register
(&
rtc_task
);
72
if
(err < 0)
73
return
err
;
74
t->
private_data
= &
rtc_task
;
75
return
0;
76
}
77
78
static
int
79
rtctimer_close(
struct
snd_timer
*t)
80
{
81
rtc_task_t
*
rtc
= t->
private_data
;
82
if
(rtc) {
83
rtc_unregister
(rtc);
84
tasklet_kill
(&rtc_tasklet);
85
t->
private_data
=
NULL
;
86
}
87
return
0;
88
}
89
90
static
int
91
rtctimer_start(
struct
snd_timer
*
timer
)
92
{
93
rtc_task_t
*rtc = timer->
private_data
;
94
if
(
snd_BUG_ON
(!rtc))
95
return
-
EINVAL
;
96
rtc_control
(rtc,
RTC_IRQP_SET
, rtctimer_freq);
97
rtc_control
(rtc,
RTC_PIE_ON
, 0);
98
return
0;
99
}
100
101
static
int
102
rtctimer_stop(
struct
snd_timer
*timer)
103
{
104
rtc_task_t
*rtc = timer->
private_data
;
105
if
(
snd_BUG_ON
(!rtc))
106
return
-
EINVAL
;
107
rtc_control
(rtc,
RTC_PIE_OFF
, 0);
108
return
0;
109
}
110
111
static
void
rtctimer_tasklet(
unsigned
long
data
)
112
{
113
snd_timer_interrupt
((
struct
snd_timer
*)data, 1);
114
}
115
116
/*
117
* interrupt
118
*/
119
static
void
rtctimer_interrupt(
void
*
private_data
)
120
{
121
tasklet_schedule(private_data);
122
}
123
124
125
/*
126
* ENTRY functions
127
*/
128
static
int
__init
rtctimer_init(
void
)
129
{
130
int
err
;
131
struct
snd_timer
*
timer
;
132
133
if
(rtctimer_freq < 2 || rtctimer_freq > 8192 ||
134
!
is_power_of_2
(rtctimer_freq)) {
135
snd_printk
(
KERN_ERR
"rtctimer: invalid frequency %d\n"
,
136
rtctimer_freq);
137
return
-
EINVAL
;
138
}
139
140
/* Create a new timer and set up the fields */
141
err =
snd_timer_global_new
(
"rtc"
,
SNDRV_TIMER_GLOBAL_RTC
, &timer);
142
if
(err < 0)
143
return
err
;
144
145
timer->
module
=
THIS_MODULE
;
146
strcpy
(timer->
name
,
"RTC timer"
);
147
timer->
hw
= rtc_hw;
148
timer->
hw
.resolution =
NANO_SEC
/ rtctimer_freq;
149
150
tasklet_init
(&rtc_tasklet, rtctimer_tasklet, (
unsigned
long
)timer);
151
152
/* set up RTC callback */
153
rtc_task
.
func
= rtctimer_interrupt;
154
rtc_task
.
private_data
= &rtc_tasklet;
155
156
err =
snd_timer_global_register
(timer);
157
if
(err < 0) {
158
snd_timer_global_free
(timer);
159
return
err
;
160
}
161
rtctimer =
timer
;
/* remember this */
162
163
return
0;
164
}
165
166
static
void
__exit
rtctimer_exit(
void
)
167
{
168
if
(rtctimer) {
169
snd_timer_global_free
(rtctimer);
170
rtctimer =
NULL
;
171
}
172
}
173
174
175
/*
176
* exported stuff
177
*/
178
module_init
(rtctimer_init)
179
module_exit
(rtctimer_exit)
180
181
module_param
(rtctimer_freq,
int
, 0444);
182
MODULE_PARM_DESC
(rtctimer_freq, "timer
frequency
in
Hz");
183
184
MODULE_LICENSE
("GPL");
185
186
MODULE_ALIAS
("snd-timer-"
__stringify
(
SNDRV_TIMER_GLOBAL_RTC
));
187
188
#endif
/* CONFIG_RTC || CONFIG_RTC_MODULE */
Generated on Thu Jan 10 2013 15:03:57 for Linux Kernel by
1.8.2