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>
32 #include <hw/display.h>
34 #include "ambient-mode.h"
36 #include "core/devices.h"
37 #include "core/list.h"
38 #include "core/common.h"
40 #include "device-interface.h"
43 #include "device-node.h"
48 #define LCD_PHASED_MIN_BRIGHTNESS 1
49 #define LCD_PHASED_MAX_BRIGHTNESS 100
50 #define LCD_PHASED_CHANGE_STEP 5
51 #define LCD_PHASED_DELAY 35000 /* microsecond */
53 #define POWER_AUTOSLEEP_PATH "/sys/power/autosleep"
54 #define POWER_LOCK_PATH "/sys/power/wake_lock"
55 #define POWER_UNLOCK_PATH "/sys/power/wake_unlock"
56 #define POWER_WAKEUP_PATH "/sys/power/wakeup_count"
57 #define POWER_STATE_PATH "/sys/power/state"
64 struct _backlight_ops backlight_ops;
65 struct _power_ops power_ops;
67 static bool custom_status;
68 static int custom_brightness;
69 static int force_brightness;
70 static int default_brightness;
72 static struct display_device *display_dev;
74 static int bl_onoff(int on)
76 enum display_state val;
78 if (!display_dev || !display_dev->set_state)
79 return dpms_set_power(on);
86 val = DISPLAY_STANDBY;
89 val = DISPLAY_SUSPEND;
98 return display_dev->set_state(val);
101 static int bl_brt(int brightness, int delay)
108 if (force_brightness > 0) {
109 _I("brightness(%d), force brightness(%d)",
110 brightness, force_brightness);
111 brightness = force_brightness;
114 /* Update device brightness */
115 ret = backlight_ops.set_brightness(brightness);
117 _I("set brightness %d, %d", brightness, ret);
122 static int system_suspend(void)
126 _I("system suspend");
127 ret = sys_set_str(POWER_STATE_PATH, "mem");
128 _I("system resume (result : %d)", ret);
132 static int system_enable_autosleep(void)
134 _I("system autosleep enabled");
135 return sys_set_str(POWER_AUTOSLEEP_PATH, "mem");
138 static int system_power_lock(void)
140 dd_list *elem, *elem_n;
141 const struct device_ops *dev;
144 _I("system power lock");
145 ret = sys_set_str(POWER_LOCK_PATH, "mainlock");
148 DD_LIST_FOREACH_SAFE(dev_head, elem, elem_n, dev) {
156 static int system_power_unlock(void)
158 dd_list *elem, *elem_n;
159 const struct device_ops *dev;
161 /* Devices Suspend */
162 DD_LIST_FOREACH_SAFE(dev_head, elem, elem_n, dev) {
167 _I("system power unlock");
168 return sys_set_str(POWER_UNLOCK_PATH, "mainlock");
171 static int system_get_power_lock_support(void)
173 static int power_lock_support = -1;
176 if (power_lock_support >= 0)
179 ret = sys_check_node(POWER_LOCK_PATH);
181 power_lock_support = false;
183 power_lock_support = true;
185 _I("system power lock : %s",
186 (power_lock_support ? "support" : "not support"));
189 return power_lock_support;
192 static int get_lcd_power(void)
194 enum dpms_state state;
195 enum display_state val;
198 if (ambient_get_state())
201 if (!display_dev || !display_dev->get_state) {
202 ret = dpms_get_power(&state);
208 ret = display_dev->get_state(&val);
215 case DISPLAY_STANDBY:
217 case DISPLAY_SUSPEND:
226 void change_brightness(int start, int end, int step)
232 if ((pm_status_flag & PWRSV_FLAG) &&
233 !(pm_status_flag & BRTCH_FLAG))
236 ret = backlight_ops.get_brightness(&prev);
238 _E("fail to get brightness : %d", ret);
245 _D("start %d end %d step %d", start, end, step);
249 if (abs(diff) < step)
250 val = (diff > 0 ? 1 : -1);
252 val = (int)ceil((double)diff / step);
254 while (start != end) {
258 if ((val > 0 && start > end) ||
259 (val < 0 && start < end))
262 bl_brt(start, LCD_PHASED_DELAY);
266 static int backlight_on(enum device_flags flags)
270 _D("LCD on %x", flags);
272 ret = bl_onoff(DPMS_ON);
274 _E("Failed to turn on backlight");
276 if (flags & LCD_PHASED_TRANSIT_MODE)
277 change_brightness(LCD_PHASED_MIN_BRIGHTNESS,
278 default_brightness, LCD_PHASED_CHANGE_STEP);
283 static int backlight_off(enum device_flags flags)
287 _D("LCD off %x", flags);
289 if (flags & LCD_PHASED_TRANSIT_MODE)
290 change_brightness(default_brightness,
291 LCD_PHASED_MIN_BRIGHTNESS, LCD_PHASED_CHANGE_STEP);
293 if (flags & AMBIENT_MODE)
296 ret = bl_onoff(DPMS_OFF);
298 _E("Failed to turn off backlight");
303 static int backlight_dim(void)
308 if (vconf_get_int(VCONFKEY_SETAPPL_LCD_DIM_BRIGHTNESS, &brightness) != 0) {
309 _E("Failed to get VCONFKEY_SETAPPL_LCD_DIM_BRIGHTNESS value");
313 ret = bl_brt(brightness, 0);
316 pm_history_save(PM_LOG_LCD_DIM, pm_cur_state);
318 pm_history_save(PM_LOG_LCD_DIM_FAIL, pm_cur_state);
323 static int set_custom_status(bool on)
329 static bool get_custom_status(void)
331 return custom_status;
334 static int save_custom_brightness(void)
338 ret = backlight_ops.get_brightness(&brightness);
340 custom_brightness = brightness;
345 static int custom_backlight_update(void)
349 if (custom_brightness < PM_MIN_BRIGHTNESS ||
350 custom_brightness > PM_MAX_BRIGHTNESS)
353 if ((pm_status_flag & PWRSV_FLAG) && !(pm_status_flag & BRTCH_FLAG)) {
354 ret = backlight_dim();
356 _I("custom brightness restored! %d", custom_brightness);
357 ret = bl_brt(custom_brightness, 0);
363 static int set_force_brightness(int level)
365 if (level < 0 || level > PM_MAX_BRIGHTNESS)
368 force_brightness = level;
373 static int backlight_update(void)
377 if (get_custom_status()) {
378 _I("custom brightness mode! brt no updated");
381 if ((pm_status_flag & PWRSV_FLAG) && !(pm_status_flag & BRTCH_FLAG))
382 ret = backlight_dim();
384 ret = bl_brt(default_brightness, 0);
389 static int backlight_standby(int force)
393 if ((get_lcd_power() == DPMS_ON) || force) {
395 ret = bl_onoff(DPMS_STANDBY);
401 static int set_default_brt(int level)
403 if (level < PM_MIN_BRIGHTNESS || level > PM_MAX_BRIGHTNESS)
404 level = PM_DEFAULT_BRIGHTNESS;
406 default_brightness = level;
411 static int check_wakeup_src(void)
414 * return wackeup source. user input or device interrupts? (EVENT_DEVICE or EVENT_INPUT)
419 static int get_wakeup_count(int *cnt)
427 ret = sys_get_int(POWER_WAKEUP_PATH, &wakeup_count);
435 static int set_wakeup_count(int cnt)
439 ret = sys_set_int(POWER_WAKEUP_PATH, cnt);
446 static int get_max_brightness(void)
455 _E("there is no display device");
459 if (!display_dev->get_max_brightness) {
460 max = DEFAULT_DISPLAY_MAX_BRIGHTNESS;
464 ret = display_dev->get_max_brightness(&max);
466 _E("Failed to get max brightness (%d)", ret);
473 static int set_brightness(int val)
477 if (!display_dev || !display_dev->set_brightness) {
478 _E("there is no display device");
482 max = get_max_brightness();
484 _E("Failed to get max brightness");
488 /* Maximum Brightness to users is 100.
489 * Thus real brightness need to be calculated */
490 val = val * max / 100;
492 return display_dev->set_brightness(val);
495 static int get_brt_normalized(int brt_raw)
497 int quotient, remainder;
500 max = get_max_brightness();
502 _E("Failed to get max brightness");
506 /* Maximum Brightness to users is 100.
507 * Thus the brightness value need to be calculated using real brightness.
508 * ex) Let's suppose that the maximum brightness of driver is 255.
509 * case 1) When the user sets the brightness to 41,
511 * 41 * 255 / 100 = 104.55 = 104 (rounded off)
512 * case 2) When the user gets the brightness,
513 * the driver returns the brightness 104.
514 * Thus the brightness to users is
515 * 104 * 100 / 255 = 40.7843.... = 41 (rounded up)
517 quotient = brt_raw * 100 / max;
518 remainder = brt_raw * 100 % max;
525 static int get_brightness(int *val)
529 if (!display_dev || !display_dev->get_brightness) {
530 _E("there is no display device");
534 ret = display_dev->get_brightness(&brt);
536 _E("failed to get brightness (%d)", ret);
540 *val = get_brt_normalized(brt);
544 static int get_brightness_by_light_sensor(float lmax, float lmin, float light, int *brt)
549 if (!display_dev || !display_dev->get_auto_brightness)
552 ret = display_dev->get_auto_brightness(lmax, lmin, light, &brt_raw);
554 _E("failed to get brightness by light sensor(%d)", ret);
558 *brt = get_brt_normalized(brt_raw);
562 static int get_frame_rate(int *rate)
567 if (!display_dev || !display_dev->get_frame_rate)
570 return display_dev->get_frame_rate(rate);
573 static int set_frame_rate(int rate)
576 static int fmin = -1, fmax = -1;
579 !display_dev->set_frame_rate)
582 if (display_dev->get_min_frame_rate) {
584 ret = display_dev->get_min_frame_rate(&fmin);
586 _E("Failed to get min frate rate (%d)", ret);
591 _E("Invalid rate(%d)! (Valid rate: %d <= rate)", rate, fmin);
596 if (display_dev->get_max_frame_rate) {
598 ret = display_dev->get_max_frame_rate(&fmax);
600 _E("Failed to get max frate rate (%d)", ret);
605 _E("Invalid rate(%d)! (Valid rate: rate <= %d)", rate, fmax);
610 return display_dev->set_frame_rate(rate);
613 static void _init_ops(void)
615 backlight_ops.off = backlight_off;
616 backlight_ops.dim = backlight_dim;
617 backlight_ops.on = backlight_on;
618 backlight_ops.update = backlight_update;
619 backlight_ops.standby = backlight_standby;
620 backlight_ops.set_default_brt = set_default_brt;
621 backlight_ops.get_lcd_power = get_lcd_power;
622 backlight_ops.set_custom_status = set_custom_status;
623 backlight_ops.get_custom_status = get_custom_status;
624 backlight_ops.save_custom_brightness = save_custom_brightness;
625 backlight_ops.custom_update = custom_backlight_update;
626 backlight_ops.set_force_brightness = set_force_brightness;
627 backlight_ops.set_brightness = set_brightness;
628 backlight_ops.get_brightness = get_brightness;
629 backlight_ops.get_brightness_by_light_sensor = get_brightness_by_light_sensor;
630 backlight_ops.get_frame_rate = get_frame_rate;
631 backlight_ops.set_frame_rate = set_frame_rate;
633 power_ops.suspend = system_suspend;
634 power_ops.enable_autosleep = system_enable_autosleep;
635 power_ops.power_lock = system_power_lock;
636 power_ops.power_unlock = system_power_unlock;
637 power_ops.get_power_lock_support = system_get_power_lock_support;
638 power_ops.check_wakeup_src = check_wakeup_src;
639 power_ops.get_wakeup_count = get_wakeup_count;
640 power_ops.set_wakeup_count = set_wakeup_count;
643 int display_service_load(void)
645 struct hw_info *info;
651 r = hw_get_info(DISPLAY_HARDWARE_DEVICE_ID,
652 (const struct hw_info **)&info);
654 _I("display shared library is not supported: %d", r);
659 _E("fail to open display device : open(NULL)");
663 r = info->open(info, NULL, (struct hw_common **)&display_dev);
665 _E("fail to get display device structure : %d", r);
669 _D("display device structure load success");
673 int display_service_free(void)
675 struct hw_info *info;
680 info = display_dev->common.info;
684 info->close((struct hw_common *)display_dev);
698 const struct device_ops *ops = NULL;
702 ops = find_device("touchscreen");
703 if (!check_default(ops))
704 ops->start(NORMAL_MODE);
706 ops = find_device("touchkey");
707 if (!check_default(ops))
708 ops->start(NORMAL_MODE);