4 * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
23 #include <sys/types.h>
33 #include <hal/device/hal-display.h>
35 #include "ambient-mode.h"
37 #include "shared/devices.h"
38 #include "shared/common.h"
39 #include "shared/device-notifier.h"
41 #include "device-interface.h"
44 #include "display/display-dpms.h"
45 #include "display/display.h"
46 #include "display/display-lock.h"
47 #include "battery-monitor.h"
48 #include "battery/power-supply.h"
49 #include "power/power-suspend.h"
50 #include "shared/plugin.h"
55 #define LCD_PHASED_MIN_BRIGHTNESS 1
56 #define LCD_PHASED_MAX_BRIGHTNESS 100
57 #define LCD_PHASED_CHANGE_STEP 5
58 #define LCD_PHASED_DELAY 10000 /* microsecond */
59 #define DUMP_MODE_WAITING_TIME 600000 /* milisecond */
61 #define DISPLAY_HAL_LIB_PATH "/usr/lib/libdisplay-hal.so"
63 #define GESTURE_STR "gesture"
64 #define POWERKEY_STR "powerkey"
65 #define EVENT_STR "event"
66 #define TOUCH_STR "touch"
67 #define BEZEL_STR "bezel"
68 #define TIMEOUT_STR "timeout"
69 #define PROXIMITY_STR "proximity"
70 #define PALM_STR "palm"
71 #define UNKNOWN_STR "unknown"
73 #define FREEZER_VITAL_WAKEUP_CGROUP "/sys/fs/cgroup/freezer/vital_wakeup/freezer.state"
76 static struct _backlight_ops backlight_ops;
77 static struct battery_plugin *battery_plgn;
78 static bool custom_status;
79 static int custom_brightness;
80 static int force_brightness;
81 static int default_brightness;
82 static int dpms_running_state = DPMS_SETTING_DONE;
83 static bool display_dev_available = false;
84 static guint release_timer;
85 static int aod_max_level = -1;
86 static int aod_normal_level = -1;
87 static int aod_min_level = -1;
88 static int aod_charging_level = -1;
89 static const struct display_config *display_conf;
90 static struct battery_status *battery = NULL;
91 static struct battery_status* (*fp_get_var_battery_status)(void);
93 inline struct _backlight_ops *get_var_backlight_ops(void)
95 return &backlight_ops;
98 bool display_dev_ready(void)
100 return display_dev_available;
103 void dpms_set_running_state(int val)
105 dpms_running_state = val;
108 static int bl_onoff(int on, enum device_flags flags)
114 pm_history_save(PM_LOG_LCD_ON_COMPLETE, get_pm_cur_state());
115 else if (on == DPMS_OFF || on == DPMS_FORCE_OFF)
116 pm_history_save(PM_LOG_LCD_OFF_COMPLETE, get_pm_cur_state());
118 pm_history_save(PM_LOG_LCD_CONTROL_FAIL, on);
124 static int bl_brt(int brightness, int delay)
131 /* Update device brightness */
132 ret = backlight_ops.set_brightness(brightness);
134 _I("Set brightness(%d): %d", brightness, ret);
139 static int get_lcd_power_node(void)
142 enum display_state val;
144 ret = hal_device_display_get_state(&val);
148 if (val == DISPLAY_ON && ambient_get_state())
151 if (dpms_running_state != DPMS_SETTING_DONE)
152 return dpms_running_state;
157 case DISPLAY_STANDBY:
159 case DISPLAY_SUSPEND:
170 bool display_dimstay_check(void)
172 if (get_pm_status_flag() & DIM_FLAG)
178 static void change_brightness(int start, int end, int step)
184 if (display_dimstay_check())
187 ret = backlight_ops.get_brightness(&prev);
189 _E("Failed to get brightness: %d", ret);
196 if (get_pm_status_flag() & DIM_MASK)
199 _I("start %d end %d step %d", start, end, step);
201 if (display_dev_available) {
202 ret = hal_device_display_set_multi_brightness(end, step, LCD_PHASED_DELAY);
203 if (ret != -ENODEV) {
205 _E("Failed to set_multi_brightness (%d)", ret);
207 backlight_ops.set_brightness(end);
215 if (abs(diff) < step)
216 val = (diff > 0 ? 1 : -1);
218 val = (int)ceil((double)diff / step);
220 while (start != end) {
224 if ((val > 0 && start > end) ||
225 (val < 0 && start < end))
228 bl_brt(start, LCD_PHASED_DELAY);
232 static int backlight_on(enum device_flags flags)
237 _I("[DPMS XLIB Backlight] LCD on %#x cnt:%d", flags, cnt);
240 ret = bl_onoff(DPMS_ON, flags);
242 pm_history_save(PM_LOG_LCD_ON, get_pm_cur_state());
248 static int backlight_off(enum device_flags flags)
251 static int cnt, ambient_cnt;
253 if (flags & AMBIENT_MODE) {
254 _I("[DPMS XLIB Backlight] LCD suspend %#x cnt:%d", flags, ambient_cnt);
260 _I("[DPMS XLIB Backlight] LCD off %#x cnt:%d", flags, cnt);
263 if (flags & LCD_PHASED_TRANSIT_MODE)
264 backlight_ops.transit_brt(default_brightness,
265 LCD_PHASED_MIN_BRIGHTNESS, LCD_PHASED_CHANGE_STEP);
267 if (flags & FORCE_OFF_MODE)
268 ret = bl_onoff(DPMS_FORCE_OFF, flags);
270 ret = bl_onoff(DPMS_OFF, flags);
273 pm_history_save(PM_LOG_LCD_OFF, get_pm_cur_state());
279 static int backlight_dim(void)
283 ret = backlight_ops.set_brightness(PM_DIM_BRIGHTNESS);
286 pm_history_save(PM_LOG_LCD_DIM, get_pm_cur_state());
288 pm_history_save(PM_LOG_LCD_DIM_FAIL, get_pm_cur_state());
293 static int set_custom_status(bool on)
299 static bool get_custom_status(void)
301 return custom_status;
304 static int save_custom_brightness(void)
308 ret = backlight_ops.get_brightness(&brightness);
310 custom_brightness = brightness;
315 static int custom_backlight_update(void)
319 if (custom_brightness < PM_MIN_BRIGHTNESS ||
320 custom_brightness > PM_MAX_BRIGHTNESS)
323 if (display_dimstay_check())
324 ret = backlight_dim();
326 _I("custom brightness restored! %d", custom_brightness);
327 ret = backlight_ops.set_brightness(custom_brightness);
333 static int set_force_brightness(int level)
335 if (level < 0 || level > PM_MAX_BRIGHTNESS)
338 force_brightness = level;
343 static int backlight_update(void)
348 if (get_custom_status()) {
349 _I("custom brightness mode! brt no updated");
352 if (display_dimstay_check())
353 ret = backlight_dim();
355 brt = backlight_ops.get_default_brt();
356 ret = backlight_ops.set_brightness(brt);
361 static int backlight_standby(int force)
365 if ((dpms_get_cached_state() == DPMS_ON) || force) {
367 ret = bl_onoff(DPMS_STANDBY, 0);
373 static int set_default_brt(int level)
375 if (level < PM_MIN_BRIGHTNESS || level > PM_MAX_BRIGHTNESS)
376 level = display_conf->pm_default_brightness;
378 default_brightness = level;
383 static int get_default_brt(void)
385 return default_brightness;
388 static int get_max_brightness(void)
396 if (!display_dev_available) {
397 _E("There is no HAL for display.");
401 ret = hal_device_display_get_max_brightness(&max);
403 if (ret == -ENODEV) {
404 _E("Get max brightness is not supported.");
405 max = DEFAULT_DISPLAY_MAX_BRIGHTNESS;
408 _E("Failed to get max brightness: %d", ret);
416 static int set_brightness(int val)
420 if (!display_dev_available) {
421 _E("There is no display device.");
425 max = get_max_brightness();
427 _E("Failed to get max brightness.");
431 if (force_brightness > 0 && val != PM_DIM_BRIGHTNESS) {
432 _I("brightness(%d), force brightness(%d)",
433 val, force_brightness);
434 val = force_brightness;
437 if (get_pm_status_flag() & DIM_MASK)
440 /* Maximum Brightness to users is 100.
441 * Thus real brightness need to be calculated */
442 val = val * max / 100;
444 update_bds_brightness_record(val);
445 _I("set brightness %d (default:%d)", val, default_brightness);
446 device_notify(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
448 return hal_device_display_set_brightness(val);
451 static int get_brt_normalized(int brt_raw)
453 int quotient, remainder;
456 max = get_max_brightness();
458 _E("Failed to get max brightness.");
462 /* Maximum Brightness to users is 100.
463 * Thus the brightness value need to be calculated using real brightness.
464 * ex) Let's suppose that the maximum brightness of driver is 255.
465 * case 1) When the user sets the brightness to 41,
467 * 41 * 255 / 100 = 104.55 = 104 (rounded off)
468 * case 2) When the user gets the brightness,
469 * the driver returns the brightness 104.
470 * Thus the brightness to users is
471 * 104 * 100 / 255 = 40.7843.... = 41 (rounded up)
473 quotient = brt_raw * 100 / max;
474 remainder = brt_raw * 100 % max;
481 static int get_brightness(int *val)
485 if (!display_dev_available) {
486 _E("There is no display device.");
490 ret = hal_device_display_get_brightness(&brt);
493 _E("Get brightness is not supported.");
495 _E("Failed to get brightness: %d", ret);
500 *val = get_brt_normalized(brt);
504 static int get_brightness_by_light_sensor(float lmax, float lmin, float light, int *brt)
509 if (!display_dev_available)
512 ret = hal_device_display_get_auto_brightness(lmax, lmin, light, &brt_raw);
515 _E("Get auto brightness is not supported.");
517 _E("Failed to get brightness by light sensor: %d", ret);
522 *brt = get_brt_normalized(brt_raw);
526 static int get_image_effect(enum display_image_effect *effect)
529 enum display_image_effect val;
531 if (!display_dev_available) {
532 _E("There is no display device.");
536 ret = hal_device_display_get_image_effect(&val);
539 _E("Get image effect is not supported.");
541 _E("Failed to get image effect: %d", ret);
551 static int set_image_effect(enum display_image_effect effect)
555 if (!display_dev_available) {
556 _E("There is no display device.");
560 ret = hal_device_display_set_image_effect(effect);
563 _E("Set image effect is not supported.");
565 _E("Failed to set image effect: %d", ret);
573 static int get_panel_mode(enum display_panel_mode *mode)
576 enum display_panel_mode val;
578 if (!display_dev_available) {
579 _E("There is no display device.");
583 ret = hal_device_display_get_panel_mode(&val);
586 _E("Get panel mode is not supported.");
588 _E("Failed to get panel mode(%d)", ret);
598 static int set_panel_mode(enum display_panel_mode mode)
602 if (!display_dev_available) {
603 _E("There is no display device.");
607 ret = hal_device_display_set_panel_mode(mode);
610 _E("Set panel mode is not supported.");
612 _E("Failed to set panel mode(%d)", ret);
620 static int get_frame_rate(int *rate)
625 if (!display_dev_available)
628 return hal_device_display_get_frame_rate(rate);
631 static int set_frame_rate(int rate)
634 static int fmin = -1, fmax = -1;
636 if (!display_dev_available)
640 ret = hal_device_display_get_min_frame_rate(&fmin);
642 _E("Failed to get min frate rate: %d", ret);
646 if ((ret != -ENODEV) && (rate < fmin)) {
647 _E("Invalid rate(%d). (Valid rate: %d <= rate)", rate, fmin);
652 ret = hal_device_display_get_max_frame_rate(&fmax);
654 _E("Failed to get max frate rate: %d", ret);
658 if ((ret != -ENODEV) && (rate > fmax)) {
659 _E("Invalid rate(%d). (Valid rate: rate <= %d)", rate, fmax);
663 return hal_device_display_set_frame_rate(rate);
666 /* It was operated only AOD enter & leave */
667 static int backlight_transit_state(int state)
671 static int aod_brightness_level;
673 backlight_ops.get_brightness(&brt);
675 if (state == DPMS_OFF) {
679 * The value of backlight_ops.get_brightness is system brightness.
680 * But when device is LBM, the value is not same with real brightness.
681 * So it should be read exactly value for transit smooth effect
683 get_brightness(&val);
687 * Compare current brightness with threshold based on charger's charging state.
688 * Charger charging state has 2 threshold: CHARGING, MIN
689 * The other states has 3 threshold: MAX, NORMAL, MIN
691 * Select the highest threshold among the thresholds less then the current brightness.
692 * If current brightness is less then MIN threshold, do not transit brightness.
695 * threshold for | threshold for
696 * charger CHARGING | the other charger states
706 * MIN(10)-----|-----MIN(10)
707 * if DISCHARGING and current brightness is 30, then AOD brightness will be 10.
708 * if DISCHARGING and current brightness is 45, then AOD brightness will be 40.
709 * if CHARGING and current brightness is 80, then AOD brightness will be 20.
710 * if current brightness is 5, do not transit brightness.
712 if (aod_min_level > 0 && val < aod_min_level) {
713 _W("Current brightness is already lower than minimum threshold.");
717 if (battery && battery->charge_now == CHARGER_CHARGING) {
718 if (aod_charging_level > 0 && val >= aod_charging_level)
719 aod_brightness_level = aod_charging_level;
720 else if (aod_min_level > 0 && val >= aod_min_level)
721 aod_brightness_level = aod_min_level;
723 aod_brightness_level = display_conf->aod_enter_level;
725 if (aod_max_level > 0 && val >= aod_max_level)
726 aod_brightness_level = aod_max_level;
727 else if (aod_normal_level > 0 && val >= aod_normal_level)
728 aod_brightness_level = aod_normal_level;
729 else if (aod_min_level > 0 && val >= aod_min_level)
730 aod_brightness_level = aod_min_level;
732 aod_brightness_level = display_conf->aod_enter_level;
735 if (val > aod_brightness_level) {
736 _D("backlight transit start %d end %d DPMS OFF", start, aod_brightness_level);
737 backlight_ops.transit_brt(start, aod_brightness_level, display_conf->brightness_change_step);
740 /* prevent transit effect when another effect is already executed */
741 if (brt != aod_brightness_level) {
742 _W("effect is already executed brt(%d) aod_level(%d)",
743 brt, aod_brightness_level);
747 start = aod_brightness_level;
748 end = default_brightness;
749 _D("backlight transit start %d end %d DPMS ON", start, end);
750 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
756 static gboolean blink_cb(gpointer data)
760 set_brightness(flag ? PM_MAX_BRIGHTNESS : PM_MIN_BRIGHTNESS);
764 return G_SOURCE_CONTINUE;
767 static void blink(int timeout)
772 g_source_remove(timer);
777 _E("timeout value is invalid %d", timeout);
786 timer = g_timeout_add(timeout, blink_cb, NULL);
789 static gboolean release_blink_cb(gpointer data)
794 return G_SOURCE_REMOVE;
797 static void release_blink(void)
800 g_source_remove(release_timer);
804 release_timer = g_timeout_add(DUMP_MODE_WAITING_TIME, release_blink_cb, NULL);
807 static void restore_brightness_func(void)
809 backlight_ops.set_brightness = set_brightness;
810 backlight_ops.get_brightness = get_brightness;
811 backlight_ops.transit_brt = change_brightness;
814 static struct _backlight_ops backlight_ops = {
815 .off = backlight_off,
816 .dim = backlight_dim,
818 .update = backlight_update,
819 .standby = backlight_standby,
820 .set_default_brt = set_default_brt,
821 .get_default_brt = get_default_brt,
822 .get_lcd_power = dpms_get_cached_state,
823 .get_lcd_power_node = get_lcd_power_node,
824 .set_custom_status = set_custom_status,
825 .get_custom_status = get_custom_status,
826 .save_custom_brightness = save_custom_brightness,
827 .custom_update = custom_backlight_update,
828 .set_force_brightness = set_force_brightness,
829 .set_brightness = set_brightness,
830 .get_brightness = get_brightness,
831 .restore_brightness_func = restore_brightness_func,
832 .get_brightness_by_light_sensor = get_brightness_by_light_sensor,
833 .get_image_effect = get_image_effect,
834 .set_image_effect = set_image_effect,
835 .get_panel_mode = get_panel_mode,
836 .set_panel_mode = set_panel_mode,
837 .get_frame_rate = get_frame_rate,
838 .set_frame_rate = set_frame_rate,
839 .transit_state = backlight_transit_state,
840 .transit_brt = change_brightness,
842 .release_blink = release_blink,
843 /* auto-test only function */
844 .get_brightness_raw = get_brightness, /* always fetch brightness from node even LBM mode */
847 int display_service_load(void)
851 if (display_dev_available)
854 r = hal_device_display_get_backend();
856 _E("There is no HAL for display.");
857 display_dev_available = false;
858 display_set_hal_backend_available(display_dev_available);
862 display_dev_available = true;
863 display_set_hal_backend_available(display_dev_available);
864 _D("Display device structure load success.");
868 int display_service_free(void)
870 display_dev_available = false;
871 return hal_device_display_put_backend();
874 int is_lcdon_blocked(void)
876 int state = backlight_ops.get_lcd_power();
878 if ((state == DPMS_DETACH) || (state == -EINVAL))
879 return LCDON_BLOCK_WHEN_DISPLAY_DETACHED;
881 return LCDON_BLOCK_NONE;
884 int init_sysfs(unsigned int flags)
886 register_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
888 if (battery_plgn->handle) {
889 fp_get_var_battery_status = dlsym(battery_plgn->handle, "get_var_battery_status");
890 if (fp_get_var_battery_status) {
891 battery = fp_get_var_battery_status();
893 _E("Failed to get battery status.");
895 _E("Failed to obtain address of get_var_battery_status, %s.", dlerror());
897 _I("There is no battery module.");
904 const struct device_ops *ops = NULL;
910 ops = find_device("touchscreen");
911 if (!check_default(ops))
912 ops->start(NORMAL_MODE);
914 unregister_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
919 static void __CONSTRUCTOR__ initialize(void)
921 display_conf = get_var_display_config();
923 _E("Failed to get display configuration variable.");
925 battery_plgn = get_var_battery_plugin();
927 _E("Failed to get battery plugin variable.");