Linux framebuffer on OK6410

Framebuffer programming:

There are very few information on how to use the framebuffer on the user side rather than frambuffer
developers.

I put this together and it is not complete by any means. It is what I managed to find and experiment with.

Devices:

You will need to compile the kernel with framebuffer support. Most kernels are configured by default to support
frame buffers.

For the OK6410 it comes with excellent support for Frame Buffers. Open your .config or OK6410_CFG found
in the Linux directory (unpack the kernel that comes with the board), and here is the section:

#
# Console display driver support
#
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y

CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
# CONFIG_LOGO is not set
CONFIG_FB_S3C_EXT=y
CONFIG_FB_S3C_EXT_TFT480272=y

CONFIG_FB_S3C_EXT_BPP=y

CONFIG_FB_S3C_EXT_BPP_16=y
# CONFIG_FB_S3C_EXT_BPP_24 is not set
# CONFIG_FB_S3C_EXT_BPP_28 is not set
# CONFIG_FB_S3C_EXT_BPP_32 is not set
CONFIG_FB_S3C_EXT_NUM=4
CONFIG_FB_S3C_EXT_VIRTUAL_SCREEN=y
CONFIG_FB_S3C_EXT_DOUBLE_BUFFERING=y

This will support 4 frame buffers with 16BPP.

Once the kernel is compiled you will see them in /dev, like so:

root@OK6410 /]# ls /dev/fb*
/dev/fb0 /dev/fb1 /dev/fb2 /dev/fb3

Accessing the framebuffer:

You access the framebuffer by opening the device as a file (standard UNIX) and getting an file descriptor to it (fd):

#include

// open framebuffer device and read out info
int fd = open(“/dev/fb0”, O_RDWR);

(don’t forget to check for errors).

Next to start issuing IOCTL commands to the buffer. Possible cmds are:

/*
* ioctl values
*
* FBIOGET_VSCREENINFO get variable information of the framerbuffer
* FBIOPUT_VSCREENINFO put variable informaton of the framebuffer
* FBIOGET_FSCREENINFO get fixed information of the framebuffer
* FBIOGETCMAP get colour palette (I think for 8BPP or less)
* FBIOPUTCMAP put own colour palette
* FBIOPAN_DISPLAY move physical display within the virtual
* FBIOGET_CON2FBMAP save contents of console
* FBIOPUT_CON2FBMAP restore contents of console
* FBIOBLANK delete contents of console
* FBIOGET_VBLANK get current raster beam position
* FBIO_ALLOC allocate graphics memory for own purposes for dual buffering etc.
* FBIO_FREEF free graphics memory assigned above
*
* */

Next we need to determine the screen dimensions, bits per pixel, and the color layout, RGB (565, or 555 etc).
You get these as follows:

struct fb_var_screeninfo varscreeninfo;
struct fb_fix_screeninfo fixscreeninfo;
ioctl (fd, FBIOGET_VSCREENINFO, &varscreeninfo);
ioctl (fd, FBIOGET_FSCREENINFO, &fixscreeninfo);

Those will return all the iformation you will need. Check the structures layout in fb.h.

Next you will need to access the frambuffer memory, and it is best to mmap the address or let it
handle it for you:

unsigned char *fbScreen;
fbScreen = (unsigned char*) mmap(0, fixscreeninfo.smem_len ,PROT_READ|PROT_WRITE, MAP_SHARED, fd,0);

Next you will need to know how many bits per pixel there is :

check

varscreeninfo->bits_per_pixel (mine = 16)

the bitfield structure is like this:

// bitfields
// struct fb_bitfield {
// __u32 offset; /* beginning of bitfield */
// __u32 length; /* length of bitfield */
// __u32 msb_right; /* != 0 : Most significant bit is */
// /* right */
// };

printf (“\toffset %d\n”, screeninfo->red.offset); red.length); green.offset); green.length); blue.offset);
printf (“\tlength %d\n”, screeninfo->blue.length);

(mine is 5 bits for red, 6 for green and 5 gor blue. So it is RGB 565).

Now setting a pixel is really simple. Yo can now access the framebuffer as an array of positions:

fbScreen[x + y * fixscreeninfo.line_length] = color;

depending on how you setup the physical and virtual screen you might need to adjust the pixel
location to cater for offsets as follows:

pixel = (x+varscreeninfo.xoffset) * (varscreeninfo.bits_per_pixel/8) +
(y+varscreeninfo.yoffset) * fixscreeninfoinfo.line_length;

If you get color as RGB (separate red, green and blue components) then you will need to pack
the colors into an unsigned short and use that to set the pixel. For example:

it will in this format A RRRRR GGGGGG BBBBB
A = alpha channel (maybe used by graphics hardware maybe not, check the value in the strcutures above)
R = 5 bits of red
G = 6 bits of green
A = 5 bits of blue

unsigned short pixel = (red << 11) | (green <> 11;
unsigned char green = (pixel & green_mask) >> 5;
unsigned char blue = (pixel & blue_mask);

If the framebuffer is 8BPP then yo don’t need to do anything and just use the value directly. However, it is possible to set the
OK6410 to 24 bits (1 byte for each color) so the calculations above will not apply. Use the info in the returned structures above.

When finished working with framebuffer, you will need to do :

close(fd);

// unmap framebuffer out of memory
munmap(fbScreen, fixscreeninfo.smem_len);

Once you have your setpixel(x,y,color) routine working, you can start writing other drawing primitives.

Or if you are feeling adventurous, cross compile DirectFB http://www.directfb.org, a powerful graphics layer with acceleration. I might do that and post results here.

Another project would be to download libjpeg library and cross compile as follows:

./configure –target=arm-linux –host=arm-linux CROSS_COMPILE=arm-linux- –prefix=

then

make all
make install

(I am using the compiler that came with the board (arm-linux-gcc-4.3.2).

with this library you can pack/unpack jpeg images (and you can even scale them down for the OK6410
screen size) and display them.

Same goes for libpng .
You will need zlib first.

Cross compile and then cross compile libpng.

Posted on December 3, 2011, in Embedded Linux. Bookmark the permalink. 5 Comments.

  1. I don’t think OK6410 can be set to RGB24 mode..
    I email the service and he say that OK6410 hardware doesn’t support RGB24 for the screen either the cmos camera..

    And I have a question, hope you know about this.
    I am using Linux 2.6.28.
    I read the user manual in chapter 7-3, it says that the file /etc/init.d/rcS can be changed.
    But it return to its original when reboot.
    Do you know how to solve this?

    • georges samara

      Hi,

      I do remember setting it to 24bits. I had to reserve twice the memory I think
      and my trivial graphics library worked. That was a long time ago I will double
      Check.

      If you are running linux from the board then it will not work.
      Remember in this case it is running from read only memory.
      To change files you will need to boot it over NSF where the file
      System is mounted as read/write. Change the file then repackage the file
      such as cramfs and boot again.

      Hope this helps and sorry for any mistakes as I am writing this on
      My phone at work :-).

      • I have tried to edit the code for camera example to work on RGB24 mode but I still get the data from the camera is in RGB565 mode, the screen too.

        Thank you for the answer, I am trying on it.

      • georges samara

        Hi Heri,

        In my Previous post I said NSF which I meant NFS.

        1. configure the kernel to mount filesystem over NFS
        2 Mount Linux filesystem over NFS,
        3. do the editing,
        4. repackage the file system
        4. burn the filesystem to flash
        5. reconfigure the kernel for the new file system
        6. boot.

        Now I dug out the documentation for the screen. As far as I can make out the brand from the source code it matches what I have. Here are the spec:

        WXCAT43-TG3#001 is a transmissive type a-Si TFT-LCD (amorphous silicon thin film
        transistor liquid crystal display) module, which is composed of a TFT-LCD panel, a
        driver circuit, a backlight unit, and a 4-wires analog resistive type touch panel. The
        panel size is 4.3 inch and the resolution is 480×272. The panel can display up to
        16.7M colors and is suitable for portable device display application.
        1.1 Features
        High image quality a-Si TFT LCD module.
        16:9 wide display
        16,777,216 color number.
        24bit RGB Interface
        High contrast, high brightness.
        Light weight, slim design.
        Low power consumption.
        Line inversion mode with stripe type.
        4-wires analog resistive type touch panel.

        So I am not sure qhat is going on here. I am positive that I reconfigured it for 24bit and it worked. However, they might have removed some code in the new kernel (they keep changing stuff). I have too busy at work at the moment until summer. I’ll see if I can have a go at it.

        Cheers

      • yah.. they say that the screen itself support the 24bit but not the development board(adapter).
        I’d lke to know that, just take your time.

        Thank you

Leave a comment