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>
34 #include "ambient-mode.h"
36 #include "core/devices.h"
37 #include "core/common.h"
38 #include "core/device-notifier.h"
40 #include "device-interface.h"
43 #include "device-node.h"
44 #include "display/display-dpms.h"
45 #include "display/display.h"
46 #include "display/display-lock.h"
47 #include "power/boot.h"
48 #include "power/power-control.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 DISPLAY_HAL_LIB_PATH "/usr/lib/libdisplay-hal.so"
61 #define GESTURE_STR "gesture"
62 #define POWERKEY_STR "powerkey"
63 #define EVENT_STR "event"
64 #define TOUCH_STR "touch"
65 #define TIMEOUT_STR "timeout"
66 #define PROXIMITY_STR "proximity"
67 #define PALM_STR "palm"
68 #define UNKNOWN_STR "unknown"
70 static struct _backlight_ops backlight_ops;
71 static bool custom_status;
72 static int custom_brightness;
73 static int force_brightness;
74 static int default_brightness;
75 static int dpms_running_state = DPMS_SETTING_DONE;
76 static struct display_device *display_dev;
77 static guint release_timer;
78 static struct display_config *display_conf;
80 inline struct _backlight_ops *get_var_backlight_ops(void)
82 return &backlight_ops;
85 struct display_device *display_dev_get(void)
90 void dpms_set_running_state(int val)
92 dpms_running_state = val;
95 static int bl_onoff(int on, enum device_flags flags)
101 pm_history_save(PM_LOG_LCD_ON_COMPLETE, get_pm_cur_state());
102 else if (on == DPMS_OFF || on == DPMS_FORCE_OFF)
103 pm_history_save(PM_LOG_LCD_OFF_COMPLETE, get_pm_cur_state());
105 pm_history_save(PM_LOG_LCD_CONTROL_FAIL, on);
111 static int bl_brt(int brightness, int delay)
118 /* Update device brightness */
119 ret = backlight_ops.set_brightness(brightness);
121 _I("Set brightness(%d): %d", brightness, ret);
126 static int get_lcd_power(void)
128 enum display_state val;
131 if (!display_dev || !display_dev->get_state) {
132 return dpms_get_state();
134 ret = display_dev->get_state(&val);
138 if (val == DISPLAY_ON && ambient_get_state())
141 if (dpms_running_state != DPMS_SETTING_DONE)
142 return dpms_running_state;
147 case DISPLAY_STANDBY:
149 case DISPLAY_SUSPEND:
159 bool display_dimstay_check(void)
161 if (get_pm_status_flag() & DIM_FLAG)
164 if ((get_pm_status_flag() & PWRSV_FLAG) && !(get_pm_status_flag() & BRTCH_FLAG))
170 static void change_brightness(int start, int end, int step)
176 if (display_dimstay_check())
179 ret = backlight_ops.get_brightness(&prev);
181 _E("Failed to get brightness: %d", ret);
188 if (get_pm_status_flag() & DIM_MASK)
191 _I("start %d end %d step %d", start, end, step);
193 if (display_dev && display_dev->set_multi_brightness) {
194 ret = display_dev->set_multi_brightness(end, step, LCD_PHASED_DELAY);
196 _E("Failed to set_multi_brightness (%d)", ret);
198 backlight_ops.set_brightness(end);
205 if (abs(diff) < step)
206 val = (diff > 0 ? 1 : -1);
208 val = (int)ceil((double)diff / step);
210 while (start != end) {
214 if ((val > 0 && start > end) ||
215 (val < 0 && start < end))
218 bl_brt(start, LCD_PHASED_DELAY);
222 static int backlight_on(enum device_flags flags)
227 _I("[DPMS XLIB Backlight] LCD on %#x cnt:%d", flags, cnt);
230 ret = bl_onoff(DPMS_ON, flags);
232 pm_history_save(PM_LOG_LCD_ON, get_pm_cur_state());
238 static int backlight_off(enum device_flags flags)
241 static int cnt, ambient_cnt;
243 if (flags & AMBIENT_MODE) {
244 _I("[DPMS XLIB Backlight] LCD suspend %#x cnt:%d", flags, ambient_cnt);
250 _I("[DPMS XLIB Backlight] LCD off %#x cnt:%d", flags, cnt);
253 if (flags & LCD_PHASED_TRANSIT_MODE)
254 backlight_ops.transit_brt(default_brightness,
255 LCD_PHASED_MIN_BRIGHTNESS, LCD_PHASED_CHANGE_STEP);
257 if (flags & FORCE_OFF_MODE)
258 ret = bl_onoff(DPMS_FORCE_OFF, flags);
260 ret = bl_onoff(DPMS_OFF, flags);
263 pm_history_save(PM_LOG_LCD_OFF, get_pm_cur_state());
269 static int backlight_dim(void)
273 ret = backlight_ops.set_brightness(PM_DIM_BRIGHTNESS);
276 pm_history_save(PM_LOG_LCD_DIM, get_pm_cur_state());
278 pm_history_save(PM_LOG_LCD_DIM_FAIL, get_pm_cur_state());
283 static int set_custom_status(bool on)
289 static bool get_custom_status(void)
291 return custom_status;
294 static int save_custom_brightness(void)
298 ret = backlight_ops.get_brightness(&brightness);
300 custom_brightness = brightness;
305 static int custom_backlight_update(void)
309 if (custom_brightness < PM_MIN_BRIGHTNESS ||
310 custom_brightness > PM_MAX_BRIGHTNESS)
313 if (display_dimstay_check())
314 ret = backlight_dim();
316 _I("custom brightness restored! %d", custom_brightness);
317 ret = backlight_ops.set_brightness(custom_brightness);
323 static int set_force_brightness(int level)
325 if (level < 0 || level > PM_MAX_BRIGHTNESS)
328 force_brightness = level;
333 static int backlight_update(void)
338 if (get_custom_status()) {
339 _I("custom brightness mode! brt no updated");
342 if (display_dimstay_check())
343 ret = backlight_dim();
345 brt = backlight_ops.get_default_brt();
346 ret = backlight_ops.set_brightness(brt);
351 static int backlight_standby(int force)
355 if ((get_lcd_power() == DPMS_ON) || force) {
357 ret = bl_onoff(DPMS_STANDBY, 0);
363 static int set_default_brt(int level)
365 if (level < PM_MIN_BRIGHTNESS || level > PM_MAX_BRIGHTNESS)
366 level = display_conf->pm_default_brightness;
368 default_brightness = level;
373 static int get_default_brt(void)
375 return default_brightness;
378 static int get_max_brightness(void)
387 _E("There is no display device.");
391 if (!display_dev->get_max_brightness) {
392 max = DEFAULT_DISPLAY_MAX_BRIGHTNESS;
396 ret = display_dev->get_max_brightness(&max);
398 _E("Failed to get max brightness: %d", ret);
405 static int set_brightness(int val)
409 if (!display_dev || !display_dev->set_brightness) {
410 _E("There is no display device.");
414 max = get_max_brightness();
416 _E("Failed to get max brightness.");
420 if (force_brightness > 0 && val != PM_DIM_BRIGHTNESS) {
421 _I("brightness(%d), force brightness(%d)",
422 val, force_brightness);
423 val = force_brightness;
426 if (get_pm_status_flag() & DIM_MASK)
429 /* Maximum Brightness to users is 100.
430 * Thus real brightness need to be calculated */
431 val = val * max / 100;
433 _I("set brightness %d (default:%d)", val, default_brightness);
434 device_notify(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
436 return display_dev->set_brightness(val);
439 static int get_brt_normalized(int brt_raw)
441 int quotient, remainder;
444 max = get_max_brightness();
446 _E("Failed to get max brightness.");
450 /* Maximum Brightness to users is 100.
451 * Thus the brightness value need to be calculated using real brightness.
452 * ex) Let's suppose that the maximum brightness of driver is 255.
453 * case 1) When the user sets the brightness to 41,
455 * 41 * 255 / 100 = 104.55 = 104 (rounded off)
456 * case 2) When the user gets the brightness,
457 * the driver returns the brightness 104.
458 * Thus the brightness to users is
459 * 104 * 100 / 255 = 40.7843.... = 41 (rounded up)
461 quotient = brt_raw * 100 / max;
462 remainder = brt_raw * 100 % max;
469 static int get_brightness(int *val)
473 if (!display_dev || !display_dev->get_brightness) {
474 _E("There is no display device.");
478 ret = display_dev->get_brightness(&brt);
480 _E("Failed to get brightness: %d", ret);
484 *val = get_brt_normalized(brt);
488 static int get_brightness_by_light_sensor(float lmax, float lmin, float light, int *brt)
493 if (!display_dev || !display_dev->get_auto_brightness)
496 ret = display_dev->get_auto_brightness(lmax, lmin, light, &brt_raw);
498 _E("Failed to get brightness by light sensor: %d", ret);
502 *brt = get_brt_normalized(brt_raw);
506 static int get_image_effect(enum display_image_effect *effect)
509 enum display_image_effect val;
511 if (!display_dev || !display_dev->get_image_effect) {
512 _E("There is no display device.");
516 ret = display_dev->get_image_effect(&val);
518 _E("Failed to get image effect: %d", ret);
527 static int set_image_effect(enum display_image_effect effect)
531 if (!display_dev || !display_dev->set_image_effect) {
532 _E("There is no display device.");
536 ret = display_dev->set_image_effect(effect);
538 _E("Failed to set image effect: %d", ret);
545 static int get_panel_mode(enum display_panel_mode *mode)
548 enum display_panel_mode val;
550 if (!display_dev || !display_dev->get_panel_mode) {
551 _E("there is no display device");
555 ret = display_dev->get_panel_mode(&val);
557 _E("failed to get panel mode(%d)", ret);
566 static int set_panel_mode(enum display_panel_mode mode)
570 if (!display_dev || !display_dev->set_panel_mode) {
571 _E("there is no display device");
575 ret = display_dev->set_panel_mode(mode);
577 _E("failed to set panel mode(%d)", ret);
584 static int get_frame_rate(int *rate)
589 if (!display_dev || !display_dev->get_frame_rate)
592 return display_dev->get_frame_rate(rate);
595 static int set_frame_rate(int rate)
598 static int fmin = -1, fmax = -1;
601 !display_dev->set_frame_rate)
604 if (display_dev->get_min_frame_rate) {
606 ret = display_dev->get_min_frame_rate(&fmin);
608 _E("Failed to get min frate rate: %d", ret);
613 _E("Invalid rate(%d). (Valid rate: %d <= rate)", rate, fmin);
618 if (display_dev->get_max_frame_rate) {
620 ret = display_dev->get_max_frame_rate(&fmax);
622 _E("Failed to get max frate rate: %d", ret);
627 _E("Invalid rate(%d). (Valid rate: rate <= %d)", rate, fmax);
632 return display_dev->set_frame_rate(rate);
635 /* It was operated only AOD enter & leave */
636 static int backlight_transit_state(int state)
641 backlight_ops.get_brightness(&brt);
643 if (state == DPMS_OFF) {
645 end = display_conf->aod_enter_level;
648 * The value of backlight_ops.get_brightness is system brightness.
649 * But when device is LBM, the value is not same with real brightness.
650 * So it should be read exactly value for transit smooth effect
652 get_brightness(&val);
654 if (val > display_conf->aod_enter_level)
655 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
657 /* prevent transit effect when another effect is already executed */
658 if (brt != display_conf->aod_enter_level) {
659 _W("effect is already executed brt(%d) aod_level(%d)",
660 brt, display_conf->aod_enter_level);
664 start = display_conf->aod_enter_level;
665 end = default_brightness;
666 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
672 static gboolean blink_cb(gpointer data)
676 set_brightness(flag ? PM_MAX_BRIGHTNESS : PM_MIN_BRIGHTNESS);
680 return G_SOURCE_CONTINUE;
683 static void blink(int timeout)
688 g_source_remove(timer);
693 _E("timeout value is invalid %d", timeout);
702 timer = g_timeout_add(timeout, blink_cb, NULL);
705 static gboolean release_blink_cb(gpointer data)
710 return G_SOURCE_REMOVE;
713 static void release_blink(void)
716 g_source_remove(release_timer);
720 release_timer = g_timeout_add(DUMP_MODE_WAITING_TIME, release_blink_cb, NULL);
723 static void restore_brightness_func(void)
725 backlight_ops.set_brightness = set_brightness;
726 backlight_ops.get_brightness = get_brightness;
727 backlight_ops.transit_brt = change_brightness;
730 static struct _backlight_ops backlight_ops = {
731 .off = backlight_off,
732 .dim = backlight_dim,
734 .update = backlight_update,
735 .standby = backlight_standby,
736 .set_default_brt = set_default_brt,
737 .get_default_brt = get_default_brt,
738 .get_lcd_power = get_lcd_power,
739 .set_custom_status = set_custom_status,
740 .get_custom_status = get_custom_status,
741 .save_custom_brightness = save_custom_brightness,
742 .custom_update = custom_backlight_update,
743 .set_force_brightness = set_force_brightness,
744 .set_brightness = set_brightness,
745 .get_brightness = get_brightness,
746 .restore_brightness_func = restore_brightness_func,
747 .get_brightness_by_light_sensor = get_brightness_by_light_sensor,
748 .get_image_effect = get_image_effect,
749 .set_image_effect = set_image_effect,
750 .get_panel_mode = get_panel_mode,
751 .set_panel_mode = set_panel_mode,
752 .get_frame_rate = get_frame_rate,
753 .set_frame_rate = set_frame_rate,
754 .transit_state = backlight_transit_state,
755 .transit_brt = change_brightness,
757 .release_blink = release_blink,
760 int display_service_load(void)
762 struct hw_info *info;
768 r = hw_get_info(DISPLAY_HARDWARE_DEVICE_ID,
769 (const struct hw_info **)&info);
771 _I("display shared library is not supported: %d", r);
776 _E("Failed to open display device: open(NULL).");
780 r = info->open(info, NULL, (struct hw_common **)&display_dev);
782 _E("Failed to get display device structure: %d", r);
786 _D("Display device structure load success.");
790 int display_service_free(void)
792 struct hw_info *info;
797 info = display_dev->common.info;
801 info->close((struct hw_common *)display_dev);
807 static int booting_done(void *data)
809 static int done = false;
819 int is_lcdon_blocked(void)
821 /* block lcdon until booting done in silent boot mode */
822 if (silent_boot && !booting_done(NULL))
823 return LCDON_BLOCK_DURING_SILENT_BOOT;
825 return LCDON_BLOCK_NONE;
828 int init_sysfs(unsigned int flags)
830 register_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
831 register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
838 const struct device_ops *ops = NULL;
844 ops = find_device("touchscreen");
845 if (!check_default(ops))
846 ops->start(NORMAL_MODE);
848 ops = find_device("touchkey");
849 if (!check_default(ops))
850 ops->start(NORMAL_MODE);
852 unregister_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
857 static void __CONSTRUCTOR__ initialize(void)
859 display_conf = get_var_display_config();
861 _E("Failed to get display configuration variable.");