From f40f2dc0ee7357bc2a605bd19369b98e9c1ca791 Mon Sep 17 00:00:00 2001 From: Simo Piiroinen Date: Wed, 14 May 2014 14:06:27 +0300 Subject: [PATCH] Use ambient light sensor to tune display brightness in lpm_on state 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 --- inifiles/als-defaults.ini | 5 ++ mce-sensorfw.c | 8 +++ mce.c | 3 ++ mce.h | 4 ++ modules/display.c | 89 ++++++++++++++++++++++++++++++--- modules/filter-brightness-als.c | 41 ++++++++++++++- 6 files changed, 142 insertions(+), 8 deletions(-) diff --git a/inifiles/als-defaults.ini b/inifiles/als-defaults.ini index 29d7249c..db3ae938 100644 --- a/inifiles/als-defaults.ini +++ b/inifiles/als-defaults.ini @@ -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 diff --git a/mce-sensorfw.c b/mce-sensorfw.c index 6295b300..8eae66e1 100644 --- a/mce-sensorfw.c +++ b/mce-sensorfw.c @@ -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 diff --git a/mce.c b/mce.c index b2abd4a3..57984c80 100644 --- a/mce.c +++ b/mce.c @@ -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, @@ -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); diff --git a/mce.h b/mce.h index 6957e583..c129e809 100644 --- a/mce.h +++ b/mce.h @@ -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 */ diff --git a/modules/display.c b/modules/display.c index 37848028..608d82bd 100644 --- a/modules/display.c +++ b/modules/display.c @@ -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); @@ -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 @@ -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; @@ -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); @@ -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, @@ -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; @@ -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: @@ -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: @@ -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 { @@ -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 { @@ -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 diff --git a/modules/filter-brightness-als.c b/modules/filter-brightness-als.c index 6e1ac38c..272699b8 100644 --- a/modules/filter-brightness-als.c +++ b/modules/filter-brightness-als.c @@ -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); @@ -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); } @@ -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; @@ -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(); @@ -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 * @@ -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(); @@ -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, @@ -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);