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"
36 #include "power/power-suspend.h"
38 #include "shared/devices.h"
39 #include "shared/common.h"
40 #include "shared/device-notifier.h"
42 #include "device-interface.h"
45 #include "display/display-dpms.h"
46 #include "display/display.h"
47 #include "display/display-lock.h"
48 #include "display/display-backlight.h"
49 #include "display/display-panel.h"
54 #define LCD_PHASED_MAX_BRIGHTNESS 100
55 #define LCD_PHASED_DELAY 10000 /* microsecond */
57 #define DISPLAY_HAL_LIB_PATH "/usr/lib/libdisplay-hal.so"
59 #define GESTURE_STR "gesture"
60 #define POWERKEY_STR "powerkey"
61 #define EVENT_STR "event"
62 #define TOUCH_STR "touch"
63 #define TIMEOUT_STR "timeout"
64 #define PROXIMITY_STR "proximity"
65 #define PALM_STR "palm"
66 #define UNKNOWN_STR "unknown"
68 #define FREEZER_VITAL_WAKEUP_CGROUP "/sys/fs/cgroup/freezer/vital_wakeup/freezer.state"
70 static struct _backlight_ops backlight_ops;
71 static bool display_dev_available = false;
72 static const struct display_config *display_conf;
74 inline struct _backlight_ops *get_var_backlight_ops(void)
76 return &backlight_ops;
79 bool display_dev_ready(void)
81 return display_dev_available;
84 bool display_dimstay_check(void)
86 if (get_pm_status_flag() & DIM_FLAG)
89 if ((get_pm_status_flag() & PWRSV_FLAG) && !(get_pm_status_flag() & BRTCH_FLAG))
95 static void change_brightness(int start, int end, int step)
101 if (display_dimstay_check())
104 ret = backlight_ops.get_brightness(&prev);
106 _E("Failed to get brightness: %d", ret);
113 if (get_pm_status_flag() & DIM_MASK)
116 _I("start %d end %d step %d", start, end, step);
118 if (display_dev_available) {
119 ret = hal_device_display_set_multi_brightness(end, step, LCD_PHASED_DELAY);
120 if (ret != -ENODEV) {
122 _E("Failed to set_multi_brightness (%d)", ret);
124 backlight_ops.set_brightness(end);
132 if (abs(diff) < step)
133 val = (diff > 0 ? 1 : -1);
135 val = (int)ceil((double)diff / step);
137 while (start != end) {
141 if ((val > 0 && start > end) ||
142 (val < 0 && start < end))
145 display_backlight_set_brightness_with_delay(start, LCD_PHASED_DELAY);
149 static int set_brightness(int val)
152 int default_brightness = 0, force_brightness = 0;
154 display_backlight_get_default_brightness(&default_brightness);
155 display_backlight_get_force_brightness(&force_brightness);
157 if (!display_dev_available) {
158 _E("There is no display device.");
162 ret = display_backlight_get_max_brightness(&max);
164 _E("Failed to get max brightness.");
168 if (force_brightness > 0 && val != PM_DIM_BRIGHTNESS) {
169 _I("brightness(%d), force brightness(%d)",
170 val, force_brightness);
171 val = force_brightness;
174 if (get_pm_status_flag() & DIM_MASK)
177 /* Maximum Brightness to users is 100.
178 * Thus real brightness need to be calculated */
179 val = val * max / 100;
181 _I("set brightness %d (default:%d)", val, default_brightness);
182 device_notify(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
184 return hal_device_display_set_brightness(val);
187 static int get_brightness(int *val)
191 if (!display_dev_available) {
192 _E("There is no display device.");
196 ret = hal_device_display_get_brightness(&brt);
199 _E("Get brightness is not supported.");
201 _E("Failed to get brightness: %d", ret);
206 ret = display_backlight_get_normalized_brightness(brt, val);
208 _E("Failed to get normalized brightness.");
215 /* It was operated only AOD enter & leave */
216 static int backlight_transit_state(int state)
220 int default_brightness = 0;
222 display_backlight_get_default_brightness(&default_brightness);
224 backlight_ops.get_brightness(&brt);
226 if (state == DPMS_OFF) {
228 end = display_conf->aod_enter_level;
231 * The value of backlight_ops.get_brightness is system brightness.
232 * But when device is LBM, the value is not same with real brightness.
233 * So it should be read exactly value for transit smooth effect
235 get_brightness(&val);
237 if (val > display_conf->aod_enter_level)
238 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
240 /* prevent transit effect when another effect is already executed */
241 if (brt != display_conf->aod_enter_level) {
242 _W("effect is already executed brt(%d) aod_level(%d)",
243 brt, display_conf->aod_enter_level);
247 start = display_conf->aod_enter_level;
248 end = default_brightness;
249 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
255 static void restore_brightness_func(void)
257 backlight_ops.set_brightness = set_brightness;
258 backlight_ops.get_brightness = get_brightness;
259 backlight_ops.transit_brt = change_brightness;
262 static struct _backlight_ops backlight_ops = {
263 .get_lcd_power = dpms_get_cached_state,
264 .set_brightness = set_brightness,
265 .get_brightness = get_brightness,
266 .restore_brightness_func = restore_brightness_func,
267 .transit_state = backlight_transit_state,
268 .transit_brt = change_brightness,
271 int display_service_load(void)
275 if (display_dev_available)
278 r = hal_device_display_get_backend();
280 _E("There is no HAL for display.");
281 display_dev_available = false;
282 display_set_hal_backend_available(display_dev_available);
286 display_dev_available = true;
287 display_set_hal_backend_available(display_dev_available);
288 _D("Display device structure load success.");
292 int display_service_free(void)
294 display_dev_available = false;
295 return hal_device_display_put_backend();
298 /* Dummy. Do not consider detached display state */
299 int is_lcdon_blocked(void)
301 return LCDON_BLOCK_NONE;
304 int init_sysfs(unsigned int flags)
306 register_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
313 const struct device_ops *ops = NULL;
315 display_backlight_update_by_default_brightness();
319 ops = find_device("touchscreen");
320 if (!check_default(ops))
321 ops->start(NORMAL_MODE);
323 ops = find_device("touchkey");
324 if (!check_default(ops))
325 ops->start(NORMAL_MODE);
327 unregister_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
332 static void __CONSTRUCTOR__ initialize(void)
334 display_conf = get_var_display_config();
336 _E("Failed to get display configuration variable.");