* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / video / fbgen.c
blobff14807a0909b7111fe0df0261f632e2f797bdc8
1 /*
2 * linux/drivers/video/fbgen.c -- Generic routines for frame buffer devices
4 * Created 3 Jan 1998 by Geert Uytterhoeven
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file README.legal in the main directory of this archive
8 * for more details.
9 */
11 #include <linux/module.h>
12 #include <linux/string.h>
13 #include <linux/tty.h>
14 #include <linux/fb.h>
15 #include <linux/slab.h>
17 #include <asm/uaccess.h>
18 #include <asm/io.h>
21 static int currcon = 0;
24 /* ---- `Generic' versions of the frame buffer device operations ----------- */
28 * Get the Fixed Part of the Display
31 int fbgen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
33 struct fb_info_gen *info2 = (struct fb_info_gen *)info;
34 struct fbgen_hwswitch *fbhw = info2->fbhw;
35 char par[info2->parsize];
37 if (con == -1)
38 fbhw->get_par(&par, info2);
39 else {
40 int err;
42 if ((err = fbhw->decode_var(&fb_display[con].var, &par, info2)))
43 return err;
45 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
46 return fbhw->encode_fix(fix, &par, info2);
51 * Get the User Defined Part of the Display
54 int fbgen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
56 struct fb_info_gen *info2 = (struct fb_info_gen *)info;
57 struct fbgen_hwswitch *fbhw = info2->fbhw;
58 char par[info2->parsize];
60 if (con == -1) {
61 fbhw->get_par(&par, info2);
62 fbhw->encode_var(var, &par, info2);
63 } else
64 *var = fb_display[con].var;
65 return 0;
70 * Set the User Defined Part of the Display
73 int fbgen_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
75 struct fb_info_gen *info2 = (struct fb_info_gen *)info;
76 int err;
77 int oldxres, oldyres, oldbpp, oldxres_virtual, oldyres_virtual, oldyoffset;
79 if ((err = fbgen_do_set_var(var, con == currcon, info2)))
80 return err;
81 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
82 oldxres = fb_display[con].var.xres;
83 oldyres = fb_display[con].var.yres;
84 oldxres_virtual = fb_display[con].var.xres_virtual;
85 oldyres_virtual = fb_display[con].var.yres_virtual;
86 oldbpp = fb_display[con].var.bits_per_pixel;
87 oldyoffset = fb_display[con].var.yoffset;
88 fb_display[con].var = *var;
89 if (oldxres != var->xres || oldyres != var->yres ||
90 oldxres_virtual != var->xres_virtual ||
91 oldyres_virtual != var->yres_virtual ||
92 oldbpp != var->bits_per_pixel ||
93 oldyoffset != var->yoffset) {
94 fbgen_set_disp(con, info2);
95 if (info->changevar)
96 (*info->changevar)(con);
97 if ((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))
98 return err;
99 fbgen_install_cmap(con, info2);
102 var->activate = 0;
103 return 0;
108 * Get the Colormap
111 int fbgen_get_cmap(struct fb_cmap *cmap, int kspc, int con,
112 struct fb_info *info)
114 struct fb_info_gen *info2 = (struct fb_info_gen *)info;
115 struct fbgen_hwswitch *fbhw = info2->fbhw;
117 if (con == currcon) /* current console ? */
118 return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
119 else
120 if (fb_display[con].cmap.len) /* non default colormap ? */
121 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
122 else {
123 int size = fb_display[con].var.bits_per_pixel == 16 ? 64 : 256;
124 fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
126 return 0;
131 * Set the Colormap
134 int fbgen_set_cmap(struct fb_cmap *cmap, int kspc, int con,
135 struct fb_info *info)
137 struct fb_info_gen *info2 = (struct fb_info_gen *)info;
138 struct fbgen_hwswitch *fbhw = info2->fbhw;
139 int err;
141 if (!fb_display[con].cmap.len) { /* no colormap allocated ? */
142 int size = fb_display[con].var.bits_per_pixel == 16 ? 64 : 256;
143 if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
144 return err;
146 if (con == currcon) /* current console ? */
147 return fb_set_cmap(cmap, kspc, fbhw->setcolreg, info);
148 else
149 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
150 return 0;
155 * Pan or Wrap the Display
157 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
160 int fbgen_pan_display(struct fb_var_screeninfo *var, int con,
161 struct fb_info *info)
163 struct fb_info_gen *info2 = (struct fb_info_gen *)info;
164 struct fbgen_hwswitch *fbhw = info2->fbhw;
165 int xoffset = var->xoffset;
166 int yoffset = var->yoffset;
167 int err;
169 if (xoffset < 0 ||
170 xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
171 yoffset < 0 ||
172 yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)
173 return -EINVAL;
174 if (con == currcon) {
175 if (fbhw->pan_display) {
176 if ((err = fbhw->pan_display(var, info2)))
177 return err;
178 } else
179 return -EINVAL;
181 fb_display[con].var.xoffset = var->xoffset;
182 fb_display[con].var.yoffset = var->yoffset;
183 if (var->vmode & FB_VMODE_YWRAP)
184 fb_display[con].var.vmode |= FB_VMODE_YWRAP;
185 else
186 fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
188 return 0;
193 * Frame Buffer Specific ioctls
196 int fbgen_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
197 unsigned long arg, int con, struct fb_info *info)
199 return -EINVAL;
203 /* ---- Helper functions --------------------------------------------------- */
207 * Change the video mode
210 int fbgen_do_set_var(struct fb_var_screeninfo *var, int isactive,
211 struct fb_info_gen *info)
213 struct fbgen_hwswitch *fbhw = info->fbhw;
214 int err, activate;
215 char par[info->parsize];
217 if ((err = fbhw->decode_var(var, &par, info)))
218 return err;
219 activate = var->activate;
220 if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
221 fbhw->set_par(&par, info);
222 fbhw->encode_var(var, &par, info);
223 var->activate = activate;
224 return 0;
228 void fbgen_set_disp(int con, struct fb_info_gen *info)
230 struct fbgen_hwswitch *fbhw = info->fbhw;
231 struct fb_fix_screeninfo fix;
232 char par[info->parsize];
233 struct display *display;
235 if (con >= 0)
236 display = &fb_display[con];
237 else
238 display = info->info.disp; /* used during initialization */
240 if (con == -1)
241 fbhw->get_par(&par, info);
242 else
243 fbhw->decode_var(&fb_display[con].var, &par, info);
244 memset(&fix, 0, sizeof(struct fb_fix_screeninfo));
245 fbhw->encode_fix(&fix, &par, info);
247 display->visual = fix.visual;
248 display->type = fix.type;
249 display->type_aux = fix.type_aux;
250 display->ypanstep = fix.ypanstep;
251 display->ywrapstep = fix.ywrapstep;
252 display->line_length = fix.line_length;
253 if (info->fbhw->blank || fix.visual == FB_VISUAL_PSEUDOCOLOR ||
254 fix.visual == FB_VISUAL_DIRECTCOLOR)
255 display->can_soft_blank = 1;
256 else
257 display->can_soft_blank = 0;
258 fbhw->set_disp(&par, display, info);
259 #if 0 /* FIXME: generic inverse is not supported yet */
260 display->inverse = (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
261 #else
262 display->inverse = fix.visual == FB_VISUAL_MONO01;
263 #endif
268 * Install the current colormap
271 void fbgen_install_cmap(int con, struct fb_info_gen *info)
273 struct fbgen_hwswitch *fbhw = info->fbhw;
274 if (con != currcon)
275 return;
276 if (fb_display[con].cmap.len)
277 fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, &info->info);
278 else {
279 int size = fb_display[con].var.bits_per_pixel == 16 ? 64 : 256;
280 fb_set_cmap(fb_default_cmap(size), 1, fbhw->setcolreg, &info->info);
286 * Update the `var' structure (called by fbcon.c)
289 int fbgen_update_var(int con, struct fb_info *info)
291 struct fb_info_gen *info2 = (struct fb_info_gen *)info;
292 struct fbgen_hwswitch *fbhw = info2->fbhw;
293 int err;
295 if (fbhw->pan_display) {
296 if ((err = fbhw->pan_display(&fb_display[con].var, info2)))
297 return err;
299 return 0;
304 * Switch to a different virtual console
307 int fbgen_switch(int con, struct fb_info *info)
309 struct fb_info_gen *info2 = (struct fb_info_gen *)info;
310 struct fbgen_hwswitch *fbhw = info2->fbhw;
312 /* Do we have to save the colormap ? */
313 if (fb_display[currcon].cmap.len)
314 fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
315 &info2->info);
316 fbgen_do_set_var(&fb_display[con].var, 1, info2);
317 currcon = con;
318 /* Install new colormap */
319 fbgen_install_cmap(con, info2);
320 return 0;
325 * Blank the screen
328 void fbgen_blank(int blank, struct fb_info *info)
330 struct fb_info_gen *info2 = (struct fb_info_gen *)info;
331 struct fbgen_hwswitch *fbhw = info2->fbhw;
332 u16 black[16];
333 struct fb_cmap cmap;
335 if (fbhw->blank && !fbhw->blank(blank, info2))
336 return;
337 if (blank) {
338 memset(black, 0, 16*sizeof(u16));
339 cmap.red = black;
340 cmap.green = black;
341 cmap.blue = black;
342 cmap.transp = NULL;
343 cmap.start = 0;
344 cmap.len = 16;
345 fb_set_cmap(&cmap, 1, fbhw->setcolreg, info);
346 } else
347 fbgen_install_cmap(currcon, info2);