aboutsummaryrefslogtreecommitdiffstats
path: root/boards/base/Linux-Framebuffer/board_framebuffer.h
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-05-22 17:21:19 +1000
committerinmarket <andrewh@inmarket.com.au>2014-05-22 17:21:19 +1000
commit285bd0f4d66fa3161a80bf6711d1bef226b17fe3 (patch)
tree93666d6d8831a67f2e6cd6fd008bfa0bf7c4b4d9 /boards/base/Linux-Framebuffer/board_framebuffer.h
parent52cfaf00ccd35f5a0740a489a1a2af64c800b537 (diff)
downloaduGFX-285bd0f4d66fa3161a80bf6711d1bef226b17fe3.tar.gz
uGFX-285bd0f4d66fa3161a80bf6711d1bef226b17fe3.tar.bz2
uGFX-285bd0f4d66fa3161a80bf6711d1bef226b17fe3.zip
GDISP framebuffer driver + an implementation for the linux kernel framebuffer device
Diffstat (limited to 'boards/base/Linux-Framebuffer/board_framebuffer.h')
-rw-r--r--boards/base/Linux-Framebuffer/board_framebuffer.h217
1 files changed, 217 insertions, 0 deletions
diff --git a/boards/base/Linux-Framebuffer/board_framebuffer.h b/boards/base/Linux-Framebuffer/board_framebuffer.h
new file mode 100644
index 00000000..71e00937
--- /dev/null
+++ b/boards/base/Linux-Framebuffer/board_framebuffer.h
@@ -0,0 +1,217 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+// Set this to your frame buffer pixel format. Note Linux frame buffer only supports RGB modes (no BGR modes).
+#ifndef GDISP_LLD_PIXELFORMAT
+ #define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+#endif
+
+#ifdef GDISP_DRIVER_VMT
+
+ #define FBDEV_PATH1 "/dev/fb0"
+ #define FBDEV_PATH2 "/dev/fb/0" // Optional - comment this out to only try the one device
+ #define USE_SET_MODE // Optional - comment this out to not to try to set the color mode we want
+ //#define VTDEV_PATH "/dev/tty0" // Optional - if defined use this tty to switch from text to graphics mode
+
+ #define _GNU_SOURCE 1
+ #include <fcntl.h>
+ #include <limits.h>
+ #include <linux/fb.h>
+ #include <linux/kd.h>
+ #include <linux/vt.h>
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <sys/ioctl.h>
+ #include <sys/mman.h>
+ #include <sys/stat.h>
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+
+ #if VTDEV_PATH
+ static void board_revert2textmode(void) {
+ int tty;
+
+ // Go back to text mode
+ if ((tty = open(VTDEV_PATH, O_RDWR)) >= 0) {
+ ioctl(tty, KDSETMODE, KD_TEXT);
+ close(tty);
+ }
+ }
+ static void board_switch2graphicsmode(void) {
+ int tty;
+
+ // Open the tty
+ if ((tty = open (VTDEV_PATH, O_RDWR)) < 0) {
+ fprintf(stderr, "GDISP Framebuffer: Cannot open tty %s\n", VTDEV_PATH);
+ exit(-1);
+ }
+ if (ioctl (tty, KDSETMODE, KD_GRAPHICS) == -1) {
+ fprintf(stderr, "GDISP Framebuffer: Cannot set to graphics mode\n");
+ exit(-1);
+ }
+ close(tty);
+
+ // Make sure we clean up properly
+ atexit(board_revert2textmode)
+ }
+ #endif
+
+ static void board_init(GDisplay *g, fbInfo *fbi) {
+ int fb;
+ char * env;
+ size_t fblen;
+ struct fb_fix_screeninfo fb_fix;
+ struct fb_var_screeninfo fb_var;
+
+ // Open the frame buffer device
+ if((env = getenv("FRAMEBUFFER")) != 0)
+ fb = open(env, O_RDWR);
+ else {
+ fb = open(FBDEV_PATH1, O_RDWR);
+ #ifdef FBDEV_PATH2
+ if (fb < 0) fb = open(FBDEV_PATH2, O_RDWR);
+ #endif
+ }
+ if(fb < 0) {
+ fprintf(stderr, "GDISP Framebuffer: Error opening the framebuffer device\n");
+ exit(-1);
+ }
+
+ // Get screen info
+ if (ioctl(fb, FBIOGET_FSCREENINFO, &fb_fix) == -1 || ioctl(fb, FBIOGET_VSCREENINFO, &fb_var) == -1) {
+ fprintf(stderr, "GDISP Framebuffer: Error getting screen info\n");
+ exit(-1);
+ }
+
+ #ifdef USE_SET_MODE
+ info.reserved[0] = 0;
+ fb_var.reserved[1] = 0;
+ fb_var.reserved[2] = 0;
+ fb_var.xoffset = 0;
+ fb_var.yoffset = 0;
+ fb_var.bits_per_pixel = LLDCOLOR_BITS;
+ fb_var.activate = FB_ACTIVATE_NOW;
+ if (ioctl(fb, FBIOPUT_VSCREENINFO, &fb_var) == -1 || ioctl (fb, FBIOGET_VSCREENINFO, &fb_var) == -1) {
+ fprintf(stderr, "GDISP Framebuffer: Failed to set video mode\n");
+ exit(-1);
+ }
+ #endif
+
+ // Check things are as they should be
+ if (fb_fix.type != FB_TYPE_PACKED_PIXELS) {
+ fprintf(stderr, "GDISP Framebuffer: The display is not in a single plane graphics mode\n");
+ exit(-1);
+ }
+ if (fb_fix.visual != FB_VISUAL_TRUECOLOR) {
+ fprintf(stderr, "GDISP Framebuffer: The display is not in TRUECOLOR mode\n");
+ exit(-1);
+ }
+ if (fb_var.bits_per_pixel != LLDCOLOR_BITS) {
+ fprintf(stderr, "GDISP Framebuffer: The display is not %u bits per pixel\n", LLDCOLOR_BITS);
+ exit(-1);
+ }
+ if (fb_var.red.length != LLDCOLOR_BITS_R || fb_var.green.length != LLDCOLOR_BITS_G || fb_var.blue.length != LLDCOLOR_BITS_B) {
+ fprintf(stderr, "GDISP Framebuffer: The display pixel format is not %d%d%d\n", LLDCOLOR_BITS_R, LLDCOLOR_BITS_G, LLDCOLOR_BITS_B);
+ exit(-1);
+ }
+ if (fb_var.red.offset != LLDCOLOR_SHIFT_R || fb_var.green.offset != LLDCOLOR_SHIFT_G || fb_var.blue.offset != LLDCOLOR_SHIFT_B) {
+ #if LLDCOLOR_SHIFT_B == 0
+ fprintf(stderr, "GDISP Framebuffer: THe display pixel format is not RGB\n");
+ #else
+ fprintf(stderr, "GDISP Framebuffer: The display pixel format is not BGR\n");
+ #endif
+ exit(-1);
+ }
+
+ // Ensure we are at the origin of the virtual display area
+ if (fb_var.xoffset || fb_var.yoffset) {
+ fb_var.xoffset = 0;
+ fb_var.yoffset = 0;
+ ioctl(fb, FBIOPAN_DISPLAY, &fb_var);
+ }
+
+ // Switch to graphics mode (if required)
+ #ifdef VTDEV_PATH
+ board_switch2graphicsmode();
+ #endif
+
+ // Calculate the frame buffer length
+ fblen = fb_var.yres * fb_fix.line_length;
+
+ // Different systems need mapping in slightly different ways - Yuck!
+ #ifdef ARCH_LINUX_SPARC
+ #define CG3_MMAP_OFFSET 0x4000000
+ #define CG6_RAM 0x70016000
+ #define TCX_RAM8BIT 0x00000000
+ #define TCX_RAM24BIT 0x01000000
+ switch (fb_fix.accel) {
+ case FB_ACCEL_SUN_CGTHREE:
+ fbi->pixels = mmap(0, fblen, PROT_READ|PROT_WRITE, MAP_SHARED, fb, CG3_MMAP_OFFSET);
+ break;
+ case FB_ACCEL_SUN_CGSIX:
+ fbi->pixels = mmap(0, fblen, PROT_READ|PROT_WRITE, MAP_SHARED, fb, CG6_RAM);
+ break;
+ case FB_ACCEL_SUN_TCX:
+ fbi->pixels = mmap(0, fblen, PROT_READ|PROT_WRITE, MAP_SHARED, fb, TCX_RAM24BIT);
+ break;
+ default:
+ fprintf(stderr, "GDISP Framebuffer: Don't know how to mmap with accel %d\n", fb_fix.accel);
+ exit(-1);
+ }
+ #elif defined(BLACKFIN)
+ fbi->pixels = mmap(0, fblen, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FILE, fb, 0);
+ #elif defined(__uClinux__)
+ fbi->pixels = mmap(0, fblen, PROT_READ|PROT_WRITE, 0, fb, 0);
+ #else
+ fbi->pixels = mmap(0, fblen, PROT_READ|PROT_WRITE, MAP_SHARED, fb, 0);
+ #endif
+ if(!fbi->pixels || fbi->pixels == (void *)-1) {
+ fprintf(stderr, "GDISP Framebuffer: mmap of display buffer failed\n");
+ exit(-1);
+ }
+
+ // If this program gets children they should not inherit this file descriptor
+ fcntl(fb, F_SETFD, FD_CLOEXEC);
+
+ // We are finished with the file descriptor
+ close(fb);
+
+ // Set the rest of the details of the frame buffer
+ g->g.Width = fb_var.xres;
+ g->g.Height = fb_var.yres;
+ g->g.Backlight = 100;
+ g->g.Contrast = 50;
+ fbi->linelen = fb_fix.line_length;
+ }
+
+ #if GDISP_HARDWARE_FLUSH
+ static void board_flush(GDisplay *g) {
+ (void) g;
+ }
+ #endif
+
+ #if GDISP_NEED_CONTROL
+ static void board_backlight(GDisplay *g, uint8_t percent) {
+ (void) g;
+ (void) percent;
+ }
+
+ static void board_contrast(GDisplay *g, uint8_t percent) {
+ (void) g;
+ (void) percent;
+ }
+
+ static void board_power(GDisplay *g, powermode_t pwr) {
+ (void) g;
+ (void) pwr;
+ }
+ #endif
+
+#endif /* GDISP_LLD_BOARD_IMPLEMENTATION */