/* Timer handler used to do the VT switch at a time when not drawing */ static void vt_do_switch(void *arg) { static unsigned short r[16], g[16], b[16]; /* * If a drawing function is in progress then we cannot mode * switch right now because the drawing function would continue to * scribble on the screen after the switch. So disable further * drawing and schedule an alarm to try again in .1 second. */ if(mwdrawing) { draw_disable (); GdAddTimer(100, vt_do_switch, NULL); return; } if(visible) { draw_disable (); ioctl_getpalette(0, 16, r, g, b); if(ioctl (ttyfd, VT_RELDISP, 1) == -1) EPRINTF("Error can't switch away from VT: %m\n"); } else { ioctl_setpalette(0, 16, r, g, b); draw_enable (); if(ioctl (ttyfd, VT_RELDISP, VT_ACKACQ) == -1) EPRINTF("Error can't acknowledge VT switch: %m\n"); } }
static void fb_getpalette(PSD psd,int first, int count, GAL_Color *palette) { int i; unsigned short red[count]; unsigned short green[count]; unsigned short blue[count]; ioctl_getpalette(first,count,red,green,blue); for(i=0; i < count; i++) { GAL_Color *p = &palette[i]; /* grayscale computation: * red[i] = green[i] = blue[i] = * (p->r * 77 + p->g * 151 + p->b * 28); */ p->r = (red[i] >> 8) * 100 / fade; p->g = (green[i] >>8) * 100 / fade; p->b = (blue[i] >>8) * 100 / fade; } }
/* init framebuffer*/ static PSD fb_open(PSD psd) { PSUBDRIVER subdriver; struct lcd_info li; assert(status < 2); // Initialize LCD screen lcd_init(16); lcd_getinfo(&li); psd->portrait = MWPORTRAIT_NONE; psd->xres = psd->xvirtres = li.width; psd->yres = psd->yvirtres = li.height; psd->planes = 1; psd->bpp = li.bpp; psd->ncolors = (psd->bpp >= 24)? (1 << 24): (1 << psd->bpp); psd->pitch = li.rlen; psd->size = psd->yres * psd->pitch; psd->flags = PSF_SCREEN; /* set pixel format*/ switch (li.type) { case FB_TRUE_RGB565: psd->pixtype = MWPF_TRUECOLOR565; break; default: EPRINTF("Unsupported display type: %d\n", li.type); goto fail; } #if 0 if(1 /*visual == FB_VISUAL_TRUECOLOR || visual == FB_VISUAL_DIRECTCOLOR*/) { switch(psd->bpp) { case 8: psd->pixtype = MWPF_TRUECOLOR332; break; case 16: psd->pixtype = MWPF_TRUECOLOR565; break; case 24: psd->pixtype = MWPF_TRUECOLOR888; break; case 32: psd->pixtype = MWPF_TRUECOLOR8888; break; default: EPRINTF("Unsupported %d color (%d bpp) truecolor framebuffer\n", psd->ncolors, psd->bpp); goto fail; } } else psd->pixtype = MWPF_PALETTE; #endif diag_printf("%dx%dx%d pitch %d type %d bpp %d\n", psd->xres, psd->yres, psd->ncolors, psd->pitch, li.type, psd->bpp); /* set standard data format from bpp and pixtype*/ psd->data_format = set_data_format(psd); /* select a framebuffer subdriver based on planes and bpp*/ subdriver = select_fb_subdriver(psd); if (!subdriver) { EPRINTF("No driver for screen bpp %d\n", psd->bpp); goto fail; } /* set subdriver into screen driver */ set_subdriver(psd, subdriver); /* mmap framebuffer into this address space*/ psd->addr = li.fb; if(psd->addr == NULL || psd->addr == (unsigned char *)-1) { // EPRINTF("Error mmaping %s: %m\n", env); goto fail; } #if 0 /* FIXME */ /* save original palette*/ ioctl_getpalette(0, 16, saved_red, saved_green, saved_blue); /* setup direct color palette if required (ATI cards)*/ if(visual == FB_VISUAL_DIRECTCOLOR) set_directcolor_palette(psd); #endif status = 2; return psd; /* success*/ fail: return NULL; }
/* init framebuffer*/ static PSD fb_open(PSD psd) { char * env; int type, visual; PSUBDRIVER subdriver; struct fb_fix_screeninfo fb_fix; struct fb_var_screeninfo fb_var; /* locate and open framebuffer, get info*/ if(!(env = getenv ("FRAMEBUFFER"))) env = "/dev/fb0"; fb = open(env, O_RDWR); if(fb < 0) { fprintf(stderr,"GAL fbcon engine: Error when opening %s: %m. Please check kernel config.\n", env); return NULL; } if(ioctl(fb, FBIOGET_FSCREENINFO, &fb_fix) == -1 || ioctl(fb, FBIOGET_VSCREENINFO, &fb_var) == -1) { fprintf(stderr,"GAL fbcon engine: Error when reading screen info: %m.\n"); goto fail; } /* setup screen device from framebuffer info*/ type = fb_fix.type; visual = fb_fix.visual; psd->xres = psd->xvirtres = fb_var.xres; psd->yres = psd->yvirtres = fb_var.yres; /* set planes from fb type*/ if (type == FB_TYPE_VGA_PLANES) psd->planes = 4; else if (type == FB_TYPE_PACKED_PIXELS) psd->planes = 1; else psd->planes = 0; /* force error later*/ psd->bpp = fb_var.bits_per_pixel; psd->ncolors = (psd->bpp >= 24)? (1 << 24): (1 << psd->bpp); /* set linelen to byte length, possibly converted later*/ psd->linelen = (psd->xres * psd->bpp) >> 3; /* * Some framebuffer drivers give wrong line_length value. * If line_length < xres_virtual * bpp, it's certainly wrong. * But how do i know if line_length > xres_virtual * bpp. * God bless me! * James Liu */ if (fb_fix.line_length > psd->linelen) psd->linelen = fb_fix.line_length; psd->size = 0; /* force subdriver init of size*/ psd->flags = PSF_SCREEN; /* * For 1bpp, 2bpp and 4bpp framebuffer, some systems have * different bit order. That means the highest bits represent * the first pixel or the lowest bites represent first pixel. * * For example: * * EP7211 2bpp: Byte 1 Byte 2 * | D0 D1 | D2 D3 | D4 D5 | D6 D7 | | D0 D1 | D2 D3 | D4 D5 | D6 D7 | * | pixel0 | pixel1 | pixel2 | pixel3 | | pixel4 | pixel5 | pixel6 | pixel7 | * * Helio 2bpp: Byte 1 Byte 2 * | D0 D1 | D2 D3 | D4 D5 | D6 D7 | | D0 D1 | D2 D3 | D4 D5 | D6 D7 | * | pixel3 | pixel2 | pixel1 | pixel0 | | pixel7 | pixel6 | pixel5 | pixel4 | */ if (fb_var.red.msb_right) psd->flags |= PSF_MSBRIGHT; /* set pixel format*/ if (visual == FB_VISUAL_TRUECOLOR || visual == FB_VISUAL_DIRECTCOLOR) { switch(psd->bpp) { case 8: psd->pixtype = PF_TRUECOLOR332; break; case 16: psd->pixtype = PF_TRUECOLOR565; break; case 24: psd->pixtype = PF_TRUECOLOR888; break; case 32: psd->pixtype = PF_TRUECOLOR0888; break; default: fprintf(stderr, "GAL fbcon engine: Unsupported FrameBuffer type\n"); goto fail; } } else psd->pixtype = PF_PALETTE; /* select a framebuffer subdriver based on planes and bpp*/ subdriver = select_fb_subdriver(psd); if (!subdriver) { fprintf(stderr,"GAL fbcon engine: No driver for screen type %d visual %d bpp %d\n", type, visual, psd->bpp); goto fail; } /* * set and initialize subdriver into screen driver * psd->size is calculated by subdriver init */ if(!set_subdriver(psd, subdriver, TRUE)) { fprintf(stderr,"GAL fbcon engine: Driver initialize failed type %d visual %d bpp %d\n", type, visual, psd->bpp); goto fail; } #ifdef _HAVE_TEXT_MODE #ifdef _LITE_VERSION if (mgIsServer) #endif { /* open tty, enter graphics mode*/ char* tty_dev; if (geteuid() == 0) tty_dev = "/dev/tty0"; else /* not a super user, so try to open the control terminal */ tty_dev = "/dev/tty"; tty = open (tty_dev, O_RDWR); if(tty < 0) { fprintf(stderr,"GAL fbcon engine: Can't open /dev/tty0: %m\n"); goto fail; } if(ioctl (tty, KDSETMODE, KD_GRAPHICS) == -1) { fprintf(stderr,"GAL fbcon engine: Error when setting console to graphics mode: %m\n"); fprintf(stderr,"GAL fbcon engine: Maybe have no enough permission.\n"); goto fail; } } #endif /* mmap framebuffer into this address space*/ psd->size = (psd->size + getpagesize () - 1) / getpagesize () * getpagesize (); #ifdef __uClinux__ //cyli fix 20080219 // psd->addr = mmap(NULL, psd->size, PROT_READ | PROT_WRITE, 0, fb, 0); psd->addr = do_mmap(NULL, psd->size, PROT_READ | PROT_WRITE, 0, fb, 0); #else //cyli fix 20080219 // psd->addr = mmap(NULL, psd->size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); psd->addr = do_mmap(NULL, psd->size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); #endif // printf("cyli test mmap psd->addr=%x psd->size=%x \n", psd->addr, psd->size); if(psd->addr == NULL || psd->addr == (unsigned char *)-1) { fprintf(stderr,"GAL fbcon engine: Error when mmaping %s: %m\n", env); goto fail; } /* save original palette*/ ioctl_getpalette(0, 16, saved_red, saved_green, saved_blue); status = 2; psd->gr_mode = MODE_SET; return psd; /* success*/ fail: #ifdef _HAVE_TEXT_MODE #ifdef _LITE_VERSION if (mgIsServer) { #endif /* enter text mode*/ if (tty >= 0) { ioctl (tty, KDSETMODE, KD_TEXT); close (tty); tty = -1; } #ifdef _LITE_VERSION } #endif #endif close(fb); return NULL; }