Index: firmware/export/config-gigabeat-s.h =================================================================== --- firmware/export/config-gigabeat-s.h (revision 19140) +++ firmware/export/config-gigabeat-s.h (working copy) @@ -82,7 +82,7 @@ #define HAVE_BACKLIGHT_BRIGHTNESS /* Main LCD backlight brightness range and defaults */ -#define MIN_BRIGHTNESS_SETTING 0 +#define MIN_BRIGHTNESS_SETTING 1 #define MAX_BRIGHTNESS_SETTING 24 #define DEFAULT_BRIGHTNESS_SETTING 12 Index: firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c =================================================================== --- firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c (revision 19140) +++ firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c (working copy) @@ -65,50 +65,106 @@ }; #endif /* HAVE_BACKLIGHT_BRIGHTNESS */ +#define MC13783_LED_CONTROL0_BITS \ + (MC13783_LEDEN | MC13783_BOOSTEN | MC13783_ABMODE_MONCH_LEDMD1234 | \ + MC13783_ABREF_400MV) + +static int backlight_brightness; +static bool backlight_on_status = true; +static struct mutex backlight_mutex; + bool _backlight_init(void) { - mc13783_write(MC13783_LED_CONTROL0, - MC13783_LEDEN | - MC13783_LEDMDRAMPUP | - MC13783_LEDMDRAMPDOWN | - MC13783_BOOSTEN | - MC13783_ABMODE_MONCH_LEDMD1234 | - MC13783_ABREF_400MV); + mutex_init(&backlight_mutex); + + /* Set default LED register value */ + mc13783_write(MC13783_LED_CONTROL0, MC13783_LED_CONTROL0_BITS); + + /* Our PWM and I-Level is different than retailos (but same apparent + * brightness), so init to our default. */ + _backlight_set_brightness(DEFAULT_BRIGHTNESS_SETTING); return true; } void _backlight_on(void) { - /* LEDEN=1 */ - mc13783_set(MC13783_LED_CONTROL0, MC13783_LEDEN); + static const char regs[2] = + { + MC13783_LED_CONTROL0, + MC13783_LED_CONTROL2 + }; + + uint32_t data[2]; + + mutex_lock(&backlight_mutex); + + /* Set/clear LEDRAMPUP bit, clear LEDRAMPDOWN bit */ + data[0] = MC13783_LED_CONTROL0_BITS; + + if (!backlight_on_status) + data[0] |= 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] |= MC13783_LEDMDDCw(led_md_pwm_table[backlight_brightness].pwm); + + /* Write regs within 30uS of each other (requires single xfer) */ + mc13783_write_regset(regs, data, 2); + } + + mutex_unlock(&backlight_mutex); } void _backlight_off(void) { - /* LEDEN=0 */ - mc13783_clear(MC13783_LED_CONTROL0, MC13783_LEDEN); + uint32_t ctrl0 = MC13783_LED_CONTROL0_BITS; + + mutex_lock(&backlight_mutex); + + if (backlight_on_status) + ctrl0 |= 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, MC13783_LEDMDDCw(0), + MC13783_LEDMDDC); + + mutex_unlock(&backlight_mutex); } #ifdef HAVE_BACKLIGHT_BRIGHTNESS /* Assumes that the backlight has been initialized */ void _backlight_set_brightness(int brightness) { - uint32_t data, md, pwm; + uint32_t md, pwm; if ((unsigned)brightness >= ARRAYLEN(led_md_pwm_table)) brightness = DEFAULT_BRIGHTNESS_SETTING; - data = mc13783_read(MC13783_LED_CONTROL2); + mutex_lock(&backlight_mutex); - if (data == (uint32_t)-1) - return; + backlight_brightness = brightness; md = led_md_pwm_table[brightness].md; - pwm = led_md_pwm_table[brightness].pwm; + pwm = backlight_on_status ? led_md_pwm_table[brightness].pwm : 0; - data &= ~(MC13783_LEDMD | MC13783_LEDMDDC); - data |= MC13783_LEDMDw(md) | MC13783_LEDMDDCw(pwm); + mc13783_write_masked(MC13783_LED_CONTROL2, + MC13783_LEDMDw(md) | MC13783_LEDMDDCw(pwm), + MC13783_LEDMD | MC13783_LEDMDDC); - mc13783_write(MC13783_LED_CONTROL2, data); + mutex_unlock(&backlight_mutex); } #endif /* HAVE_BACKLIGHT_BRIGHTNESS */