diff options
Diffstat (limited to 'arch/mips/lasat/picvue_proc.c')
-rw-r--r-- | arch/mips/lasat/picvue_proc.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c new file mode 100644 index 000000000000..eaa2b4625124 --- /dev/null +++ b/arch/mips/lasat/picvue_proc.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * Picvue PVC160206 display driver | ||
3 | * | ||
4 | * Brian Murphy <brian.murphy@eicon.com> | ||
5 | * | ||
6 | */ | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/module.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/errno.h> | ||
11 | |||
12 | #include <linux/proc_fs.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | |||
15 | #include <linux/timer.h> | ||
16 | |||
17 | #include "picvue.h" | ||
18 | |||
19 | static char pvc_lines[PVC_NLINES][PVC_LINELEN+1]; | ||
20 | static int pvc_linedata[PVC_NLINES]; | ||
21 | static struct proc_dir_entry *pvc_display_dir; | ||
22 | static char *pvc_linename[PVC_NLINES] = {"line1", "line2"}; | ||
23 | #define DISPLAY_DIR_NAME "display" | ||
24 | static int scroll_dir = 0, scroll_interval = 0; | ||
25 | |||
26 | static struct timer_list timer; | ||
27 | |||
28 | static void pvc_display(unsigned long data) { | ||
29 | int i; | ||
30 | |||
31 | pvc_clear(); | ||
32 | for (i=0; i<PVC_NLINES; i++) | ||
33 | pvc_write_string(pvc_lines[i], 0, i); | ||
34 | } | ||
35 | |||
36 | static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0); | ||
37 | |||
38 | static int pvc_proc_read_line(char *page, char **start, | ||
39 | off_t off, int count, | ||
40 | int *eof, void *data) | ||
41 | { | ||
42 | char *origpage = page; | ||
43 | int lineno = *(int *)data; | ||
44 | |||
45 | if (lineno < 0 || lineno > PVC_NLINES) { | ||
46 | printk("proc_read_line: invalid lineno %d\n", lineno); | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | down(&pvc_sem); | ||
51 | page += sprintf(page, "%s\n", pvc_lines[lineno]); | ||
52 | up(&pvc_sem); | ||
53 | |||
54 | return page - origpage; | ||
55 | } | ||
56 | |||
57 | static int pvc_proc_write_line(struct file *file, const char *buffer, | ||
58 | unsigned long count, void *data) | ||
59 | { | ||
60 | int origcount = count; | ||
61 | int lineno = *(int *)data; | ||
62 | |||
63 | if (lineno < 0 || lineno > PVC_NLINES) { | ||
64 | printk("proc_write_line: invalid lineno %d\n", lineno); | ||
65 | return origcount; | ||
66 | } | ||
67 | |||
68 | if (count > PVC_LINELEN) | ||
69 | count = PVC_LINELEN; | ||
70 | |||
71 | if (buffer[count-1] == '\n') | ||
72 | count--; | ||
73 | |||
74 | down(&pvc_sem); | ||
75 | strncpy(pvc_lines[lineno], buffer, count); | ||
76 | pvc_lines[lineno][count] = '\0'; | ||
77 | up(&pvc_sem); | ||
78 | |||
79 | tasklet_schedule(&pvc_display_tasklet); | ||
80 | |||
81 | return origcount; | ||
82 | } | ||
83 | |||
84 | static int pvc_proc_write_scroll(struct file *file, const char *buffer, | ||
85 | unsigned long count, void *data) | ||
86 | { | ||
87 | int origcount = count; | ||
88 | int cmd = simple_strtol(buffer, NULL, 10); | ||
89 | |||
90 | down(&pvc_sem); | ||
91 | if (scroll_interval != 0) | ||
92 | del_timer(&timer); | ||
93 | |||
94 | if (cmd == 0) { | ||
95 | scroll_dir = 0; | ||
96 | scroll_interval = 0; | ||
97 | } else { | ||
98 | if (cmd < 0) { | ||
99 | scroll_dir = -1; | ||
100 | scroll_interval = -cmd; | ||
101 | } else { | ||
102 | scroll_dir = 1; | ||
103 | scroll_interval = cmd; | ||
104 | } | ||
105 | add_timer(&timer); | ||
106 | } | ||
107 | up(&pvc_sem); | ||
108 | |||
109 | return origcount; | ||
110 | } | ||
111 | |||
112 | static int pvc_proc_read_scroll(char *page, char **start, | ||
113 | off_t off, int count, | ||
114 | int *eof, void *data) | ||
115 | { | ||
116 | char *origpage = page; | ||
117 | |||
118 | down(&pvc_sem); | ||
119 | page += sprintf(page, "%d\n", scroll_dir * scroll_interval); | ||
120 | up(&pvc_sem); | ||
121 | |||
122 | return page - origpage; | ||
123 | } | ||
124 | |||
125 | |||
126 | void pvc_proc_timerfunc(unsigned long data) | ||
127 | { | ||
128 | if (scroll_dir < 0) | ||
129 | pvc_move(DISPLAY|RIGHT); | ||
130 | else if (scroll_dir > 0) | ||
131 | pvc_move(DISPLAY|LEFT); | ||
132 | |||
133 | timer.expires = jiffies + scroll_interval; | ||
134 | add_timer(&timer); | ||
135 | } | ||
136 | |||
137 | static void pvc_proc_cleanup(void) | ||
138 | { | ||
139 | int i; | ||
140 | for (i=0; i<PVC_NLINES; i++) | ||
141 | remove_proc_entry(pvc_linename[i], pvc_display_dir); | ||
142 | remove_proc_entry("scroll", pvc_display_dir); | ||
143 | remove_proc_entry(DISPLAY_DIR_NAME, NULL); | ||
144 | |||
145 | del_timer(&timer); | ||
146 | } | ||
147 | |||
148 | static int __init pvc_proc_init(void) | ||
149 | { | ||
150 | struct proc_dir_entry *proc_entry; | ||
151 | int i; | ||
152 | |||
153 | pvc_display_dir = proc_mkdir(DISPLAY_DIR_NAME, NULL); | ||
154 | if (pvc_display_dir == NULL) | ||
155 | goto error; | ||
156 | |||
157 | for (i=0; i<PVC_NLINES; i++) { | ||
158 | strcpy(pvc_lines[i], ""); | ||
159 | pvc_linedata[i] = i; | ||
160 | } | ||
161 | for (i=0; i<PVC_NLINES; i++) { | ||
162 | proc_entry = create_proc_entry(pvc_linename[i], 0644, pvc_display_dir); | ||
163 | if (proc_entry == NULL) | ||
164 | goto error; | ||
165 | proc_entry->read_proc = pvc_proc_read_line; | ||
166 | proc_entry->write_proc = pvc_proc_write_line; | ||
167 | proc_entry->data = &pvc_linedata[i]; | ||
168 | } | ||
169 | proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir); | ||
170 | if (proc_entry == NULL) | ||
171 | goto error; | ||
172 | proc_entry->write_proc = pvc_proc_write_scroll; | ||
173 | proc_entry->read_proc = pvc_proc_read_scroll; | ||
174 | |||
175 | init_timer(&timer); | ||
176 | timer.function = pvc_proc_timerfunc; | ||
177 | |||
178 | return 0; | ||
179 | error: | ||
180 | pvc_proc_cleanup(); | ||
181 | return -ENOMEM; | ||
182 | } | ||
183 | |||
184 | module_init(pvc_proc_init); | ||
185 | module_exit(pvc_proc_cleanup); | ||
186 | MODULE_LICENSE("GPL"); | ||