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-panel.h"
46 #include "display/display.h"
47 #include "display/display-backlight.h"
48 #include "power/power-suspend.h"
49 #include "display/display-lock.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 static int bl_brt(int brightness, int delay)
91 /* Update device brightness */
92 ret = backlight_ops.set_brightness(brightness);
94 _I("Set brightness(%d): %d", brightness, ret);
99 bool display_dimstay_check(void)
101 if (get_pm_status_flag() & DIM_FLAG)
104 if ((get_pm_status_flag() & PWRSV_FLAG) && !(get_pm_status_flag() & BRTCH_FLAG))
110 static void change_brightness(int start, int end, int step)
116 if (display_dimstay_check())
119 ret = backlight_ops.get_brightness(&prev);
121 _E("Failed to get brightness: %d", ret);
128 if (get_pm_status_flag() & DIM_MASK)
131 _I("start %d end %d step %d", start, end, step);
133 if (display_dev_available) {
134 ret = hal_device_display_set_multi_brightness(end, step, LCD_PHASED_DELAY);
135 if (ret != -ENODEV) {
137 _E("Failed to set_multi_brightness (%d)", ret);
139 backlight_ops.set_brightness(end);
147 if (abs(diff) < step)
148 val = (diff > 0 ? 1 : -1);
150 val = (int)ceil((double)diff / step);
152 while (start != end) {
156 if ((val > 0 && start > end) ||
157 (val < 0 && start < end))
160 bl_brt(start, LCD_PHASED_DELAY);
164 static int set_brightness(int val)
167 int default_brightness = 0, force_brightness = 0;
169 display_backlight_get_default_brightness(&default_brightness);
170 display_backlight_get_force_brightness(&force_brightness);
172 if (!display_dev_available) {
173 _E("There is no display device.");
177 ret = display_backlight_get_max_brightness(&max);
179 _E("Failed to get max brightness.");
183 if (force_brightness > 0 && val != PM_DIM_BRIGHTNESS) {
184 _I("brightness(%d), force brightness(%d)",
185 val, force_brightness);
186 val = force_brightness;
189 if (get_pm_status_flag() & DIM_MASK)
192 /* Maximum Brightness to users is 100.
193 * Thus real brightness need to be calculated */
194 val = val * max / 100;
196 _I("set brightness %d (default:%d)", val, default_brightness);
197 device_notify(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
199 return hal_device_display_set_brightness(val);
202 static int get_brightness(int *val)
206 if (!display_dev_available) {
207 _E("There is no display device.");
211 ret = hal_device_display_get_brightness(&brt);
214 _E("Get brightness is not supported.");
216 _E("Failed to get brightness: %d", ret);
221 ret = display_backlight_get_normalized_brightness(brt, val);
223 _E("Failed to get normalized brightness.");
230 /* It was operated only AOD enter & leave */
231 static int backlight_transit_state(int state)
235 int default_brightness = 0;
237 display_backlight_get_default_brightness(&default_brightness);
239 backlight_ops.get_brightness(&brt);
241 if (state == DPMS_OFF) {
243 end = display_conf->aod_enter_level;
246 * The value of backlight_ops.get_brightness is system brightness.
247 * But when device is LBM, the value is not same with real brightness.
248 * So it should be read exactly value for transit smooth effect
250 get_brightness(&val);
252 if (val > display_conf->aod_enter_level)
253 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
255 /* prevent transit effect when another effect is already executed */
256 if (brt != display_conf->aod_enter_level) {
257 _W("effect is already executed brt(%d) aod_level(%d)",
258 brt, display_conf->aod_enter_level);
262 start = display_conf->aod_enter_level;
263 end = default_brightness;
264 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
270 static void restore_brightness_func(void)
272 backlight_ops.set_brightness = set_brightness;
273 backlight_ops.get_brightness = get_brightness;
274 backlight_ops.transit_brt = change_brightness;
277 static struct _backlight_ops backlight_ops = {
278 .get_lcd_power = dpms_get_cached_state,
279 .set_brightness = set_brightness,
280 .get_brightness = get_brightness,
281 .restore_brightness_func = restore_brightness_func,
282 .transit_state = backlight_transit_state,
283 .transit_brt = change_brightness,
286 int display_service_load(void)
290 if (display_dev_available)
293 r = hal_device_display_get_backend();
295 _E("There is no HAL for display.");
296 display_dev_available = false;
297 display_set_hal_backend_available(display_dev_available);
301 display_dev_available = true;
302 display_set_hal_backend_available(display_dev_available);
303 _D("Display device structure load success.");
307 int display_service_free(void)
309 display_dev_available = false;
310 return hal_device_display_put_backend();
313 /* Dummy. Do not consider detached display state */
314 int is_lcdon_blocked(void)
316 return LCDON_BLOCK_NONE;
319 int init_sysfs(unsigned int flags)
321 register_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
328 const struct device_ops *ops = NULL;
330 display_backlight_update_by_default_brightness();
334 ops = find_device("touchscreen");
335 if (!check_default(ops))
336 ops->start(NORMAL_MODE);
338 ops = find_device("touchkey");
339 if (!check_default(ops))
340 ops->start(NORMAL_MODE);
342 unregister_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
347 static void __CONSTRUCTOR__ initialize(void)
349 display_conf = get_var_display_config();
351 _E("Failed to get display configuration variable.");