clean
[linux-2.4.21-pre4.git] / drivers / video / skeletonfb.c
1 /*
2  * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
3  *
4  *  Created 28 Dec 1997 by Geert Uytterhoeven
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file COPYING in the main directory of this archive
8  * for more details.
9  */
10
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/errno.h>
14 #include <linux/string.h>
15 #include <linux/mm.h>
16 #include <linux/tty.h>
17 #include <linux/slab.h>
18 #include <linux/delay.h>
19 #include <linux/fb.h>
20 #include <linux/init.h>
21
22 #include <video/fbcon.h>
23
24
25     /*
26      *  This is just simple sample code.
27      *
28      *  No warranty that it actually compiles.
29      *  Even less warranty that it actually works :-)
30      */
31
32
33 struct xxxfb_info {
34     /*
35      *  Choose _one_ of the two alternatives:
36      *
37      *    1. Use the generic frame buffer operations (fbgen_*).
38      */
39     struct fb_info_gen gen;
40     /*
41      *    2. Provide your own frame buffer operations.
42      */
43     struct fb_info info;
44
45     /* Here starts the frame buffer device dependent part */
46     /* You can use this to store e.g. the board number if you support */
47     /* multiple boards */
48 };
49
50
51 struct xxxfb_par {
52     /*
53      *  The hardware specific data in this structure uniquely defines a video
54      *  mode.
55      *
56      *  If your hardware supports only one video mode, you can leave it empty.
57      */
58 };
59
60
61     /*
62      *  If your driver supports multiple boards, you should make these arrays,
63      *  or allocate them dynamically (using kmalloc()).
64      */
65
66 static struct xxxfb_info fb_info;
67 static struct xxxfb_par current_par;
68 static int current_par_valid = 0;
69 static struct display disp;
70
71 static struct fb_var_screeninfo default_var;
72
73 static int currcon = 0;
74 static int inverse = 0;
75
76 int xxxfb_init(void);
77 int xxxfb_setup(char*);
78
79 /* ------------------- chipset specific functions -------------------------- */
80
81
82 static void xxx_detect(void)
83 {
84     /*
85      *  This function should detect the current video mode settings and store
86      *  it as the default video mode
87      */
88
89     struct xxxfb_par par;
90
91     /* ... */
92     xxx_get_par(&par);
93     xxx_encode_var(&default_var, &par);
94 }
95
96 static int xxx_encode_fix(struct fb_fix_screeninfo *fix, struct xxxfb_par *par,
97                           const struct fb_info *info)
98 {
99     /*
100      *  This function should fill in the 'fix' structure based on the values
101      *  in the `par' structure.
102      */
103
104     /* ... */
105     return 0;
106 }
107
108 static int xxx_decode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
109                           const struct fb_info *info)
110 {
111     /*
112      *  Get the video params out of 'var'. If a value doesn't fit, round it up,
113      *  if it's too big, return -EINVAL.
114      *
115      *  Suggestion: Round up in the following order: bits_per_pixel, xres,
116      *  yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
117      *  bitfields, horizontal timing, vertical timing.
118      */
119
120     /* ... */
121
122     /* pixclock in picos, htotal in pixels, vtotal in scanlines */
123     if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
124             return -EINVAL;
125
126     return 0;
127 }
128
129 static int xxx_encode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
130                           const struct fb_info *info)
131 {
132     /*
133      *  Fill the 'var' structure based on the values in 'par' and maybe other
134      *  values read out of the hardware.
135      */
136
137     /* ... */
138     return 0;
139 }
140
141 static void xxx_get_par(struct xxxfb_par *par, const struct fb_info *info)
142 {
143     /*
144      *  Fill the hardware's 'par' structure.
145      */
146
147     if (current_par_valid)
148         *par = current_par;
149     else {
150         /* ... */
151     }
152 }
153
154 static void xxx_set_par(struct xxxfb_par *par, const struct fb_info *info)
155 {
156     /*
157      *  Set the hardware according to 'par'.
158      */
159
160     current_par = *par;
161     current_par_valid = 1;
162     /* ... */
163 }
164
165 static int xxx_getcolreg(unsigned regno, unsigned *red, unsigned *green,
166                          unsigned *blue, unsigned *transp,
167                          const struct fb_info *info)
168 {
169     /*
170      *  Read a single color register and split it into colors/transparent.
171      *  The return values must have a 16 bit magnitude.
172      *  Return != 0 for invalid regno.
173      */
174
175     /* ... */
176     return 0;
177 }
178
179 static int xxx_setcolreg(unsigned regno, unsigned red, unsigned green,
180                          unsigned blue, unsigned transp,
181                          const struct fb_info *info)
182 {
183     /*
184      *  Set a single color register. The values supplied have a 16 bit
185      *  magnitude.
186      *  Return != 0 for invalid regno.
187      */
188
189     if (regno < 16) {
190         /*
191          *  Make the first 16 colors of the palette available to fbcon
192          */
193         if (is_cfb15)           /* RGB 555 */
194             ...fbcon_cmap.cfb16[regno] = ((red & 0xf800) >> 1) |
195                                          ((green & 0xf800) >> 6) |
196                                          ((blue & 0xf800) >> 11);
197         if (is_cfb16)           /* RGB 565 */
198             ...fbcon_cmap.cfb16[regno] = (red & 0xf800) |
199                                          ((green & 0xfc00) >> 5) |
200                                          ((blue & 0xf800) >> 11);
201         if (is_cfb24)           /* RGB 888 */
202             ...fbcon_cmap.cfb24[regno] = ((red & 0xff00) << 8) |
203                                          (green & 0xff00) |
204                                          ((blue & 0xff00) >> 8);
205         if (is_cfb32)           /* RGBA 8888 */
206             ...fbcon_cmap.cfb32[regno] = ((red & 0xff00) << 16) |
207                                          ((green & 0xff00) << 8) |
208                                          (blue & 0xff00) |
209                                          ((transp & 0xff00) >> 8);
210     }
211     /* ... */
212     return 0;
213 }
214
215 static int xxx_pan_display(struct fb_var_screeninfo *var,
216                            struct xxxfb_par *par, const struct fb_info *info)
217 {
218     /*
219      *  Pan (or wrap, depending on the `vmode' field) the display using the
220      *  `xoffset' and `yoffset' fields of the `var' structure.
221      *  If the values don't fit, return -EINVAL.
222      */
223
224     /* ... */
225     return 0;
226 }
227
228 static int xxx_blank(int blank_mode, const struct fb_info *info)
229 {
230     /*
231      *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
232      *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
233      *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
234      *  to e.g. a video mode which doesn't support it. Implements VESA suspend
235      *  and powerdown modes on hardware that supports disabling hsync/vsync:
236      *    blank_mode == 2: suspend vsync
237      *    blank_mode == 3: suspend hsync
238      *    blank_mode == 4: powerdown
239      */
240
241     /* ... */
242     return 0;
243 }
244
245 static void xxx_set_disp(const void *par, struct display *disp,
246                          struct fb_info_gen *info)
247 {
248     /*
249      *  Fill in a pointer with the virtual address of the mapped frame buffer.
250      *  Fill in a pointer to appropriate low level text console operations (and
251      *  optionally a pointer to help data) for the video mode `par' of your
252      *  video hardware. These can be generic software routines, or hardware
253      *  accelerated routines specifically tailored for your hardware.
254      *  If you don't have any appropriate operations, you must fill in a
255      *  pointer to dummy operations, and there will be no text output.
256      */
257     disp->screen_base = virtual_frame_buffer_address;
258 #ifdef FBCON_HAS_CFB8
259     if (is_cfb8) {
260         disp->dispsw = fbcon_cfb8;
261     } else
262 #endif
263 #ifdef FBCON_HAS_CFB16
264     if (is_cfb16) {
265         disp->dispsw = fbcon_cfb16;
266         disp->dispsw_data = ...fbcon_cmap.cfb16;        /* console palette */
267     } else
268 #endif
269 #ifdef FBCON_HAS_CFB24
270     if (is_cfb24) {
271         disp->dispsw = fbcon_cfb24;
272         disp->dispsw_data = ...fbcon_cmap.cfb24;        /* console palette */
273     } else
274 #endif
275 #ifdef FBCON_HAS_CFB32
276     if (is_cfb32) {
277         disp->dispsw = fbcon_cfb32;
278         disp->dispsw_data = ...fbcon_cmap.cfb32;        /* console palette */
279     } else
280 #endif
281         disp->dispsw = &fbcon_dummy;
282 }
283
284
285 /* ------------ Interfaces to hardware functions ------------ */
286
287
288 struct fbgen_hwswitch xxx_switch = {
289     xxx_detect, xxx_encode_fix, xxx_decode_var, xxx_encode_var, xxx_get_par,
290     xxx_set_par, xxx_getcolreg, xxx_setcolreg, xxx_pan_display, xxx_blank,
291     xxx_set_disp
292 };
293
294
295
296 /* ------------ Hardware Independent Functions ------------ */
297
298
299     /*
300      *  Initialization
301      */
302
303 int __init xxxfb_init(void)
304 {
305     fb_info.gen.fbhw = &xxx_switch;
306     fb_info.gen.fbhw->detect();
307     strcpy(fb_info.gen.info.modename, "XXX");
308     fb_info.gen.info.changevar = NULL;
309     fb_info.gen.info.node = -1;
310     fb_info.gen.info.fbops = &xxxfb_ops;
311     fb_info.gen.info.disp = &disp;
312     fb_info.gen.info.switch_con = &xxxfb_switch;
313     fb_info.gen.info.updatevar = &xxxfb_update_var;
314     fb_info.gen.info.blank = &xxxfb_blank;
315     fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
316     /* This should give a reasonable default video mode */
317     fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
318     fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
319     fbgen_set_disp(-1, &fb_info.gen);
320     fbgen_install_cmap(0, &fb_info.gen);
321     if (register_framebuffer(&fb_info.gen.info) < 0)
322         return -EINVAL;
323     printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
324            fb_info.gen.info.modename);
325
326     /* uncomment this if your driver cannot be unloaded */
327     /* MOD_INC_USE_COUNT; */
328     return 0;
329 }
330
331
332     /*
333      *  Cleanup
334      */
335
336 void xxxfb_cleanup(struct fb_info *info)
337 {
338     /*
339      *  If your driver supports multiple boards, you should unregister and
340      *  clean up all instances.
341      */
342
343     unregister_framebuffer(info);
344     /* ... */
345 }
346
347
348     /*
349      *  Setup
350      */
351
352 int __init xxxfb_setup(char *options)
353 {
354     /* Parse user speficied options (`video=xxxfb:') */
355 }
356
357
358 /* ------------------------------------------------------------------------- */
359
360
361     /*
362      *  Frame buffer operations
363      */
364
365 /* If all you need is that - just don't define ->fb_open */
366 static int xxxfb_open(const struct fb_info *info, int user)
367 {
368     return 0;
369 }
370
371 /* If all you need is that - just don't define ->fb_release */
372 static int xxxfb_release(const struct fb_info *info, int user)
373 {
374     return 0;
375 }
376
377
378     /*
379      *  In most cases the `generic' routines (fbgen_*) should be satisfactory.
380      *  However, you're free to fill in your own replacements.
381      */
382
383 static struct fb_ops xxxfb_ops = {
384         owner:          THIS_MODULE,
385         fb_open:        xxxfb_open,    /* only if you need it to do something */
386         fb_release:     xxxfb_release, /* only if you need it to do something */
387         fb_get_fix:     fbgen_get_fix,
388         fb_get_var:     fbgen_get_var,
389         fb_set_var:     fbgen_set_var,
390         fb_get_cmap:    fbgen_get_cmap,
391         fb_set_cmap:    fbgen_set_cmap,
392         fb_pan_display: fbgen_pan_display,
393         fb_ioctl:       xxxfb_ioctl,   /* optional */
394 };
395
396
397 /* ------------------------------------------------------------------------- */
398
399
400     /*
401      *  Modularization
402      */
403
404 #ifdef MODULE
405 MODULE_LICENSE("GPL");
406 int init_module(void)
407 {
408     return xxxfb_init();
409 }
410
411 void cleanup_module(void)
412 {
413     xxxfb_cleanup(void);
414 }
415 #endif /* MODULE */