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 "battery-monitor.h"
50 #include "battery/power-supply.h"
51 #include "power/power-suspend.h"
52 #include "shared/plugin.h"
57 #define LCD_PHASED_MAX_BRIGHTNESS 100
58 #define LCD_PHASED_DELAY 10000 /* microsecond */
60 #define DISPLAY_HAL_LIB_PATH "/usr/lib/libdisplay-hal.so"
62 #define GESTURE_STR "gesture"
63 #define POWERKEY_STR "powerkey"
64 #define EVENT_STR "event"
65 #define TOUCH_STR "touch"
66 #define BEZEL_STR "bezel"
67 #define TIMEOUT_STR "timeout"
68 #define PROXIMITY_STR "proximity"
69 #define PALM_STR "palm"
70 #define UNKNOWN_STR "unknown"
72 #define FREEZER_VITAL_WAKEUP_CGROUP "/sys/fs/cgroup/freezer/vital_wakeup/freezer.state"
75 static struct _backlight_ops backlight_ops;
76 static struct battery_plugin *battery_plgn;
77 static bool display_dev_available = false;
78 static int aod_max_level = -1;
79 static int aod_normal_level = -1;
80 static int aod_min_level = -1;
81 static int aod_charging_level = -1;
82 static const struct display_config *display_conf;
83 static struct battery_status *battery = NULL;
84 static struct battery_status* (*fp_get_var_battery_status)(void);
86 inline struct _backlight_ops *get_var_backlight_ops(void)
88 return &backlight_ops;
91 bool display_dev_ready(void)
93 return display_dev_available;
96 static int bl_brt(int brightness, int delay)
103 /* Update device brightness */
104 ret = backlight_ops.set_brightness(brightness);
106 _I("Set brightness(%d): %d", brightness, ret);
111 bool display_dimstay_check(void)
113 if (get_pm_status_flag() & DIM_FLAG)
119 static void change_brightness(int start, int end, int step)
125 if (display_dimstay_check())
128 ret = backlight_ops.get_brightness(&prev);
130 _E("Failed to get brightness: %d", ret);
137 if (get_pm_status_flag() & DIM_MASK)
140 _I("start %d end %d step %d", start, end, step);
142 if (display_dev_available) {
143 ret = hal_device_display_set_multi_brightness(end, step, LCD_PHASED_DELAY);
144 if (ret != -ENODEV) {
146 _E("Failed to set_multi_brightness (%d)", ret);
148 backlight_ops.set_brightness(end);
156 if (abs(diff) < step)
157 val = (diff > 0 ? 1 : -1);
159 val = (int)ceil((double)diff / step);
161 while (start != end) {
165 if ((val > 0 && start > end) ||
166 (val < 0 && start < end))
169 bl_brt(start, LCD_PHASED_DELAY);
173 static int set_brightness(int val)
176 int default_brightness = 0, force_brightness = 0;
178 display_backlight_get_default_brightness(&default_brightness);
179 display_backlight_get_force_brightness(&force_brightness);
181 if (!display_dev_available) {
182 _E("There is no display device.");
186 ret = display_backlight_get_max_brightness(&max);
188 _E("Failed to get max brightness.");
192 if (force_brightness > 0 && val != PM_DIM_BRIGHTNESS) {
193 _I("brightness(%d), force brightness(%d)",
194 val, force_brightness);
195 val = force_brightness;
198 if (get_pm_status_flag() & DIM_MASK)
201 /* Maximum Brightness to users is 100.
202 * Thus real brightness need to be calculated */
203 val = val * max / 100;
205 update_bds_brightness_record(val);
206 _I("set brightness %d (default:%d)", val, default_brightness);
207 device_notify(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
209 return hal_device_display_set_brightness(val);
212 static int get_brightness(int *val)
216 if (!display_dev_available) {
217 _E("There is no display device.");
221 ret = hal_device_display_get_brightness(&brt);
224 _E("Get brightness is not supported.");
226 _E("Failed to get brightness: %d", ret);
231 ret = display_backlight_get_normalized_brightness(brt, val);
233 _E("Failed to get normalized brightness.");
240 /* It was operated only AOD enter & leave */
241 static int backlight_transit_state(int state)
245 static int aod_brightness_level;
246 int default_brightness = 0;
248 display_backlight_get_default_brightness(&default_brightness);
250 backlight_ops.get_brightness(&brt);
252 if (state == DPMS_OFF) {
256 * The value of backlight_ops.get_brightness is system brightness.
257 * But when device is LBM, the value is not same with real brightness.
258 * So it should be read exactly value for transit smooth effect
260 get_brightness(&val);
264 * Compare current brightness with threshold based on charger's charging state.
265 * Charger charging state has 2 threshold: CHARGING, MIN
266 * The other states has 3 threshold: MAX, NORMAL, MIN
268 * Select the highest threshold among the thresholds less then the current brightness.
269 * If current brightness is less then MIN threshold, do not transit brightness.
272 * threshold for | threshold for
273 * charger CHARGING | the other charger states
283 * MIN(10)-----|-----MIN(10)
284 * if DISCHARGING and current brightness is 30, then AOD brightness will be 10.
285 * if DISCHARGING and current brightness is 45, then AOD brightness will be 40.
286 * if CHARGING and current brightness is 80, then AOD brightness will be 20.
287 * if current brightness is 5, do not transit brightness.
289 if (aod_min_level > 0 && val < aod_min_level) {
290 _W("Current brightness is already lower than minimum threshold.");
294 if (battery && battery->charge_now == CHARGER_CHARGING) {
295 if (aod_charging_level > 0 && val >= aod_charging_level)
296 aod_brightness_level = aod_charging_level;
297 else if (aod_min_level > 0 && val >= aod_min_level)
298 aod_brightness_level = aod_min_level;
300 aod_brightness_level = display_conf->aod_enter_level;
302 if (aod_max_level > 0 && val >= aod_max_level)
303 aod_brightness_level = aod_max_level;
304 else if (aod_normal_level > 0 && val >= aod_normal_level)
305 aod_brightness_level = aod_normal_level;
306 else if (aod_min_level > 0 && val >= aod_min_level)
307 aod_brightness_level = aod_min_level;
309 aod_brightness_level = display_conf->aod_enter_level;
312 if (val > aod_brightness_level) {
313 _D("backlight transit start %d end %d DPMS OFF", start, aod_brightness_level);
314 backlight_ops.transit_brt(start, aod_brightness_level, display_conf->brightness_change_step);
317 /* prevent transit effect when another effect is already executed */
318 if (brt != aod_brightness_level) {
319 _W("effect is already executed brt(%d) aod_level(%d)",
320 brt, aod_brightness_level);
324 start = aod_brightness_level;
325 end = default_brightness;
326 _D("backlight transit start %d end %d DPMS ON", start, end);
327 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
333 static void restore_brightness_func(void)
335 backlight_ops.set_brightness = set_brightness;
336 backlight_ops.get_brightness = get_brightness;
337 backlight_ops.transit_brt = change_brightness;
340 static struct _backlight_ops backlight_ops = {
341 .get_lcd_power = dpms_get_cached_state,
342 .set_brightness = set_brightness,
343 .get_brightness = get_brightness,
344 .restore_brightness_func = restore_brightness_func,
345 .transit_state = backlight_transit_state,
346 .transit_brt = change_brightness,
347 /* auto-test only function */
348 .get_brightness_raw = get_brightness, /* always fetch brightness from node even LBM mode */
351 int display_service_load(void)
355 if (display_dev_available)
358 r = hal_device_display_get_backend();
360 _E("There is no HAL for display.");
361 display_dev_available = false;
362 display_set_hal_backend_available(display_dev_available);
366 display_dev_available = true;
367 display_set_hal_backend_available(display_dev_available);
368 _D("Display device structure load success.");
372 int display_service_free(void)
374 display_dev_available = false;
375 return hal_device_display_put_backend();
378 int is_lcdon_blocked(void)
380 int state = backlight_ops.get_lcd_power();
382 if ((state == DPMS_DETACH) || (state == -EINVAL))
383 return LCDON_BLOCK_WHEN_DISPLAY_DETACHED;
385 return LCDON_BLOCK_NONE;
388 int init_sysfs(unsigned int flags)
390 register_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
392 if (battery_plgn->handle) {
393 fp_get_var_battery_status = dlsym(battery_plgn->handle, "get_var_battery_status");
394 if (fp_get_var_battery_status) {
395 battery = fp_get_var_battery_status();
397 _E("Failed to get battery status.");
399 _E("Failed to obtain address of get_var_battery_status, %s.", dlerror());
401 _I("There is no battery module.");
408 const struct device_ops *ops = NULL;
410 display_backlight_update_by_default_brightness();
414 ops = find_device("touchscreen");
415 if (!check_default(ops))
416 ops->start(NORMAL_MODE);
418 unregister_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
423 static void __CONSTRUCTOR__ initialize(void)
425 display_conf = get_var_display_config();
427 _E("Failed to get display configuration variable.");
429 battery_plgn = get_var_battery_plugin();
431 _E("Failed to get battery plugin variable.");