4 * Copyright (c) 2012 - 2013 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>
30 #include <journal/display.h>
33 #include "core/devices.h"
35 #include "device-interface.h"
38 #include "device-node.h"
44 #define LCD_PHASED_MIN_BRIGHTNESS 1
45 #define LCD_PHASED_MAX_BRIGHTNESS 100
46 #define LCD_PHASED_CHANGE_STEP 5
47 #define LCD_PHASED_DELAY 35000 /* microsecond */
49 typedef struct _PMSys PMSys;
54 int (*sys_power_state) (PMSys *, int);
55 int (*sys_power_lock) (PMSys *, int);
56 int (*sys_get_power_lock_support) (PMSys *);
57 int (*sys_get_lcd_power) (PMSys *);
58 int (*bl_onoff) (PMSys *, int);
59 int (*bl_brt) (PMSys *, int, int);
63 struct _backlight_ops backlight_ops;
64 struct _power_ops power_ops;
66 #ifdef ENABLE_X_LCD_ONOFF
68 static bool x_dpms_enable = false;
71 static int power_lock_support = -1;
72 static bool custom_status = false;
73 static int custom_brightness = 0;
74 static int force_brightness = 0;
76 static int _bl_onoff(PMSys *p, int on)
80 cmd = DISP_CMD(PROP_DISPLAY_ONOFF, DEFAULT_DISPLAY);
81 return device_set_property(DEVICE_TYPE_DISPLAY, cmd, on);
84 static int _bl_brt(PMSys *p, int brightness, int delay)
93 if (force_brightness > 0 && brightness != p->dim_brt) {
94 _I("brightness(%d), force brightness(%d)",
95 brightness, force_brightness);
96 brightness = force_brightness;
99 cmd = DISP_CMD(PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY);
100 ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &prev);
102 /* Update new brightness to vconf */
103 if (!ret && (brightness != prev)) {
104 vconf_set_int(VCONFKEY_PM_CURRENT_BRIGHTNESS, brightness);
107 /* Update device brightness */
108 ret = device_set_property(DEVICE_TYPE_DISPLAY, cmd, brightness);
110 _I("set brightness %d, %d", brightness, ret);
115 static int _sys_power_state(PMSys *p, int state)
117 if (state < POWER_STATE_SUSPEND || state > POWER_STATE_POST_RESUME)
119 return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_STATE, state);
122 static int _sys_power_lock(PMSys *p, int state)
124 if (state != POWER_LOCK && state != POWER_UNLOCK)
126 return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_LOCK, state);
129 static int _sys_get_power_lock_support(PMSys *p)
134 ret = device_get_property(DEVICE_TYPE_POWER, PROP_POWER_LOCK_SUPPORT,
146 static int _sys_get_lcd_power(PMSys *p)
152 cmd = DISP_CMD(PROP_DISPLAY_ONOFF, DEFAULT_DISPLAY);
153 ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &value);
155 if (ret < 0 || value < 0)
161 static void _init_bldev(PMSys *p, unsigned int flags)
166 p->bl_onoff = _bl_onoff;
167 #ifdef ENABLE_X_LCD_ONOFF
168 if (flags & FLAG_X_DPMS) {
169 p->bl_onoff = pm_x_set_lcd_backlight;
170 x_dpms_enable = true;
175 static void _init_pmsys(PMSys *p)
179 val = getenv("PM_SYS_DIMBRT");
180 p->dim_brt = (val ? atoi(val) : 0);
181 p->sys_power_state = _sys_power_state;
182 p->sys_power_lock = _sys_power_lock;
183 p->sys_get_power_lock_support = _sys_get_power_lock_support;
184 p->sys_get_lcd_power = _sys_get_lcd_power;
187 static void *_system_suspend_cb(void *data)
191 _I("enter system suspend");
192 if (pmsys && pmsys->sys_power_state)
193 ret = pmsys->sys_power_state(pmsys, POWER_STATE_SUSPEND);
198 _E("Failed to system suspend! %d", ret);
203 static int system_suspend(void)
208 ret = pthread_create(&pth, 0, _system_suspend_cb, (void*)NULL);
210 _E("pthread creation failed!, suspend directly!");
211 _system_suspend_cb((void*)NULL);
213 pthread_join(pth, NULL);
219 static int system_pre_suspend(void)
221 _I("enter system pre suspend");
222 if (pmsys && pmsys->sys_power_state)
223 return pmsys->sys_power_state(pmsys, POWER_STATE_PRE_SUSPEND);
228 static int system_post_resume(void)
230 _I("enter system post resume");
231 if (pmsys && pmsys->sys_power_state)
232 return pmsys->sys_power_state(pmsys, POWER_STATE_POST_RESUME);
237 static int system_power_lock(void)
239 _I("system power lock");
240 if (pmsys && pmsys->sys_power_lock)
241 return pmsys->sys_power_lock(pmsys, POWER_LOCK);
246 static int system_power_unlock(void)
248 _I("system power unlock");
249 if (pmsys && pmsys->sys_power_lock)
250 return pmsys->sys_power_lock(pmsys, POWER_UNLOCK);
255 static int system_get_power_lock_support(void)
259 if (power_lock_support == -1) {
260 if (pmsys && pmsys->sys_get_power_lock_support) {
261 value = pmsys->sys_get_power_lock_support(pmsys);
263 _I("system power lock : support");
264 power_lock_support = 1;
266 _E("system power lock : not support");
267 power_lock_support = 0;
270 _E("system power lock : read fail");
271 power_lock_support = 0;
275 return power_lock_support;
278 static int get_lcd_power(void)
280 if (pmsys && pmsys->sys_get_lcd_power) {
281 return pmsys->sys_get_lcd_power(pmsys);
287 static int backlight_hbm_off(void)
294 ret = device_get_property(DEVICE_TYPE_DISPLAY,
295 PROP_DISPLAY_HBM_CONTROL, &state);
300 ret = device_set_property(DEVICE_TYPE_DISPLAY,
301 PROP_DISPLAY_HBM_CONTROL, 0);
309 void change_brightness(int start, int end, int step)
316 if ((pm_status_flag & PWRSV_FLAG) &&
317 !(pm_status_flag & BRTCH_FLAG))
320 cmd = DISP_CMD(PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY);
321 ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &prev);
326 _D("start %d end %d step %d", start, end, step);
330 if (abs(diff) < step)
331 val = (diff > 0 ? 1 : -1);
333 val = (int)ceil(diff / step);
335 while (start != end) {
339 if ((val > 0 && start > end) ||
340 (val < 0 && start < end))
343 pmsys->bl_brt(pmsys, start, LCD_PHASED_DELAY);
347 static int backlight_on(enum device_flags flags)
352 _D("LCD on %x", flags);
354 if (!pmsys || !pmsys->bl_onoff)
357 for (i = 0; i < PM_LCD_RETRY_CNT; i++) {
358 ret = pmsys->bl_onoff(pmsys, STATUS_ON);
359 if (get_lcd_power() == PM_LCD_POWER_ON) {
361 pm_history_save(PM_LOG_LCD_ON, pm_cur_state);
363 journal_display_on(pmsys->def_brt);
367 pm_history_save(PM_LOG_LCD_ON_FAIL, pm_cur_state);
369 #ifdef ENABLE_X_LCD_ONOFF
370 _E("Failed to LCD on, through xset");
372 _E("Failed to LCD on, through OAL");
378 if (flags & LCD_PHASED_TRANSIT_MODE)
379 change_brightness(LCD_PHASED_MIN_BRIGHTNESS,
380 pmsys->def_brt, LCD_PHASED_CHANGE_STEP);
385 static int backlight_off(enum device_flags flags)
390 _D("LCD off %x", flags);
392 if (!pmsys || !pmsys->bl_onoff)
395 if (flags & LCD_PHASED_TRANSIT_MODE)
396 change_brightness(pmsys->def_brt,
397 LCD_PHASED_MIN_BRIGHTNESS, LCD_PHASED_CHANGE_STEP);
399 if (flags & AMBIENT_MODE)
402 for (i = 0; i < PM_LCD_RETRY_CNT; i++) {
403 #ifdef ENABLE_X_LCD_ONOFF
404 if (x_dpms_enable == false)
407 ret = pmsys->bl_onoff(pmsys, STATUS_OFF);
408 if (get_lcd_power() == PM_LCD_POWER_OFF) {
410 pm_history_save(PM_LOG_LCD_OFF, pm_cur_state);
412 journal_display_off();
416 pm_history_save(PM_LOG_LCD_OFF_FAIL, pm_cur_state);
418 #ifdef ENABLE_X_LCD_ONOFF
419 _E("Failed to LCD off, through xset");
421 _E("Failed to LCD off, through OAL");
429 static int backlight_dim(void)
432 if (pmsys && pmsys->bl_brt) {
433 ret = pmsys->bl_brt(pmsys, pmsys->dim_brt, 0);
436 pm_history_save(PM_LOG_LCD_DIM, pm_cur_state);
438 pm_history_save(PM_LOG_LCD_DIM_FAIL, pm_cur_state);
444 static int set_custom_status(bool on)
450 static bool get_custom_status(void)
452 return custom_status;
455 static int save_custom_brightness(void)
457 int cmd, ret, brightness;
459 cmd = DISP_CMD(PROP_DISPLAY_BRIGHTNESS, DEFAULT_DISPLAY);
460 ret = device_get_property(DEVICE_TYPE_DISPLAY, cmd, &brightness);
462 custom_brightness = brightness;
467 static int custom_backlight_update(void)
471 if (custom_brightness < PM_MIN_BRIGHTNESS ||
472 custom_brightness > PM_MAX_BRIGHTNESS)
475 if ((pm_status_flag & PWRSV_FLAG) && !(pm_status_flag & BRTCH_FLAG)) {
476 ret = backlight_dim();
477 } else if (pmsys && pmsys->bl_brt) {
478 _I("custom brightness restored! %d", custom_brightness);
479 ret = pmsys->bl_brt(pmsys, custom_brightness, 0);
485 static int set_force_brightness(int level)
487 if (level < 0 || level > PM_MAX_BRIGHTNESS)
490 force_brightness = level;
495 static int backlight_update(void)
499 if (hbm_get_state != NULL && hbm_get_state() == true) {
500 _I("HBM is on, backlight is not updated!");
504 if (get_custom_status()) {
505 _I("custom brightness mode! brt no updated");
508 if ((pm_status_flag & PWRSV_FLAG) && !(pm_status_flag & BRTCH_FLAG)) {
509 ret = backlight_dim();
510 } else if (pmsys && pmsys->bl_brt) {
511 ret = pmsys->bl_brt(pmsys, pmsys->def_brt, 0);
516 static int backlight_standby(int force)
519 if (!pmsys || !pmsys->bl_onoff)
522 if ((get_lcd_power() == PM_LCD_POWER_ON) || force) {
524 ret = pmsys->bl_onoff(pmsys, STATUS_STANDBY);
530 static int set_default_brt(int level)
535 if (level < PM_MIN_BRIGHTNESS || level > PM_MAX_BRIGHTNESS)
536 level = PM_DEFAULT_BRIGHTNESS;
537 pmsys->def_brt = level;
544 static int check_wakeup_src(void)
547 * return wackeup source. user input or device interrupts? (EVENT_DEVICE or EVENT_INPUT)
554 backlight_ops.off = backlight_off;
555 backlight_ops.dim = backlight_dim;
556 backlight_ops.on = backlight_on;
557 backlight_ops.update = backlight_update;
558 backlight_ops.standby = backlight_standby;
559 backlight_ops.hbm_off = backlight_hbm_off;
560 backlight_ops.set_default_brt = set_default_brt;
561 backlight_ops.get_lcd_power = get_lcd_power;
562 backlight_ops.set_custom_status = set_custom_status;
563 backlight_ops.get_custom_status = get_custom_status;
564 backlight_ops.save_custom_brightness = save_custom_brightness;
565 backlight_ops.custom_update = custom_backlight_update;
566 backlight_ops.set_force_brightness = set_force_brightness;
568 power_ops.suspend = system_suspend;
569 power_ops.pre_suspend = system_pre_suspend;
570 power_ops.post_resume = system_post_resume;
571 power_ops.power_lock = system_power_lock;
572 power_ops.power_unlock = system_power_unlock;
573 power_ops.get_power_lock_support = system_get_power_lock_support;
574 power_ops.check_wakeup_src = check_wakeup_src;
577 int init_sysfs(unsigned int flags)
581 pmsys = (PMSys *) malloc(sizeof(PMSys));
583 _E("Not enough memory to alloc PM Sys");
587 memset(pmsys, 0x0, sizeof(PMSys));
590 _init_bldev(pmsys, flags);
592 if (pmsys->bl_onoff == NULL || pmsys->sys_power_state == NULL) {
593 _E("We have no managable resource to reduce the power consumption");
605 const struct device_ops *ops = NULL;
607 fd = open("/tmp/sem.pixmap_1", O_RDONLY);
609 _E("X server disable");
610 backlight_on(NORMAL_MODE);
615 ops = find_device("touchscreen");
616 if (!check_default(ops))
617 ops->start(NORMAL_MODE);
619 ops = find_device("touchkey");
620 if (!check_default(ops))
621 ops->start(NORMAL_MODE);