diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/backlight-gigabeat-s.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/backlight-gigabeat-s.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/backlight-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/backlight-gigabeat-s.c new file mode 100644 index 0000000000..ec7bf7e8a9 --- /dev/null +++ b/firmware/target/arm/imx31/gigabeat-s/backlight-gigabeat-s.c @@ -0,0 +1,214 @@ +/*************************************************************************** + * __________ __ ___. + * 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 "system.h" +#include "backlight.h" +#include "mc13783.h" +#include "backlight-target.h" +#include "lcd.h" + +#ifdef HAVE_BACKLIGHT_BRIGHTNESS +/* Table that uses combinations of current level and pwm fraction to get + * as many uniquely-visible brightness levels as possible. The lowest current + * level for any average current is used even though many combinations give + * duplicate values. Current (I) values are in mA. */ +static const struct +{ + unsigned char md; + unsigned char pwm; +} led_md_pwm_table[] = +{ + /* I-level PWM(x/15) I-Avg */ + { 0, 0 }, /* 0 0 0.0 */ + { 1, 1 }, /* 3 1 0.2 */ + { 1, 2 }, /* 3 2 0.4 */ + { 1, 3 }, /* 3 3 0.6 */ + { 1, 4 }, /* 3 4 0.8 */ + { 1, 5 }, /* 3 5 1.0 */ + { 1, 6 }, /* 3 6 1.2 */ + { 1, 7 }, /* 3 7 1.4 */ + { 1, 8 }, /* 3 8 1.6 */ + { 1, 9 }, /* 3 9 1.8 */ + { 1, 10 }, /* 3 10 2.0 */ + { 1, 11 }, /* 3 11 2.2 */ + { 1, 12 }, /* 3 12 2.4 */ /* default */ + { 1, 13 }, /* 3 13 2.6 */ + { 1, 14 }, /* 3 14 2.8 */ + { 1, 15 }, /* 3 15 3.0 */ + { 2, 9 }, /* 6 9 3.6 */ + { 2, 10 }, /* 6 10 4.0 */ + { 2, 11 }, /* 6 11 4.4 */ + { 2, 12 }, /* 6 12 4.8 */ + { 2, 13 }, /* 6 13 5.2 */ + { 2, 14 }, /* 6 14 5.6 */ + { 2, 15 }, /* 6 15 6.0 */ + { 3, 11 }, /* 9 11 6.6 */ + { 3, 12 }, /* 9 12 7.2 */ + /* Anything higher is just too much */ +}; +#endif /* HAVE_BACKLIGHT_BRIGHTNESS */ + +/* Bits always combined with ramping bits */ +#define MC13783_LED_CONTROL0_BITS \ + (MC13783_BOOSTEN | MC13783_ABMODE_MONCH_LEDMD1234 | \ + MC13783_ABREF_400MV) + +static struct mutex backlight_mutex; /* Block brightness change while + * setting up fading */ +static bool backlight_on_status = true; /* Is on or off? */ +static uint32_t backlight_pwm_bits; /* Final PWM setting for fade-in */ + +/* Backlight ramping settings */ +static uint32_t led_ramp_mask = MC13783_LEDMDRAMPDOWN | MC13783_LEDMDRAMPUP; + +bool _backlight_init(void) +{ + mutex_init(&backlight_mutex); + + /* Set default LED register value */ + mc13783_write(MC13783_LED_CONTROL0, + MC13783_LED_CONTROL0_BITS | MC13783_LEDEN); + +#ifdef HAVE_BACKLIGHT_BRIGHTNESS + /* Our PWM and I-Level is different than retailos (but same apparent + * brightness), so init to our default. */ + _backlight_set_brightness(DEFAULT_BRIGHTNESS_SETTING); +#else + /* Use default PWM */ + backlight_pwm_bits = mc13783_read(MC13783_LED_CONTROL2) & MC13783_LEDMDDC; +#endif + + return true; +} + +void backlight_set_fade_out(bool value) +{ + if (value) + led_ramp_mask |= MC13783_LEDMDRAMPDOWN; + else + led_ramp_mask &= ~MC13783_LEDMDRAMPDOWN; +} + +void backlight_set_fade_in(bool value) +{ + if (value) + led_ramp_mask |= MC13783_LEDMDRAMPUP; + else + led_ramp_mask &= ~MC13783_LEDMDRAMPUP; +} + +void _backlight_on(void) +{ + static const char regs[2] = + { + MC13783_LED_CONTROL0, + MC13783_LED_CONTROL2 + }; + + uint32_t data[2]; + + mutex_lock(&backlight_mutex); + +#ifdef HAVE_LCD_ENABLE + lcd_enable(true); +#endif + + /* Set/clear LEDRAMPUP bit, clear LEDRAMPDOWN bit, + * Ensure LED supply is on. */ + data[0] = MC13783_LED_CONTROL0_BITS | MC13783_LEDEN; + + if (!backlight_on_status) + data[0] |= led_ramp_mask & MC13783_LEDMDRAMPUP; + + backlight_on_status = true; + + /* Specify final PWM setting */ + data[1] = mc13783_read(MC13783_LED_CONTROL2); + + if (data[1] != MC13783_DATA_ERROR) + { + data[1] &= ~MC13783_LEDMDDC; + data[1] |= backlight_pwm_bits; + + /* Write regs within 30us of each other (requires single xfer) */ + mc13783_write_regset(regs, data, 2); + } + + mutex_unlock(&backlight_mutex); +} + +void _backlight_off(void) +{ + uint32_t ctrl0 = MC13783_LED_CONTROL0_BITS | MC13783_LEDEN; + + mutex_lock(&backlight_mutex); + + if (backlight_on_status) + ctrl0 |= led_ramp_mask & MC13783_LEDMDRAMPDOWN; + + backlight_on_status = false; + + /* Set/clear LEDRAMPDOWN bit, clear LEDRAMPUP bit */ + mc13783_write(MC13783_LED_CONTROL0, ctrl0); + + /* Wait 100us - 500ms */ + sleep(HZ/100); + + /* Write final PWM setting */ + mc13783_write_masked(MC13783_LED_CONTROL2, + 0 << MC13783_LEDMDDC_POS, + MC13783_LEDMDDC); + + mutex_unlock(&backlight_mutex); +} + +#ifdef HAVE_BACKLIGHT_BRIGHTNESS +/* Assumes that the backlight has been initialized - parameter should + * already be range-checked in public interface. */ +void _backlight_set_brightness(int brightness) +{ + uint32_t md; + + mutex_lock(&backlight_mutex); + + md = led_md_pwm_table[brightness].md; + backlight_pwm_bits = backlight_on_status ? + (led_md_pwm_table[brightness].pwm << MC13783_LEDMDDC_POS) : 0; + + mc13783_write_masked(MC13783_LED_CONTROL2, + (md << MC13783_LEDMD_POS) | backlight_pwm_bits, + MC13783_LEDMD | MC13783_LEDMDDC); + + mutex_unlock(&backlight_mutex); +} +#endif /* HAVE_BACKLIGHT_BRIGHTNESS */ + +#ifdef HAVE_LCD_SLEEP +/* Turn off LED supply */ +void _backlight_lcd_sleep(void) +{ + mutex_lock(&backlight_mutex); + + mc13783_clear(MC13783_LED_CONTROL0, MC13783_LEDEN); + + mutex_unlock(&backlight_mutex); +} +#endif |