Alberto Embedded & Open experience

Notes on my experience on Open Source Embedded Systems

Posts Tagged ‘mx3fb

Framebuffer OK!! explanation

leave a comment »

OOK what was the problem and what I’ve understood:
First of all I built with success the OSELAS.BSP-Phytec-phyCORE-10 following the great guide OSELAS.BSP-Phytec-phyCORE-i.MX31-Quickstart.pdf, remember, I had already built the OSELAS toolchain optimized for arm-1136jfs-linux-gnueabi.

Booting with the new filesystem (after some adjustment to /etc/network/interfaces to have eth0 statically assigned ip and /etc/modules to do not try to load unwanted modules) was fine, but fbset was still not working!
From the logo printed on the screen the problem with mx3fb driver was for sure not only in timings parameters of the video mode but also some other timings settings.

Fortunately the driver mx3fb is derived from the Freescale mxcfb making comparison simpler 🙂
With a deep debugging and comparison between the two drivers: mx3fb and mxcfb (from Atmark version of 2.6.26 kernel) I’ve found this:

in ipu_sdc.c:ipu_sdc_init_panel#ifdef CONFIG_MACH_ARMADILLO5X0
old_conf = (div |
((div >> 4) – 1) << 24 | /* DISP3_IF_CLK_DOWN_WR */
((div >> 4) – 2) << 14); /* DISP3_IF_CLK_UP_WR */
mx3fb_write_reg(mx3fb, old_conf, DI_DISP3_TIME_CONF);
#else
/*
* DISP3_IF_CLK_DOWN_WR is half the divider value and 2 fraction bits
* fewer. Subtract 1 extra from DISP3_IF_CLK_DOWN_WR based on timing
* debug. DISP3_IF_CLK_UP_WR is 0
*/
mx3fb_write_reg(mx3fb, (((div / 8) – 1) << 22) | div, DI_DISP3_TIME_CONF);
#endif

The DI_DISP3_TIME_CONF sdc register contain timing configuration for the pixel writing process (from lower bit):

  • DISP3_IF_CLK_PER_WR: 12 bit (8 bit for integer part and 4 bit for fractional) sets the divider for HSP_CLOCK (ipu_clk) to obtain the right pixel period.
  • DISP3_IF_CLK_UP_WR: 10 bit (6 bit for integer part and 4 bit for fractional) sets the rising edge position for display write access.
  • DISP3_IF_CLK_DOWN_WR: 10 bit (6 bit for integer part and 4 bit for fractional) sets the falling edge position for display write access.

The Atmark armadillo 500 board have a Video DAC (ADV7125) that transforms digital synchronous display signals in analog signals to drive a standard VGA connector for standard display devices. Those different timing configurations was due Video DAC timing specifications and so this piece of code must be ported to mx3fb driver in sdc_init_panel function!

Yes! first timing misconfiguration solved!

But the screen was still over margins, not well proportioned and last but not least there was a shadowed band of a few pixels in width on the entire height of the screen!
All those misconfiguration was solved calibrating the timings mode parameters moving the image on right over the shadowed band. This maintaining the timings constraints of the VGA displays.

How work the VGA standard display:

Horizontal sync signal:
__   ______________________________   ___________
  |_|                              |_|
  |A|
  |---------------B----------------|

Data:
         ______________________           _______
________|        VIDEO         |_________| VIDEO (next line)
    |-C-|----------D-----------|-E-|

A: Horizontal sync pulse.
B: Scanline period made of:
C: Left border (Back porch) waiting for current stability.
D: Valid Video data.
E: Right border (Front porch) cutting off current instability.

Vertical timings definition are similar.
Now for a resolution of 640×480 at 60Hz refresh rate (VGA standard) are defined those frequencies:

Clock frequency 25.175 MHz (Pixel frequency)
Line  frequency 31469 Hz   -> 800 pixel per line.
Field frequency 59.94 Hz   -> 525 lines.

Timing mode parameters must meet those constraints but we can decide amounts of left and upper margins panning the valid image onto a well displayed position!

After many tests, the better result was achieved with this configuration:

{    /* 640x480 @ 60 Hz */
 .name         = "CRT-VGA",
 .refresh      = 60,
 .xres         = 640,
 .yres         = 480,
 .pixclock     = 39721, /*Period in picos*/
 .left_margin  = 35,
 .right_margin = 115,
 .upper_margin = 43,
 .lower_margin = 1,
 .hsync_len    = 10,
 .vsync_len    = 1,
 .sync         = FB_SYNC_OE_ACT_HIGH,
 .vmode        = FB_VMODE_NONINTERLACED,
 .flag         = 0,
},

Same process for the resolution 800×600 with 56Hz of refresh rate results in this video mode:

{    /* 800x600 @ 56 Hz */
 .name         = "CRT-SVGA",
 .refresh      = 56,
 .xres         = 800,
 .yres         = 600,
 .pixclock     = 30000,
 .left_margin  = 30,
 .right_margin = 108,
 .upper_margin = 13,
 .lower_margin = 10,
 .hsync_len    = 10,
 .vsync_len    = 1,
 .sync         = FB_SYNC_OE_ACT_HIGH | FB_SYNC_HOR_HIGH_ACT |
                 FB_SYNC_VERT_HIGH_ACT,
 .vmode        = FB_VMODE_NONINTERLACED,
 .flag         = 0,
 },

Here a well formed information repository on how VGA work.

Next, USB!

Written by Alberto!

14/05/2009 at 3:00 pm