Gamma correction on i.MX6

Document created by rogeriopimentel on Nov 1, 2013
Version 1Show Document

Gamma correction

Displays usually presents a nonlinear bright response. For example, a frame buffer value of 100 will almost never give half the brightness of a value of 200. Historically, this is due to the physics of CRT monitors, but newer display technologies emulate the behavior. This is not only for compatibility, but for solid reasons based in the science of human visual perception.

A first-order approximation to the non-linearity of a CRT is:

L = ν ^ γ

where L is the radiance (light intensity) from the display, ν is the voltage applied to the CRT gun (normally proportional to the digital value in the frame buffer), and γ (Greek letter “gamma”) is a constant particular to the monitor; it's the unknown parameter that makes it all work. It usually ranges from about 2.0 to about 2.5. One useful fact is that the gamma curve is linear in log-log space (i.e. logL as a function of logν), and γ is just the slope of that line.

Example of gamma correction

The dotted line indicates a linear transfer function (γ=1), the framebuffer gamma; the solid line shows how a typical CRT behaves; the dashed line represents the inverse function, the corrected gamma.

How to correct gamma on i.MX using DP (Display Processor)?

Gamma correction can be performed by IC (Image Converter) or DP (Display Processor) sub-blocks inside IPU. Current Linux kernel (3.10) provided by Freescale has an IOCTL that changes the related gamma parameters registers DP_GAMMA_C_SYNC<i> and DP_GAMMA_S_SYNC<i> on Display Processor block.

The steps below shows how to change the gamma using user space applications:

1 - Declare a variable as mxcfb_gamma:

struct mxcfb_gamma fb_gamma;

2 - Enable the gama correction:

fb_gamma.enable = 1;

3 - Set the constk and slopek values, where i = 0 to 15 and x and y are respectively the new constk and slopek constant values:

fb_gamma.constk[i] = x;

fb_gamma.slopek[i] = y;

4 - Open the framebuffer device and call MXCFB_SET_GAMMA:

fd_fb = open("/dev/fb0", O_RDWR, 0)

ioctl(fd_fb, MXCFB_SET_GAMMA, &fb_gamma)

Running the code above will immediately change the gamma value.