LCD and backlight power management

The backlight is control by ioctl() calls on /dev/disp. All calls take the form

typedef struct {
        int reg;
        int val;
        int par1;
        int par2;
        } lcd_disp_t;


int op = /* operation code */
lcd_disp_t  t = { /* parameters*/ };
int f = open (DEV_DISP, O_RDONLY);
ioctl (f, op, &t);

The following operation codes are useful

// Set brightness
#define  DISP_SET_BCKL_LEV              _IOWR ( 'D', 9, lcd_disp_t*)
// Enable display hardware
#define  DISP_ENABLE_DISP               _IOWR ( 'D', 10, lcd_disp_t*)
// Enable backlight
#define  DISP_ENABLE_BCKL               _IOWR ( 'D', 11, lcd_disp_t*)

Each of these takes a single value in the par1 member of struct lcd_disp_t. Parameter values are as follows:

DISP_ENABLE_DISP: 1 (on) or 0 (off)

DISP_ENABLE_BCKL: 1 (on) or 0 (off)

DISP_SET_BCKL_LEVEl: 0 (off) to probably 500.

There is some uncertainty about what values are appropriate for display brightness. Minimum brightness is 1, and maximum is probably 500, although there does not appear to be a uniform spread of useful values between these extremes. There isn't a huge range of brightness anyway. AVOS only provides 3 levels and, although there probably are more, it isn't obvious that there are _usefully_ more.

The display power itself is controlled by ioctl() calls on the framebuffer device /dev/fb. I am unsure of the exact purpose of all of these. However, the following piece of code, derived from a sample provided by Archos, should shut the display and backlight down completely.

#define  FBIO_OUTPUT_ENABLE             _IOW ( 'F', 0x25, u_int32_t)
#define  VESA_NOBLANKING                0
#define  VESA_POWERDOWN                 3
#define  FBIOBLANK                      0x4611
#define  FB_BLANK_POWERDOWN             VESA_POWERDOWN + 1 
#define  FB_BLANK_NORMAL                VESA_NOBLANKING + 1 
#define  FB_BLANK_UNBLANK               VESA_NOBLANKING + 0 

void turnOffDisplay()
  {
  int osd_fd = open (DEV_FB, O_RDONLY);
  if (osd_fd <= 0)
    {
    // Handle error
   return;
    }
  int disp_fd = open (DEV_DISP, O_RDONLY);
  if (disp_fd <= 0)
    {
    close (osd_fd);
    // Handle error
    return;
    }
  int fls = 0;
  lcd_disp_t lcdOff = { .par1 = 0 };
  ioctl (disp_fd, DISP_ENABLE_BCKL, &lcdOff);
  ioctl (osd_fd, FBIO_GFX_LAYER_ENABLE, &fls);
  ioctl (osd_fd, FBIOBLANK, FB_BLANK_POWERDOWN);
  ioctl (osd_fd, FBIO_OUTPUT_ENABLE, &fls);
  ioctl (disp_fd, DISP_ENABLE_DISP, &lcdOff);
  }

And to switch it back on again:

void turnOnDisplay()
  {
  int osd_fd = open (DEV_FB, O_RDONLY);
  if (osd_fd <= 0)
    {
    // Handle error
    return;
    }
  int disp_fd = open (DEV_DISP, O_RDONLY);
  if (disp_fd <= 0)
    {
    // Handle error
    close (osd_fd);
    return;
    }
  int t = 1;
  lcd_disp_t lcdOn = { .par1 = 1 };
  ioctl (disp_fd, DISP_ENABLE_DISP, &lcdOn);
  ioctl (osd_fd, FBIO_OUTPUT_ENABLE, &t);
  ioctl (osd_fd, FBIOBLANK, FB_BLANK_UNBLANK);
  ioctl (osd_fd, FBIO_GFX_LAYER_ENABLE, &t);
  ioctl (disp_fd, DISP_ENABLE_BCKL, &lcdOn);
  close (osd_fd);
  close (disp_fd);
  }

Note that the backlight level and backlight on/off status are independent. This is very important because, so far as I know, there is no way to _read_ the backlight level from the Archos driver. So applications that switch the backlight for power saving can do so, to some extent, without changing the user's preferred brightness.