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 "power/power-boot.h"
48 #include "power/power-suspend.h"
53 #define LCD_PHASED_MIN_BRIGHTNESS 1
54 #define LCD_PHASED_MAX_BRIGHTNESS 100
55 #define LCD_PHASED_CHANGE_STEP 5
56 #define LCD_PHASED_DELAY 10000 /* microsecond */
57 #define DUMP_MODE_WAITING_TIME 600000 /* milisecond */
59 #define MAX_WHITE_BALANCE_GAIN 2047
60 #define MAX_WHITE_BALANCE_OFFSET 2047
61 #define DEFAULT_WHITE_BALANCE_GAIN 1024
62 #define DEFAULT_WHITE_BALANCE_OFFSET 0
64 #define DISPLAY_HAL_LIB_PATH "/usr/lib/libdisplay-hal.so"
66 #define GESTURE_STR "gesture"
67 #define POWERKEY_STR "powerkey"
68 #define EVENT_STR "event"
69 #define TOUCH_STR "touch"
70 #define TIMEOUT_STR "timeout"
71 #define PROXIMITY_STR "proximity"
72 #define PALM_STR "palm"
73 #define UNKNOWN_STR "unknown"
75 static struct _backlight_ops backlight_ops;
76 static struct _display_white_balance_ops display_white_balance_ops;
77 static bool custom_status;
78 static int custom_brightness;
79 static int force_brightness;
80 static int default_brightness;
81 static int dpms_running_state = DPMS_SETTING_DONE;
82 static bool display_dev_available = false;
83 static guint release_timer;
84 static struct display_config *display_conf;
86 inline struct _backlight_ops *get_var_backlight_ops(void)
88 return &backlight_ops;
91 inline struct _display_white_balance_ops *get_var_display_white_balance_ops(void)
93 return &display_white_balance_ops;
96 bool display_dev_ready(void)
98 return display_dev_available;
101 void dpms_set_running_state(int val)
103 dpms_running_state = val;
106 static int bl_onoff(int on, enum device_flags flags)
112 pm_history_save(PM_LOG_LCD_ON_COMPLETE, get_pm_cur_state());
113 else if (on == DPMS_OFF || on == DPMS_FORCE_OFF)
114 pm_history_save(PM_LOG_LCD_OFF_COMPLETE, get_pm_cur_state());
116 pm_history_save(PM_LOG_LCD_CONTROL_FAIL, on);
122 static int bl_brt(int brightness, int delay)
129 /* Update device brightness */
130 ret = backlight_ops.set_brightness(brightness);
132 _I("Set brightness(%d): %d", brightness, ret);
137 static int get_lcd_power_node(void)
140 enum display_state val;
142 ret = hal_device_display_get_state(&val);
146 if (val == DISPLAY_ON && ambient_get_state())
149 if (dpms_running_state != DPMS_SETTING_DONE)
150 return dpms_running_state;
155 case DISPLAY_STANDBY:
157 case DISPLAY_SUSPEND:
166 bool display_dimstay_check(void)
168 if (get_pm_status_flag() & DIM_FLAG)
171 if ((get_pm_status_flag() & PWRSV_FLAG) && !(get_pm_status_flag() & BRTCH_FLAG))
177 static void change_brightness(int start, int end, int step)
183 if (display_dimstay_check())
186 ret = backlight_ops.get_brightness(&prev);
188 _E("Failed to get brightness: %d", ret);
195 if (get_pm_status_flag() & DIM_MASK)
198 _I("start %d end %d step %d", start, end, step);
200 if (display_dev_available) {
201 ret = hal_device_display_set_multi_brightness(end, step, LCD_PHASED_DELAY);
202 if (ret != -ENODEV) {
204 _E("Failed to set_multi_brightness (%d)", ret);
206 backlight_ops.set_brightness(end);
214 if (abs(diff) < step)
215 val = (diff > 0 ? 1 : -1);
217 val = (int)ceil((double)diff / step);
219 while (start != end) {
223 if ((val > 0 && start > end) ||
224 (val < 0 && start < end))
227 bl_brt(start, LCD_PHASED_DELAY);
231 static int backlight_on(enum device_flags flags)
236 _I("[DPMS XLIB Backlight] LCD on %#x cnt:%d", flags, cnt);
239 ret = bl_onoff(DPMS_ON, flags);
241 pm_history_save(PM_LOG_LCD_ON, get_pm_cur_state());
247 static int backlight_off(enum device_flags flags)
250 static int cnt, ambient_cnt;
252 if (flags & AMBIENT_MODE) {
253 _I("[DPMS XLIB Backlight] LCD suspend %#x cnt:%d", flags, ambient_cnt);
259 _I("[DPMS XLIB Backlight] LCD off %#x cnt:%d", flags, cnt);
262 if (flags & LCD_PHASED_TRANSIT_MODE)
263 backlight_ops.transit_brt(default_brightness,
264 LCD_PHASED_MIN_BRIGHTNESS, LCD_PHASED_CHANGE_STEP);
266 if (flags & FORCE_OFF_MODE)
267 ret = bl_onoff(DPMS_FORCE_OFF, flags);
269 ret = bl_onoff(DPMS_OFF, flags);
272 pm_history_save(PM_LOG_LCD_OFF, get_pm_cur_state());
278 static int backlight_dim(void)
282 ret = backlight_ops.set_brightness(PM_DIM_BRIGHTNESS);
285 pm_history_save(PM_LOG_LCD_DIM, get_pm_cur_state());
287 pm_history_save(PM_LOG_LCD_DIM_FAIL, get_pm_cur_state());
292 static int set_custom_status(bool on)
298 static bool get_custom_status(void)
300 return custom_status;
303 static int save_custom_brightness(void)
307 ret = backlight_ops.get_brightness(&brightness);
309 custom_brightness = brightness;
314 static int custom_backlight_update(void)
318 if (custom_brightness < PM_MIN_BRIGHTNESS ||
319 custom_brightness > PM_MAX_BRIGHTNESS)
322 if (display_dimstay_check())
323 ret = backlight_dim();
325 _I("custom brightness restored! %d", custom_brightness);
326 ret = backlight_ops.set_brightness(custom_brightness);
332 static int set_force_brightness(int level)
334 if (level < 0 || level > PM_MAX_BRIGHTNESS)
337 force_brightness = level;
342 static int backlight_update(void)
347 if (get_custom_status()) {
348 _I("custom brightness mode! brt no updated");
351 if (display_dimstay_check())
352 ret = backlight_dim();
354 brt = backlight_ops.get_default_brt();
355 ret = backlight_ops.set_brightness(brt);
360 static int backlight_standby(int force)
364 if ((dpms_get_cached_state() == DPMS_ON) || force) {
366 ret = bl_onoff(DPMS_STANDBY, 0);
372 static int set_default_brt(int level)
374 if (level < PM_MIN_BRIGHTNESS || level > PM_MAX_BRIGHTNESS)
375 level = display_conf->pm_default_brightness;
377 default_brightness = level;
382 static int get_default_brt(void)
384 return default_brightness;
387 static int get_max_brightness(void)
395 if (!display_dev_available) {
396 _E("There is no HAL for display.");
400 ret = hal_device_display_get_max_brightness(&max);
402 if (ret == -ENODEV) {
403 _E("Get max brightness is not supported.");
404 max = DEFAULT_DISPLAY_MAX_BRIGHTNESS;
407 _E("Failed to get max brightness: %d", ret);
415 static int set_brightness(int val)
419 if (!display_dev_available) {
420 _E("There is no display device.");
424 max = get_max_brightness();
426 _E("Failed to get max brightness.");
430 if (force_brightness > 0 && val != PM_DIM_BRIGHTNESS) {
431 _I("brightness(%d), force brightness(%d)",
432 val, force_brightness);
433 val = force_brightness;
436 if (get_pm_status_flag() & DIM_MASK)
439 /* Maximum Brightness to users is 100.
440 * Thus real brightness need to be calculated */
441 val = val * max / 100;
443 _I("set brightness %d (default:%d)", val, default_brightness);
444 device_notify(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
446 return hal_device_display_set_brightness(val);
449 static int get_brt_normalized(int brt_raw)
451 int quotient, remainder;
454 max = get_max_brightness();
456 _E("Failed to get max brightness.");
460 /* Maximum Brightness to users is 100.
461 * Thus the brightness value need to be calculated using real brightness.
462 * ex) Let's suppose that the maximum brightness of driver is 255.
463 * case 1) When the user sets the brightness to 41,
465 * 41 * 255 / 100 = 104.55 = 104 (rounded off)
466 * case 2) When the user gets the brightness,
467 * the driver returns the brightness 104.
468 * Thus the brightness to users is
469 * 104 * 100 / 255 = 40.7843.... = 41 (rounded up)
471 quotient = brt_raw * 100 / max;
472 remainder = brt_raw * 100 % max;
479 static int get_brightness(int *val)
483 if (!display_dev_available) {
484 _E("There is no display device.");
488 ret = hal_device_display_get_brightness(&brt);
491 _E("Get brightness is not supported.");
493 _E("Failed to get brightness: %d", ret);
498 *val = get_brt_normalized(brt);
502 static int get_brightness_by_light_sensor(float lmax, float lmin, float light, int *brt)
507 if (!display_dev_available)
510 ret = hal_device_display_get_auto_brightness(lmax, lmin, light, &brt_raw);
513 _E("Get auto brightness is not supported.");
515 _E("Failed to get brightness by light sensor: %d", ret);
520 *brt = get_brt_normalized(brt_raw);
524 static int get_image_effect(enum display_image_effect *effect)
527 enum display_image_effect val;
529 if (!display_dev_available) {
530 _E("There is no display device.");
534 ret = hal_device_display_get_image_effect(&val);
537 _E("Get image effect is not supported.");
539 _E("Failed to get image effect: %d", ret);
549 static int set_image_effect(enum display_image_effect effect)
553 if (!display_dev_available) {
554 _E("There is no display device.");
558 ret = hal_device_display_set_image_effect(effect);
561 _E("Set image effect is not supported.");
563 _E("Failed to set image effect: %d", ret);
571 static int get_panel_mode(enum display_panel_mode *mode)
574 enum display_panel_mode val;
576 if (!display_dev_available) {
577 _E("There is no display device.");
581 ret = hal_device_display_get_panel_mode(&val);
584 _E("Get panel mode is not supported.");
586 _E("Failed to get panel mode(%d)", ret);
596 static int set_panel_mode(enum display_panel_mode mode)
600 if (!display_dev_available) {
601 _E("There is no display device.");
605 ret = hal_device_display_set_panel_mode(mode);
608 _E("Set panel mode is not supported.");
610 _E("Failed to set panel mode(%d)", ret);
618 static int get_frame_rate(int *rate)
623 if (!display_dev_available)
626 return hal_device_display_get_frame_rate(rate);
629 static int set_frame_rate(int rate)
632 static int fmin = -1, fmax = -1;
634 if (!display_dev_available)
638 ret = hal_device_display_get_min_frame_rate(&fmin);
640 _E("Failed to get min frate rate: %d", ret);
644 if ((ret != -ENODEV) && (rate < fmin)) {
645 _E("Invalid rate(%d). (Valid rate: %d <= rate)", rate, fmin);
650 ret = hal_device_display_get_max_frame_rate(&fmax);
652 _E("Failed to get max frate rate: %d", ret);
656 if ((ret != -ENODEV) && (rate > fmax)) {
657 _E("Invalid rate(%d). (Valid rate: rate <= %d)", rate, fmax);
661 return hal_device_display_set_frame_rate(rate);
664 /* It was operated only AOD enter & leave */
665 static int backlight_transit_state(int state)
670 backlight_ops.get_brightness(&brt);
672 if (state == DPMS_OFF) {
674 end = display_conf->aod_enter_level;
677 * The value of backlight_ops.get_brightness is system brightness.
678 * But when device is LBM, the value is not same with real brightness.
679 * So it should be read exactly value for transit smooth effect
681 get_brightness(&val);
683 if (val > display_conf->aod_enter_level)
684 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
686 /* prevent transit effect when another effect is already executed */
687 if (brt != display_conf->aod_enter_level) {
688 _W("effect is already executed brt(%d) aod_level(%d)",
689 brt, display_conf->aod_enter_level);
693 start = display_conf->aod_enter_level;
694 end = default_brightness;
695 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
701 static gboolean blink_cb(gpointer data)
705 set_brightness(flag ? PM_MAX_BRIGHTNESS : PM_MIN_BRIGHTNESS);
709 return G_SOURCE_CONTINUE;
712 static void blink(int timeout)
717 g_source_remove(timer);
722 _E("timeout value is invalid %d", timeout);
731 timer = g_timeout_add(timeout, blink_cb, NULL);
734 static gboolean release_blink_cb(gpointer data)
739 return G_SOURCE_REMOVE;
742 static void release_blink(void)
745 g_source_remove(release_timer);
749 release_timer = g_timeout_add(DUMP_MODE_WAITING_TIME, release_blink_cb, NULL);
752 static int set_white_balance(enum hal_display_white_balance white_balance_type, int value)
756 if (!display_dev_available) {
757 _E("There is no display device.");
761 switch (white_balance_type) {
762 case HAL_DISPLAY_WHITE_BALANCE_R_GAIN:
763 case HAL_DISPLAY_WHITE_BALANCE_G_GAIN:
764 case HAL_DISPLAY_WHITE_BALANCE_B_GAIN:
765 if (value > MAX_WHITE_BALANCE_GAIN)
766 value = DEFAULT_WHITE_BALANCE_GAIN;
768 case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET:
769 case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET:
770 case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET:
771 if (value > MAX_WHITE_BALANCE_OFFSET)
772 value = DEFAULT_WHITE_BALANCE_OFFSET;
775 _E("Unknown white balance type");
779 ret = hal_device_display_set_white_balance(white_balance_type, value);
782 _E("Set white balance is not supported.");
784 _E("Failed to set white balance value.");
790 static int get_white_balance(enum hal_display_white_balance white_balance_type, int* value)
794 if (!display_dev_available) {
795 _E("There is no display device.");
799 switch (white_balance_type) {
800 case HAL_DISPLAY_WHITE_BALANCE_R_GAIN:
801 case HAL_DISPLAY_WHITE_BALANCE_G_GAIN:
802 case HAL_DISPLAY_WHITE_BALANCE_B_GAIN:
803 case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET:
804 case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET:
805 case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET:
808 _E("Unknown white balance type");
812 ret = hal_device_display_get_white_balance(white_balance_type, value);
815 _E("Get white balance is not supported.");
817 _E("Failed to get white balance value.");
823 static void restore_brightness_func(void)
825 backlight_ops.set_brightness = set_brightness;
826 backlight_ops.get_brightness = get_brightness;
827 backlight_ops.transit_brt = change_brightness;
830 static struct _backlight_ops backlight_ops = {
831 .off = backlight_off,
832 .dim = backlight_dim,
834 .update = backlight_update,
835 .standby = backlight_standby,
836 .set_default_brt = set_default_brt,
837 .get_default_brt = get_default_brt,
838 .get_lcd_power = dpms_get_cached_state,
839 .get_lcd_power_node = get_lcd_power_node,
840 .set_custom_status = set_custom_status,
841 .get_custom_status = get_custom_status,
842 .save_custom_brightness = save_custom_brightness,
843 .custom_update = custom_backlight_update,
844 .set_force_brightness = set_force_brightness,
845 .set_brightness = set_brightness,
846 .get_brightness = get_brightness,
847 .restore_brightness_func = restore_brightness_func,
848 .get_brightness_by_light_sensor = get_brightness_by_light_sensor,
849 .get_image_effect = get_image_effect,
850 .set_image_effect = set_image_effect,
851 .get_panel_mode = get_panel_mode,
852 .set_panel_mode = set_panel_mode,
853 .get_frame_rate = get_frame_rate,
854 .set_frame_rate = set_frame_rate,
855 .transit_state = backlight_transit_state,
856 .transit_brt = change_brightness,
858 .release_blink = release_blink,
861 static struct _display_white_balance_ops display_white_balance_ops = {
862 .set_white_balance = set_white_balance,
863 .get_white_balance = get_white_balance,
866 int display_service_load(void)
870 if (display_dev_available)
873 r = hal_device_display_get_backend();
875 _E("There is no HAL for display.");
876 display_dev_available = false;
880 display_dev_available = true;
881 _D("Display device structure load success.");
885 int display_service_free(void)
887 display_dev_available = false;
888 return hal_device_display_put_backend();
891 static int delayed_init_done(void *data)
893 static int done = false;
903 int is_lcdon_blocked(void)
905 /* block lcdon until booting done in silent boot mode */
906 if (silent_boot && !delayed_init_done(NULL))
907 return LCDON_BLOCK_DURING_SILENT_BOOT;
909 return LCDON_BLOCK_NONE;
912 int init_sysfs(unsigned int flags)
914 register_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
915 register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
922 const struct device_ops *ops = NULL;
928 ops = find_device("touchscreen");
929 if (!check_default(ops))
930 ops->start(NORMAL_MODE);
932 ops = find_device("touchkey");
933 if (!check_default(ops))
934 ops->start(NORMAL_MODE);
936 unregister_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
941 static void __CONSTRUCTOR__ initialize(void)
943 display_conf = get_var_display_config();
945 _E("Failed to get display configuration variable.");