Skip to content

Commit

Permalink
Use ambient light sensor to tune display brightness in lpm_on state
Browse files Browse the repository at this point in the history
Add ALS profile configuration for use with lpm_on state. Should stay
relatively dim indoors, saturates to 100% brightness at the same level
as lowest display brightness profile.

Setup a datapipe for communicating lpm brightness changes between display
and brightness filtering plugins.

Set standby override flag for ambient light sensor so that it can be
powered on in lpm_on state too.

[mce] Use ambient light sensor to tune display brightness in lpm_on state. Fixes JB#18791
  • Loading branch information
spiiroin committed May 14, 2014
1 parent 0617156 commit f40f2dc
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 8 deletions.
5 changes: 5 additions & 0 deletions inifiles/als-defaults.ini
Expand Up @@ -81,3 +81,8 @@ LevelsProfile0=30;33;36;39;42;45;48;51;54;57;64;68;72;76;80;84;88;92;96;100
LimitsProfile0=1;2;3;6;11;20;36;66;121;220;489;599;732;896;1095;1340;1639;2005;2453;3000
LevelsProfile0=30;33;36;39;42;45;48;51;54;57;64;68;72;76;80;84;88;92;96;100


[BrightnessLPM]

LimitsProfile0=1;4;27;99;700;778;864;960;1066;1184;1315;1460;1622;1801;2000
LevelsProfile0=1;2;3;4;5;15;24;34;43;53;62;72;81;91;100
8 changes: 8 additions & 0 deletions mce-sensorfw.c
Expand Up @@ -940,6 +940,14 @@ static void mce_sensorfw_als_start_sensor(void)
if( !mce_sensorfw_start_sensor(als_name, als_iface, als_sid) )
goto EXIT;

/* ALS is used in lpm display states; from sensord point of view
* this means display is off and thus we need to set the standby
* override flag */

/* No error checking here; failures will be logged when
* we get reply message from sensord */
mce_sensorfw_set_standby_override(als_name, als_iface, als_sid, true);

als_have = true;

/* There is no quarantee that we get sensor input
Expand Down
3 changes: 3 additions & 0 deletions mce.c
Expand Up @@ -1082,6 +1082,8 @@ int main(int argc, char **argv)
0, GINT_TO_POINTER(3));
setup_datapipe(&led_brightness_pipe, READ_WRITE, DONT_FREE_CACHE,
0, GINT_TO_POINTER(0));
setup_datapipe(&lpm_brightness_pipe, READ_WRITE, DONT_FREE_CACHE,
0, GINT_TO_POINTER(0));
setup_datapipe(&led_pattern_activate_pipe, READ_ONLY, FREE_CACHE,
0, NULL);
setup_datapipe(&led_pattern_deactivate_pipe, READ_ONLY, FREE_CACHE,
Expand Down Expand Up @@ -1266,6 +1268,7 @@ int main(int argc, char **argv)
free_datapipe(&led_pattern_deactivate_pipe);
free_datapipe(&led_pattern_activate_pipe);
free_datapipe(&led_brightness_pipe);
free_datapipe(&lpm_brightness_pipe);
free_datapipe(&display_brightness_pipe);
free_datapipe(&display_state_pipe);
free_datapipe(&display_state_req_pipe);
Expand Down
4 changes: 4 additions & 0 deletions mce.h
Expand Up @@ -273,6 +273,10 @@ typedef enum {

/** LED brightness */
datapipe_struct led_brightness_pipe;

/** LPM brightness */
datapipe_struct lpm_brightness_pipe;

/** State of device; read only */
datapipe_struct device_inactive_pipe;
/** LED pattern to activate; read only */
Expand Down
89 changes: 82 additions & 7 deletions modules/display.c
Expand Up @@ -252,6 +252,7 @@ static void mdy_datapipe_submode_cb(gconstpointer data);
static gpointer mdy_datapipe_display_state_filter_cb(gpointer data);
static void mdy_datapipe_display_state_cb(gconstpointer data);
static void mdy_datapipe_display_brightness_cb(gconstpointer data);
static void mdy_datapipe_lpm_brightness_cb(gconstpointer data);
static void mdy_datapipe_display_state_req_cb(gconstpointer data);
static void mdy_datapipe_audio_route_cb(gconstpointer data);
static void mdy_datapipe_charger_state_cb(gconstpointer data);
Expand Down Expand Up @@ -305,6 +306,8 @@ static void mdy_brightness_stop_fade_timer(void);
static void mdy_brightness_start_fade_timer(gint step_time);
static void mdy_brightness_set_fade_target(gint new_brightness);
static void mdy_brightness_set_on_level(gint hbm_and_level);
static void mdy_brightness_set_dim_level(void);
static void mdy_brightness_set_lpm_level(gint level);

/* ------------------------------------------------------------------------- *
* CONTENT_ADAPTIVE_BACKLIGHT_CONTROL
Expand Down Expand Up @@ -1098,6 +1101,30 @@ static void mdy_datapipe_display_brightness_cb(gconstpointer data)
return;
}

/** Handle lpm_brightness_pipe notifications
*
* @note A brightness request is only sent if the value changed
*
* @param data The display brightness stored in a pointer
*/
static void mdy_datapipe_lpm_brightness_cb(gconstpointer data)
{
static gint curr = -1;

gint prev = curr;
curr = GPOINTER_TO_INT(data);

mce_log(LL_DEBUG, "input: %d -> %d", prev, curr);

if( curr == prev )
goto EXIT;

mdy_brightness_set_lpm_level(curr);

EXIT:
return;
}

/* Cached audio routing state */
static audio_route_t audio_route = AUDIO_ROUTE_HANDSET;

Expand Down Expand Up @@ -1388,6 +1415,8 @@ static void mdy_datapipe_init(void)
mdy_datapipe_display_state_cb);
append_output_trigger_to_datapipe(&display_brightness_pipe,
mdy_datapipe_display_brightness_cb);
append_output_trigger_to_datapipe(&lpm_brightness_pipe,
mdy_datapipe_lpm_brightness_cb);

append_output_trigger_to_datapipe(&charger_state_pipe,
mdy_datapipe_charger_state_cb);
Expand Down Expand Up @@ -1446,6 +1475,8 @@ static void mdy_datapipe_quit(void)
mdy_datapipe_audio_route_cb);
remove_output_trigger_from_datapipe(&display_brightness_pipe,
mdy_datapipe_display_brightness_cb);
remove_output_trigger_from_datapipe(&lpm_brightness_pipe,
mdy_datapipe_lpm_brightness_cb);
remove_output_trigger_from_datapipe(&display_state_pipe,
mdy_datapipe_display_state_cb);
remove_output_trigger_from_datapipe(&display_state_req_pipe,
Expand Down Expand Up @@ -1964,6 +1995,38 @@ static void mdy_brightness_set_dim_level(void)
USE_INDATA);
}

static void mdy_brightness_set_lpm_level(gint level)
{
/* Map from: 1-100% to: 1-hw_max */
int brightness = mce_xlat_int(1, 100,
1, mdy_brightness_level_maximum,
level);

mce_log(LL_DEBUG, "mdy_brightness_level_display_lpm: %d -> %d",
mdy_brightness_level_display_lpm, brightness);

mdy_brightness_level_display_lpm = brightness;

/* Take updated values in use */
switch( display_state ) {
case MCE_DISPLAY_LPM_ON:
mdy_brightness_set_fade_target(mdy_brightness_level_display_lpm);
break;

default:
case MCE_DISPLAY_OFF:
case MCE_DISPLAY_LPM_OFF:
case MCE_DISPLAY_DIM:
case MCE_DISPLAY_ON:
case MCE_DISPLAY_UNDEF:
case MCE_DISPLAY_POWER_DOWN:
case MCE_DISPLAY_POWER_UP:
break;
}

return;
}

static void mdy_brightness_set_on_level(gint hbm_and_level)
{
gint new_brightness = (hbm_and_level >> 0) & 0xff;
Expand Down Expand Up @@ -2002,17 +2065,13 @@ static void mdy_brightness_set_on_level(gint hbm_and_level)
/* Re-evaluate dim brightness too */
mdy_brightness_set_dim_level();

/* Re-evaluate lpm brightness too */
// TODO: ALS config & sensor input processing
/* Note: The lpm brightness is handled separately */

/* Take updated values in use */
switch( display_state ) {
case MCE_DISPLAY_OFF:
case MCE_DISPLAY_LPM_OFF:
break;

case MCE_DISPLAY_LPM_ON:
mdy_brightness_set_fade_target(mdy_brightness_level_display_lpm);
break;

case MCE_DISPLAY_DIM:
Expand Down Expand Up @@ -4338,6 +4397,15 @@ static void mdy_display_state_enter_post(void)
mdy_hbm_rethink();
mdy_orientation_sensor_rethink();

/* Determine the minimum brightness level above which to use
* smooth transitions. Since both lpm and dimmed brightness
* are now dynamic and lpm brightness can be greater than
* dimmed brightness, use: limit = min(dimmed_brightness-1, lpm)
*/
gint consider_off_level = mdy_brightness_level_display_dim - 1;
if( consider_off_level > mdy_brightness_level_display_lpm )
consider_off_level = mdy_brightness_level_display_lpm;

switch( display_state ) {
case MCE_DISPLAY_POWER_DOWN:
case MCE_DISPLAY_OFF:
Expand All @@ -4357,7 +4425,7 @@ static void mdy_display_state_enter_post(void)
break;

case MCE_DISPLAY_DIM:
if( mdy_brightness_level_cached <= mdy_brightness_level_display_lpm ) {
if( mdy_brightness_level_cached <= consider_off_level ) {
/* If we unblank, switch on display immediately */
mdy_brightness_force_level(mdy_brightness_level_display_dim);
} else {
Expand All @@ -4367,7 +4435,7 @@ static void mdy_display_state_enter_post(void)
break;

case MCE_DISPLAY_ON:
if( mdy_brightness_level_cached <= mdy_brightness_level_display_lpm ) {
if( mdy_brightness_level_cached <= consider_off_level ) {
/* If we unblank, switch on display immediately */
mdy_brightness_force_level(mdy_brightness_level_display_on);
} else {
Expand Down Expand Up @@ -6955,6 +7023,13 @@ static void mdy_gconf_sanitize_brightness_settings(void)
mdy_brightness_level_display_on);
mce_log(LL_DEBUG, "mdy_brightness_level_display_dim = %d",
mdy_brightness_level_display_dim);

/* Drive the initial lpm brightness value through datapipe.
* Actual value will change only if sensor is enabled, producing
* input and lpm als config is in place. */
execute_datapipe(&lpm_brightness_pipe,
GINT_TO_POINTER(mdy_brightness_level_display_lpm),
USE_INDATA, CACHE_INDATA);
}

/** Get initial gconf valus and start tracking changes
Expand Down
41 changes: 40 additions & 1 deletion modules/filter-brightness-als.c
Expand Up @@ -147,6 +147,12 @@ static als_filter_t lut_led =
.id = "Led",
};

/** ALS filtering state for low power mode display simulation */
static als_filter_t lut_lpm =
{
.id = "LPM",
};

static gboolean set_color_profile(const gchar *id);
static gboolean save_color_profile(const gchar *id);

Expand Down Expand Up @@ -387,6 +393,8 @@ static void run_datapipes(void)
USE_CACHE, DONT_CACHE_INDATA);
execute_datapipe(&led_brightness_pipe, NULL,
USE_CACHE, DONT_CACHE_INDATA);
execute_datapipe(&lpm_brightness_pipe, NULL,
USE_CACHE, DONT_CACHE_INDATA);
execute_datapipe(&key_backlight_pipe, NULL,
USE_CACHE, DONT_CACHE_INDATA);
}
Expand Down Expand Up @@ -447,8 +455,10 @@ static void rethink_als_status(void)

if( want_data )
mce_sensorfw_als_set_notify(als_lux_changed);
else
else {
mce_sensorfw_als_set_notify(0);
als_lux_changed(-1);
}

if( enable_old == enable_new )
goto EXIT;
Expand All @@ -466,6 +476,7 @@ static void rethink_als_status(void)
als_filter_clear_threshold(&lut_display);
als_filter_clear_threshold(&lut_led);
als_filter_clear_threshold(&lut_key);
als_filter_clear_threshold(&lut_lpm);
}

run_datapipes();
Expand Down Expand Up @@ -567,6 +578,29 @@ static gpointer led_brightness_filter(gpointer data)
return GINT_TO_POINTER(value * scale / 100);
}

/** Ambient Light Sensor filter for LPM brightness
*
* @param data The un-processed brightness setting (1-100) stored in a pointer
* @return The processed brightness value
*/
static gpointer lpm_brightness_filter(gpointer data)
{
int value = GPOINTER_TO_INT(data);

if( lut_lpm.profiles < 1 )
goto EXIT;

if( als_lux_latest < 0 )
goto EXIT;

/* Note: Input value is ignored and output is
* determined only by the als config */
value = als_filter_run(&lut_lpm, 0, als_lux_latest);

EXIT:
return GINT_TO_POINTER(value);
}

/**
* Ambient Light Sensor filter for keyboard backlight brightness
*
Expand Down Expand Up @@ -1056,6 +1090,7 @@ const gchar *g_module_check_init(GModule *module)
als_filter_load_config(&lut_display);
als_filter_load_config(&lut_led);
als_filter_load_config(&lut_key);
als_filter_load_config(&lut_lpm);

/* Get intial display state */
display_state = display_state_get();
Expand All @@ -1065,6 +1100,8 @@ const gchar *g_module_check_init(GModule *module)
display_brightness_filter);
append_filter_to_datapipe(&led_brightness_pipe,
led_brightness_filter);
append_filter_to_datapipe(&lpm_brightness_pipe,
lpm_brightness_filter);
append_filter_to_datapipe(&key_backlight_pipe,
key_backlight_filter);
append_output_trigger_to_datapipe(&display_state_pipe,
Expand Down Expand Up @@ -1139,6 +1176,8 @@ void g_module_unload(GModule *module)
key_backlight_filter);
remove_filter_from_datapipe(&led_brightness_pipe,
led_brightness_filter);
remove_filter_from_datapipe(&lpm_brightness_pipe,
lpm_brightness_filter);
remove_filter_from_datapipe(&display_brightness_pipe,
display_brightness_filter);

Expand Down

0 comments on commit f40f2dc

Please sign in to comment.