1 /* -------------------------------------------------------------------- */
2 /* LINUX FBCON FRAMEBUFFER UTILITY CODE */
3 /* makes setting up the framebuffer easy. Also makes it eays to port to */
4 /* some other system if needed. */
5 /* Copyright (c) 1999 - Carsten Haitzler (The Rasterman) */
6 /* -------------------------------------------------------------------- */
7 #include "evas_common.h"
11 #include <sys/ioctl.h>
22 /* -------------------------------------------------------------------- */
23 /* internal variables */
25 static struct fb_fix_screeninfo fb_fix;
27 static int bpp, depth;
28 static int orig_vt_no = 0;
30 static struct vt_mode vt_omode;
31 static struct fb_var_screeninfo fb_ovar;
32 static unsigned short ored[256], ogreen[256], oblue[256];
33 static unsigned short red[256], green[256], blue[256];
34 static struct fb_cmap ocmap = { 0, 256, ored, ogreen, oblue, NULL };
35 static struct fb_cmap cmap = { 0, 256, red, green, blue, NULL };
37 /* -------------------------------------------------------------------- */
38 /* internal function prototypes */
40 static void fb_cleanup(void);
41 //static void fb_cleanup_fork(void);
42 static void fb_setvt(int vtno);
43 static void fb_init_palette_332(FB_Mode *mode);
44 static void fb_init_palette_linear(FB_Mode *mode);
46 /* -------------------------------------------------------------------- */
50 fb_init_palette_332(FB_Mode *mode)
54 if (mode->fb_var.bits_per_pixel != 8)
58 if (ioctl(fb, FBIOGETCMAP, &cmap) == -1)
59 perror("ioctl FBIOGETCMAP");
61 /* generate the palette */
62 for (r = 0; r < 8; r++)
64 for (g = 0; g < 8; g++)
66 for (b = 0; b < 4; b++)
70 val = (r << 5) | (r << 2) | (r >> 1);
71 red[i] = (val << 8) | val;
72 val = (g << 5) | (g << 2) | (g >> 1);
73 green[i] = (val << 8) | val;
74 val = (b << 6) | (b << 4) | (b << 2) | (b);
75 blue[i] = (val << 8) | val;
82 if (ioctl(fb, FBIOPUTCMAP, &cmap) == -1)
83 perror("ioctl FBIOPUTCMAP");
88 fb_init_palette_linear(FB_Mode *mode)
92 if (mode->fb_var.bits_per_pixel != 8)
95 if (ioctl(fb, FBIOGETCMAP, &cmap) == -1)
96 perror("ioctl FBIOGETCMAP");
98 /* generate the palette */
99 for (i = 0; i < 256; i++)
100 red[i] = (i << 8) | i;
101 for (i = 0; i < 256; i++)
102 green[i] = (i << 8) | i;
103 for (i = 0; i < 256; i++)
104 blue[i] = (i << 8) | i;
107 if (ioctl(fb, FBIOPUTCMAP, &cmap) == -1)
108 perror("ioctl FBIOPUTCMAP");
112 /* -------------------------------------------------------------------- */
113 /* initialisation & cleanup */
116 fb_list_modes(int *num_return)
119 char line[256], label[256], value[256];
120 FB_Mode *modes = NULL;
124 f = fopen("/etc/fb.modes","r");
130 while (fgets(line, sizeof(line) - 1, f))
132 if (sscanf(line, "mode \"%250[^\"]\"", label) == 1)
134 char f1[32], f2[32], f3[32], f4[32];
136 f1[0] = 0; f2[0] = 0; f3[0] = 0; f4[0] = 0;
137 sscanf(label, "%30[^x]x%30[^-]-%30[^-]-%30s", f1, f2, f3, f4);
138 if ((f1[0]) && (f2[0]))
144 modes = realloc(modes, num * sizeof(FB_Mode));
145 modes[num - 1].width = atoi(f1);
146 modes[num - 1].height = atoi(f2);
148 modes[num - 1].refresh = atoi(f3);
150 modes[num - 1].refresh = 0;
151 modes[num - 1].fb_var.sync = 0;
152 while ((fgets(line, sizeof(line) - 1, f)) &&
153 (!strstr(line, "endmode")))
156 if (sscanf(line," geometry %i %i %i %i %i",
157 &modes[num - 1].fb_var.xres,
158 &modes[num - 1].fb_var.yres,
159 &modes[num - 1].fb_var.xres_virtual,
160 &modes[num - 1].fb_var.yres_virtual,
161 &modes[num - 1].fb_var.bits_per_pixel) == 5)
163 if (sscanf(line," timings %i %i %i %i %i %i %i",
164 &modes[num - 1].fb_var.pixclock,
165 &modes[num - 1].fb_var.left_margin,
166 &modes[num - 1].fb_var.right_margin,
167 &modes[num - 1].fb_var.upper_margin,
168 &modes[num - 1].fb_var.lower_margin,
169 &modes[num - 1].fb_var.hsync_len,
170 &modes[num - 1].fb_var.vsync_len) == 7)
172 if ((sscanf(line, " hsync %15s", value) == 1) &&
173 (!strcmp(value,"high")))
174 modes[num - 1].fb_var.sync |= FB_SYNC_HOR_HIGH_ACT;
175 if ((sscanf(line, " vsync %15s", value) == 1) &&
176 (!strcmp(value,"high")))
177 modes[num - 1].fb_var.sync |= FB_SYNC_VERT_HIGH_ACT;
178 if ((sscanf(line, " csync %15s", value) == 1) &&
179 (!strcmp(value,"high")))
180 modes[num - 1].fb_var.sync |= FB_SYNC_COMP_HIGH_ACT;
181 if ((sscanf(line, " extsync %15s", value) == 1) &&
182 (!strcmp(value,"true")))
183 modes[num - 1].fb_var.sync |= FB_SYNC_EXT;
184 if ((sscanf(line, " laced %15s", value) == 1) &&
185 (!strcmp(value,"true")))
186 modes[num - 1].fb_var.vmode |= FB_VMODE_INTERLACED;
187 if ((sscanf(line, " double %15s",value) == 1) &&
188 (!strcmp(value,"true")))
189 modes[num - 1].fb_var.vmode |= FB_VMODE_DOUBLE;
191 if ((!geometry) || (!timings))
202 modes[num - 1].fb_var.xoffset = 0;
203 modes[num - 1].fb_var.yoffset = 0;
215 fb_setmode(int width, int height, int depth, int refresh)
217 FB_Mode *modes, *mode = NULL;
220 modes = fb_list_modes(&num_modes);
223 for (i = 0; i < num_modes; i++)
225 if ((modes[i].width == width) &&
226 (modes[i].height == height) &&
227 (!depth || modes[i].fb_var.bits_per_pixel == depth) &&
228 (modes[i].refresh == refresh))
230 if (depth) modes[i].fb_var.bits_per_pixel = depth;
232 if (ioctl(fb, FBIOPUT_VSCREENINFO, &modes[i].fb_var) == -1)
233 perror("ioctl FBIOPUT_VSCREENINFO");
245 fb_changedepth(FB_Mode *cur_mode, int depth)
247 cur_mode->fb_var.bits_per_pixel = depth;
249 if (ioctl(fb, FBIOPUT_VSCREENINFO, &cur_mode->fb_var) == -1)
250 perror("ioctl FBIOPUT_VSCREENINFO");
257 fb_changeres(FB_Mode *cur_mode, int width, int height, int refresh)
262 modes = fb_list_modes(&num_modes);
265 for (i = 0; i < num_modes; i++)
267 if ((modes[i].width == width) &&
268 (modes[i].height == height) &&
269 (modes[i].refresh == refresh))
271 modes[i].fb_var.bits_per_pixel = cur_mode->depth;
273 if (ioctl(fb, FBIOPUT_VSCREENINFO, &modes[i].fb_var) == -1)
274 perror("ioctl FBIOPUT_VSCREENINFO");
287 fb_changemode(FB_Mode *cur_mode, int width, int height, int depth, int refresh)
292 modes = fb_list_modes(&num_modes);
295 for (i = 0; i < num_modes; i++)
297 if ((modes[i].width == width) &&
298 (modes[i].height == height) &&
299 (!depth || modes[i].fb_var.bits_per_pixel == depth) &&
300 (modes[i].refresh == refresh))
302 if (depth) modes[i].fb_var.bits_per_pixel = depth;
304 if (ioctl(fb, FBIOPUT_VSCREENINFO, &modes[i].fb_var) == -1)
305 perror("ioctl FBIOPUT_VSCREENINFO");
320 FB_Mode *mode = NULL;
321 int hpix, lines, clockrate;
323 mode = malloc(sizeof(FB_Mode));
324 /* look what we have now ... */
326 if (ioctl(fb, FBIOGET_VSCREENINFO, &mode->fb_var) == -1)
328 perror("ioctl FBIOGET_VSCREENINFO");
332 mode->width = mode->fb_var.xres;
333 mode->height = mode->fb_var.yres;
335 mode->fb_var.left_margin +
337 mode->fb_var.right_margin +
338 mode->fb_var.hsync_len;
340 mode->fb_var.upper_margin +
342 mode->fb_var.lower_margin +
343 mode->fb_var.vsync_len;
344 if (mode->fb_var.pixclock > 0)
345 clockrate = 1000000 / mode->fb_var.pixclock;
348 if ((lines > 0) && (hpix > 0))
349 mode->refresh = clockrate * 1000000 / (lines * hpix);
350 switch (mode->fb_var.bits_per_pixel)
366 if (mode->fb_var.green.length == 6)
374 bpp = mode->fb_var.bits_per_pixel / 8;
378 bpp = mode->fb_var.bits_per_pixel / 8;
381 fprintf(stderr, "Cannot handle framebuffer of depth %i\n",
382 mode->fb_var.bits_per_pixel);
389 if (mode->depth == 8)
390 fb_init_palette_332(mode);
392 fb_init_palette_linear(mode);
405 if ((ioctl(tty,VT_OPENQRY, &vtno) == -1))
407 perror("ioctl VT_OPENQRY");
412 perror("ioctl VT_OPENQRY vtno <= 0");
418 sprintf(vtname, "/dev/tty%i", vtno);
419 chown(vtname, getuid(), getgid());
420 if (access(vtname,R_OK | W_OK) == -1)
422 fprintf(stderr,"access %s: %s\n",vtname,strerror(errno));
427 if (ioctl(tty, VT_GETSTATE, &vts) == -1)
429 perror("ioctl VT_GETSTATE");
433 orig_vt_no = vts.v_active;
435 if (ioctl(tty, VT_ACTIVATE, vtno) == -1)
437 perror("ioctl VT_ACTIVATE");
440 if (ioctl(tty, VT_WAITACTIVE, vtno) == -1)
442 perror("ioctl VT_WAITACTIVE");
450 fb_init(int vt, int device)
456 if (vt != 0) fb_setvt(vt);
458 sprintf(dev, "/dev/fb/%i", device);
459 fb = open(dev, O_RDWR);
462 sprintf(dev, "/dev/fb%i", device);
463 fb = open(dev, O_RDWR);
467 fprintf(stderr,"open %s: %s\n", dev, strerror(errno));
472 if (ioctl(fb, FBIOGET_VSCREENINFO, &fb_ovar) == -1)
474 perror("ioctl FBIOGET_VSCREENINFO");
477 if (ioctl(fb, FBIOGET_FSCREENINFO, &fb_fix) == -1)
479 perror("ioctl FBIOGET_FSCREENINFO");
483 if ((fb_ovar.bits_per_pixel == 8) ||
484 (fb_fix.visual == FB_VISUAL_DIRECTCOLOR))
487 if (ioctl(fb,FBIOGETCMAP , &ocmap) == -1)
489 perror("ioctl FBIOGETCMAP");
497 else if ((tty = open("/dev/tty",O_RDWR)) == -1)
499 fprintf(stderr,"open %s: %s\n", "/dev/tty", strerror(errno));
504 if (ioctl(tty, KDGETMODE, &kd_mode) == -1)
506 perror("ioctl KDGETMODE");
509 if (ioctl(tty, VT_GETMODE, &vt_omode) == -1)
511 perror("ioctl VT_GETMODE");
519 fb_postinit(FB_Mode *mode)
522 if (ioctl(fb,FBIOGET_FSCREENINFO, &fb_fix) == -1)
524 perror("ioctl FBIOGET_FSCREENINFO");
529 if (fb_fix.type != FB_TYPE_PACKED_PIXELS)
531 fprintf(stderr,"can handle only packed pixel frame buffers\n");
535 mode->mem_offset = (unsigned)(fb_fix.smem_start) & (getpagesize()-1);
536 mode->mem = (unsigned char *)mmap(NULL, fb_fix.smem_len + mode->mem_offset,
537 PROT_WRITE | PROT_READ, MAP_SHARED, fb, 0);
538 if (mode->mem == MAP_FAILED)
543 /* move viewport to upper left corner */
544 if ((mode->fb_var.xoffset != 0) || (mode->fb_var.yoffset != 0))
546 mode->fb_var.xoffset = 0;
547 mode->fb_var.yoffset = 0;
549 if (ioctl(fb, FBIOPAN_DISPLAY, &(mode->fb_var)) == -1)
551 perror("ioctl FBIOPAN_DISPLAY");
558 if (ioctl(tty,KDSETMODE, KD_GRAPHICS) == -1)
560 perror("ioctl KDSETMODE");
572 /* restore console */
574 if (ioctl(fb, FBIOPUT_VSCREENINFO, &fb_ovar) == -1)
575 perror("ioctl FBIOPUT_VSCREENINFO");
576 if (ioctl(fb, FBIOGET_FSCREENINFO, &fb_fix) == -1)
577 perror("ioctl FBIOGET_FSCREENINFO");
579 if ((fb_ovar.bits_per_pixel == 8) ||
580 (fb_fix.visual == FB_VISUAL_DIRECTCOLOR))
583 if (ioctl(fb, FBIOPUTCMAP, &ocmap) == -1)
584 perror("ioctl FBIOPUTCMAP");
592 if (ioctl(tty, KDSETMODE, kd_mode) == -1)
593 perror("ioctl KDSETMODE");
594 if (ioctl(tty, VT_SETMODE, &vt_omode) == -1)
595 perror("ioctl VT_SETMODE");
596 /* if ((ioctl(tty, VT_ACTIVATE, orig_vt_no) == -1) && (orig_vt_no))
597 perror("ioctl VT_ACTIVATE");