rockbox/firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c
Daniel Stenberg 2acc0ac542 Updated our source code header to explicitly mention that we are GPL v2 or
later. We still need to hunt down snippets used that are not. 1324 modified
files...
http://www.rockbox.org/mail/archive/rockbox-dev-archive-2008-06/0060.shtml


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17847 a1c6a512-1295-4272-9138-f99709370657
2008-06-28 18:10:04 +00:00

427 lines
13 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 by Linus Nielsen Feltzing
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "cpu.h"
#include "system.h"
#include "backlight-target.h"
#include "backlight.h"
#include "lcd.h"
#include "sc606-meg-fx.h"
#include "power.h"
#define BUTTONLIGHT_MENU (SC606_LED_B1)
#define BUTTONLIGHT_ALL (SC606_LED_B1 | SC606_LED_B2 | SC606_LED_C1 | SC606_LED_C2)
static const int log_brightness[12] = {0,1,2,3,5,7,10,15,22,31,44,63};
#ifndef BOOTLOADER
static void led_control_service(void);
static enum sc606_states
{
SC606_CONTROL_IDLE,
SC606_CONTROL_A12,
SC606_CONTROL_B12,
SC606_CONTROL_C12,
SC606_CONTROL_CONF
} sc606_control;
#endif /* BOOTLOADER */
static enum backlight_states
{
BACKLIGHT_CONTROL_IDLE,
BACKLIGHT_CONTROL_OFF,
BACKLIGHT_CONTROL_ON,
BACKLIGHT_CONTROL_SET,
BACKLIGHT_CONTROL_FADE
} backlight_control;
enum buttonlight_states
{
BUTTONLIGHT_CONTROL_IDLE,
BUTTONLIGHT_CONTROL_OFF,
BUTTONLIGHT_CONTROL_ON,
BUTTONLIGHT_CONTROL_SET,
BUTTONLIGHT_CONTROL_FADE,
} buttonlight_control;
static unsigned char backlight_brightness;
static unsigned char buttonlight_brightness;
static unsigned char backlight_target;
static unsigned char buttonlight_target;
static unsigned short buttonlight_trigger_now;
/* Assumes that the backlight has been initialized */
void _backlight_set_brightness(int brightness)
{
/* clamp the brightness value */
brightness = MAX(1, MIN(12, brightness));
/* stop the interrupt from messing us up */
backlight_control = BACKLIGHT_CONTROL_IDLE;
backlight_brightness = log_brightness[brightness - 1];
backlight_control = BACKLIGHT_CONTROL_SET;
}
/* only works if the buttonlight mode is set to triggered mode */
void __buttonlight_trigger(void)
{
buttonlight_trigger_now = 1;
}
/* map the mode from the command into the state machine entries */
void __buttonlight_mode(enum buttonlight_mode mode)
{
/* choose stop to setup mode */
buttonlight_control = BUTTONLIGHT_CONTROL_IDLE;
/* which mode to use */
switch (mode)
{
case BUTTONLIGHT_OFF:
buttonlight_control = BUTTONLIGHT_CONTROL_OFF;
break;
case BUTTONLIGHT_ON:
buttonlight_control = BUTTONLIGHT_CONTROL_ON;
break;
case BUTTONLIGHT_FOLLOW:
buttonlight_control = BUTTONLIGHT_CONTROL_FADE;
break;
default:
return; /* unknown mode */
}
}
/* led_control_service runs in interrupt context - be brief!
* This service is called once per interrupt timer tick - 100 times a second.
*
* There should be at most only one i2c operation per call - if more are need
* the calls should be spread across calls.
*
* Putting all led servicing in one thread means that we wont step on any
* i2c operations - they are all serialized here in the ISR tick. It also
* insures that we get called at equal timing for good visual effect.
*/
#ifndef BOOTLOADER
static void led_control_service(void)
{
static unsigned char
sc606regAval=DEFAULT_BRIGHTNESS_SETTING,
sc606regBval=0,
sc606regCval=0,
sc606regCONFval=0x03;
static bool sc606_changed=false, sc606_CONF_changed=false;
if(sc606_changed==false)
{
switch (backlight_control)
{
case BACKLIGHT_CONTROL_IDLE:
backlight_control = BACKLIGHT_CONTROL_IDLE;
break;
case BACKLIGHT_CONTROL_OFF:
sc606_changed=true;
sc606_CONF_changed=true;
sc606regCONFval &= ~0x03;
sc606regAval=0;
backlight_control = BACKLIGHT_CONTROL_IDLE;
break;
case BACKLIGHT_CONTROL_ON:
sc606_changed=true;
sc606_CONF_changed=true;
sc606regCONFval |= 0x03;
sc606regAval=backlight_brightness;
backlight_control = BACKLIGHT_CONTROL_IDLE;
break;
case BACKLIGHT_CONTROL_SET:
if(!(sc606regCONFval&0x03))
break;
sc606_changed=true;
sc606regAval=backlight_brightness;
backlight_control = BACKLIGHT_CONTROL_IDLE;
break;
case BACKLIGHT_CONTROL_FADE:
/* Was this mode set while the backlight is already on/off? */
if(backlight_target==sc606regAval)
{
backlight_control = BACKLIGHT_CONTROL_IDLE;
break;
}
sc606_changed=true;
if(!(sc606regCONFval&0x03))
{
sc606_CONF_changed=true;
sc606regCONFval |= 0x03;
}
if(backlight_target>sc606regAval)
{
sc606regAval++;
if(backlight_target==sc606regAval)
backlight_control = BACKLIGHT_CONTROL_IDLE;
}
else
{
sc606regAval--;
if(sc606regAval==0)
backlight_control = BACKLIGHT_CONTROL_OFF;
else if (backlight_target==sc606regAval)
backlight_control = BACKLIGHT_CONTROL_IDLE;
}
break;
default:
backlight_control = BACKLIGHT_CONTROL_IDLE;
break;
}
switch (buttonlight_control)
{
case BUTTONLIGHT_CONTROL_IDLE:
buttonlight_control=BUTTONLIGHT_CONTROL_IDLE;
break;
case BUTTONLIGHT_CONTROL_OFF:
sc606_changed=true;
sc606_CONF_changed=true;
sc606regCONFval &= ~BUTTONLIGHT_ALL;
sc606regBval=sc606regCval=0;
buttonlight_control=BUTTONLIGHT_CONTROL_IDLE;
break;
case BUTTONLIGHT_CONTROL_ON:
sc606_changed=true;
sc606_CONF_changed=true;
sc606regCONFval |= BUTTONLIGHT_ALL;
sc606regBval=sc606regCval=buttonlight_brightness;
buttonlight_control=BUTTONLIGHT_CONTROL_IDLE;
break;
case BUTTONLIGHT_CONTROL_SET:
if(!(sc606regCONFval&BUTTONLIGHT_ALL))
break;
sc606_changed=true;
sc606regBval=sc606regCval=buttonlight_brightness;
buttonlight_control = BUTTONLIGHT_CONTROL_IDLE;
break;
case BUTTONLIGHT_CONTROL_FADE:
/* Was this mode set while the button light is already on? */
if(buttonlight_target==sc606regBval)
{
buttonlight_control = BUTTONLIGHT_CONTROL_IDLE;
break;
}
sc606_changed=true;
if(!(sc606regCONFval&BUTTONLIGHT_ALL))
{
sc606_CONF_changed=true;
sc606regCONFval |= BUTTONLIGHT_ALL;
}
if(buttonlight_target>sc606regBval)
{
sc606regCval=++sc606regBval;
if(buttonlight_target==sc606regBval)
buttonlight_control = BUTTONLIGHT_CONTROL_IDLE;
}
else
{
sc606regCval=--sc606regBval;
if(sc606regBval==0)
buttonlight_control = BUTTONLIGHT_CONTROL_OFF;
else if (buttonlight_target==sc606regBval)
backlight_control = BACKLIGHT_CONTROL_IDLE;
}
break;
default:
buttonlight_control = BUTTONLIGHT_CONTROL_IDLE;
break;
}
}
switch (sc606_control)
{
case SC606_CONTROL_IDLE:
if(sc606_changed)
sc606_control=SC606_CONTROL_A12;
else
sc606_control=SC606_CONTROL_IDLE;
break;
case SC606_CONTROL_A12:
sc606_write(SC606_REG_A , sc606regAval);
sc606_control=SC606_CONTROL_B12;
break;
case SC606_CONTROL_B12:
sc606_write(SC606_REG_B , sc606regBval);
sc606_control=SC606_CONTROL_C12;
break;
case SC606_CONTROL_C12:
sc606_write(SC606_REG_C , sc606regCval);
if(sc606_CONF_changed!=true)
{
sc606_changed=false;
if(backlight_control != BACKLIGHT_CONTROL_IDLE ||
buttonlight_control != BUTTONLIGHT_CONTROL_IDLE)
{
sc606_control=SC606_CONTROL_A12;
}
else
{
sc606_control=SC606_CONTROL_IDLE;
}
}
else
{
sc606_control=SC606_CONTROL_CONF;
}
break;
case SC606_CONTROL_CONF:
sc606_write(SC606_REG_CONF , sc606regCONFval);
sc606_changed=false;
sc606_CONF_changed=false;
if(backlight_control != BACKLIGHT_CONTROL_IDLE ||
buttonlight_control != BUTTONLIGHT_CONTROL_IDLE)
{
sc606_control=SC606_CONTROL_A12;
}
else
{
sc606_control=SC606_CONTROL_IDLE;
}
break;
default:
sc606_control=SC606_CONTROL_IDLE;
break;
}
}
#endif /* BOOTLOADER */
static void __backlight_dim(bool dim_now)
{
/* dont let the interrupt tick happen */
backlight_control = BACKLIGHT_CONTROL_IDLE;
backlight_target = (dim_now == true) ? 0 : backlight_brightness;
if(backlight_target==0 && backlight_brightness==0)
{
if(dim_now == false)
backlight_control = BACKLIGHT_CONTROL_ON;
else
backlight_control = BACKLIGHT_CONTROL_OFF;
}
else
backlight_control = BACKLIGHT_CONTROL_FADE;
}
void _backlight_on(void)
{
#ifdef HAVE_LCD_SLEEP
backlight_lcd_sleep_countdown(false); /* stop counter */
#endif
#ifdef HAVE_LCD_ENABLE
lcd_enable(true); /* power on lcd + visible display */
#endif
__backlight_dim(false);
}
void _backlight_off(void)
{
__backlight_dim(true);
#ifdef HAVE_LCD_SLEEP
/* Disable lcd after fade completes (when lcd_sleep timeout expires) */
backlight_lcd_sleep_countdown(true); /* start countdown */
#endif
}
static inline void __buttonlight_on(void)
{
buttonlight_control = BUTTONLIGHT_CONTROL_ON;
}
static inline void __buttonlight_off(void)
{
buttonlight_control = BUTTONLIGHT_CONTROL_OFF;
}
static void __buttonlight_dim(bool dim_now)
{
buttonlight_control = BUTTONLIGHT_CONTROL_IDLE;
buttonlight_target = (dim_now == true) ? 0 : buttonlight_brightness;
if(buttonlight_target==0 && buttonlight_brightness==0)
{
if(dim_now == false)
buttonlight_control = BUTTONLIGHT_CONTROL_ON;
else
buttonlight_control = BUTTONLIGHT_CONTROL_OFF;
}
else
buttonlight_control = BUTTONLIGHT_CONTROL_FADE;
}
void _buttonlight_on(void)
{
__buttonlight_dim(false);
}
void _buttonlight_off(void)
{
#ifndef BOOTLOADER
if(_buttonlight_timeout>0)
__buttonlight_dim(true);
else
#endif
__buttonlight_off();
}
void _buttonlight_set_brightness(int brightness)
{
/* clamp the brightness value */
brightness = MAX(1, MIN(12, brightness));
/* stop the interrupt from messing us up */
buttonlight_control = BUTTONLIGHT_CONTROL_IDLE;
buttonlight_brightness = log_brightness[brightness - 1];
buttonlight_control = BUTTONLIGHT_CONTROL_SET;
}
bool _backlight_init(void)
{
buttonlight_brightness = DEFAULT_BRIGHTNESS_SETTING;
backlight_brightness = DEFAULT_BRIGHTNESS_SETTING;
buttonlight_control = BUTTONLIGHT_CONTROL_IDLE;
backlight_control = BACKLIGHT_CONTROL_ON;
/* Set the backlight up in a known state */
sc606_init();
sc606_write(SC606_REG_A , DEFAULT_BRIGHTNESS_SETTING);
sc606_write(SC606_REG_B , 0);
sc606_write(SC606_REG_C , 0);
sc606_write(SC606_REG_CONF , 0x03);
#ifndef BOOTLOADER
/* put the led control on the tick list */
tick_add_task(led_control_service);
#endif
return true;
}