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.h"
46 #include "display/display-lock.h"
47 #include "display/display-backlight.h"
48 #include "display/display-panel.h"
49 #include "power/power-boot.h"
50 #include "power/power-suspend.h"
55 #define LCD_PHASED_MAX_BRIGHTNESS 100
56 #define LCD_PHASED_DELAY 10000 /* microsecond */
58 #define DISPLAY_HAL_LIB_PATH "/usr/lib/libdisplay-hal.so"
60 #define GESTURE_STR "gesture"
61 #define POWERKEY_STR "powerkey"
62 #define EVENT_STR "event"
63 #define TOUCH_STR "touch"
64 #define TIMEOUT_STR "timeout"
65 #define PROXIMITY_STR "proximity"
66 #define PALM_STR "palm"
67 #define UNKNOWN_STR "unknown"
69 static struct _backlight_ops backlight_ops;
70 static bool display_dev_available = false;
71 static const struct display_config *display_conf;
73 inline struct _backlight_ops *get_var_backlight_ops(void)
75 return &backlight_ops;
78 bool display_dev_ready(void)
80 return display_dev_available;
83 bool display_dimstay_check(void)
85 if (get_pm_status_flag() & DIM_FLAG)
88 if ((get_pm_status_flag() & PWRSV_FLAG) && !(get_pm_status_flag() & BRTCH_FLAG))
94 static void change_brightness(int start, int end, int step)
100 if (display_dimstay_check())
103 ret = backlight_ops.get_brightness(&prev);
105 _E("Failed to get brightness: %d", ret);
112 if (get_pm_status_flag() & DIM_MASK)
115 _I("start %d end %d step %d", start, end, step);
117 if (display_dev_available) {
118 ret = hal_device_display_set_multi_brightness(end, step, LCD_PHASED_DELAY);
119 if (ret != -ENODEV) {
121 _E("Failed to set_multi_brightness (%d)", ret);
123 backlight_ops.set_brightness(end);
131 if (abs(diff) < step)
132 val = (diff > 0 ? 1 : -1);
134 val = (int)ceil((double)diff / step);
136 while (start != end) {
140 if ((val > 0 && start > end) ||
141 (val < 0 && start < end))
144 display_backlight_set_brightness_with_delay(start, LCD_PHASED_DELAY);
148 static int set_brightness(int val)
151 int default_brightness = 0, force_brightness = 0;
153 display_backlight_get_default_brightness(&default_brightness);
154 display_backlight_get_force_brightness(&force_brightness);
156 if (!display_dev_available) {
157 _E("There is no display device.");
161 ret = display_backlight_get_max_brightness(&max);
163 _E("Failed to get max brightness.");
167 if (force_brightness > 0 && val != PM_DIM_BRIGHTNESS) {
168 _I("brightness(%d), force brightness(%d)",
169 val, force_brightness);
170 val = force_brightness;
173 if (get_pm_status_flag() & DIM_MASK)
176 /* Maximum Brightness to users is 100.
177 * Thus real brightness need to be calculated */
178 val = val * max / 100;
180 _I("set brightness %d (default:%d)", val, default_brightness);
181 device_notify(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
183 return hal_device_display_set_brightness(val);
186 static int get_brightness(int *val)
190 if (!display_dev_available) {
191 _E("There is no display device.");
195 ret = hal_device_display_get_brightness(&brt);
198 _E("Get brightness is not supported.");
200 _E("Failed to get brightness: %d", ret);
205 ret = display_backlight_get_normalized_brightness(brt, val);
207 _E("Failed to get normalized brightness.");
214 /* It was operated only AOD enter & leave */
215 static int backlight_transit_state(int state)
219 int default_brightness = 0;
221 display_backlight_get_default_brightness(&default_brightness);
223 backlight_ops.get_brightness(&brt);
225 if (state == DPMS_OFF) {
227 end = display_conf->aod_enter_level;
230 * The value of backlight_ops.get_brightness is system brightness.
231 * But when device is LBM, the value is not same with real brightness.
232 * So it should be read exactly value for transit smooth effect
234 get_brightness(&val);
236 if (val > display_conf->aod_enter_level)
237 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
239 /* prevent transit effect when another effect is already executed */
240 if (brt != display_conf->aod_enter_level) {
241 _W("effect is already executed brt(%d) aod_level(%d)",
242 brt, display_conf->aod_enter_level);
246 start = display_conf->aod_enter_level;
247 end = default_brightness;
248 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
254 static void restore_brightness_func(void)
256 backlight_ops.set_brightness = set_brightness;
257 backlight_ops.get_brightness = get_brightness;
258 backlight_ops.transit_brt = change_brightness;
261 static struct _backlight_ops backlight_ops = {
262 .get_lcd_power = dpms_get_cached_state,
263 .set_brightness = set_brightness,
264 .get_brightness = get_brightness,
265 .restore_brightness_func = restore_brightness_func,
266 .transit_state = backlight_transit_state,
267 .transit_brt = change_brightness,
270 int display_service_load(void)
274 if (display_dev_available)
277 r = hal_device_display_get_backend();
279 _E("There is no HAL for display.");
280 display_dev_available = false;
281 display_set_hal_backend_available(display_dev_available);
285 display_dev_available = true;
286 display_set_hal_backend_available(display_dev_available);
287 _D("Display device structure load success.");
291 int display_service_free(void)
293 display_dev_available = false;
294 return hal_device_display_put_backend();
297 static int delayed_init_done(void *data)
299 static int done = false;
309 int is_lcdon_blocked(void)
311 /* block lcdon until booting done in silent boot mode */
312 if (silent_boot && !delayed_init_done(NULL))
313 return LCDON_BLOCK_DURING_SILENT_BOOT;
315 return LCDON_BLOCK_NONE;
318 int init_sysfs(unsigned int flags)
320 register_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
321 register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
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.");