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 bool display_dimstay_check(void)
98 if (get_pm_status_flag() & DIM_FLAG)
104 static void change_brightness(int start, int end, int step)
110 if (display_dimstay_check())
113 ret = backlight_ops.get_brightness(&prev);
115 _E("Failed to get brightness: %d", ret);
122 if (get_pm_status_flag() & DIM_MASK)
125 _I("start %d end %d step %d", start, end, step);
127 if (display_dev_available) {
128 ret = hal_device_display_set_multi_brightness(end, step, LCD_PHASED_DELAY);
129 if (ret != -ENODEV) {
131 _E("Failed to set_multi_brightness (%d)", ret);
133 backlight_ops.set_brightness(end);
141 if (abs(diff) < step)
142 val = (diff > 0 ? 1 : -1);
144 val = (int)ceil((double)diff / step);
146 while (start != end) {
150 if ((val > 0 && start > end) ||
151 (val < 0 && start < end))
154 display_backlight_set_brightness_with_delay(start, LCD_PHASED_DELAY);
158 static int set_brightness(int val)
161 int default_brightness = 0, force_brightness = 0;
163 display_backlight_get_default_brightness(&default_brightness);
164 display_backlight_get_force_brightness(&force_brightness);
166 if (!display_dev_available) {
167 _E("There is no display device.");
171 ret = display_backlight_get_max_brightness(&max);
173 _E("Failed to get max brightness.");
177 if (force_brightness > 0 && val != PM_DIM_BRIGHTNESS) {
178 _I("brightness(%d), force brightness(%d)",
179 val, force_brightness);
180 val = force_brightness;
183 if (get_pm_status_flag() & DIM_MASK)
186 /* Maximum Brightness to users is 100.
187 * Thus real brightness need to be calculated */
188 val = val * max / 100;
190 update_bds_brightness_record(val);
191 _I("set brightness %d (default:%d)", val, default_brightness);
192 device_notify(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
194 return hal_device_display_set_brightness(val);
197 static int get_brightness(int *val)
201 if (!display_dev_available) {
202 _E("There is no display device.");
206 ret = hal_device_display_get_brightness(&brt);
209 _E("Get brightness is not supported.");
211 _E("Failed to get brightness: %d", ret);
216 ret = display_backlight_get_normalized_brightness(brt, val);
218 _E("Failed to get normalized brightness.");
225 /* It was operated only AOD enter & leave */
226 static int backlight_transit_state(int state)
230 static int aod_brightness_level;
231 int default_brightness = 0;
233 display_backlight_get_default_brightness(&default_brightness);
235 backlight_ops.get_brightness(&brt);
237 if (state == DPMS_OFF) {
241 * The value of backlight_ops.get_brightness is system brightness.
242 * But when device is LBM, the value is not same with real brightness.
243 * So it should be read exactly value for transit smooth effect
245 get_brightness(&val);
249 * Compare current brightness with threshold based on charger's charging state.
250 * Charger charging state has 2 threshold: CHARGING, MIN
251 * The other states has 3 threshold: MAX, NORMAL, MIN
253 * Select the highest threshold among the thresholds less then the current brightness.
254 * If current brightness is less then MIN threshold, do not transit brightness.
257 * threshold for | threshold for
258 * charger CHARGING | the other charger states
268 * MIN(10)-----|-----MIN(10)
269 * if DISCHARGING and current brightness is 30, then AOD brightness will be 10.
270 * if DISCHARGING and current brightness is 45, then AOD brightness will be 40.
271 * if CHARGING and current brightness is 80, then AOD brightness will be 20.
272 * if current brightness is 5, do not transit brightness.
274 if (aod_min_level > 0 && val < aod_min_level) {
275 _W("Current brightness is already lower than minimum threshold.");
279 if (battery && battery->charge_now == CHARGER_CHARGING) {
280 if (aod_charging_level > 0 && val >= aod_charging_level)
281 aod_brightness_level = aod_charging_level;
282 else if (aod_min_level > 0 && val >= aod_min_level)
283 aod_brightness_level = aod_min_level;
285 aod_brightness_level = display_conf->aod_enter_level;
287 if (aod_max_level > 0 && val >= aod_max_level)
288 aod_brightness_level = aod_max_level;
289 else if (aod_normal_level > 0 && val >= aod_normal_level)
290 aod_brightness_level = aod_normal_level;
291 else if (aod_min_level > 0 && val >= aod_min_level)
292 aod_brightness_level = aod_min_level;
294 aod_brightness_level = display_conf->aod_enter_level;
297 if (val > aod_brightness_level) {
298 _D("backlight transit start %d end %d DPMS OFF", start, aod_brightness_level);
299 backlight_ops.transit_brt(start, aod_brightness_level, display_conf->brightness_change_step);
302 /* prevent transit effect when another effect is already executed */
303 if (brt != aod_brightness_level) {
304 _W("effect is already executed brt(%d) aod_level(%d)",
305 brt, aod_brightness_level);
309 start = aod_brightness_level;
310 end = default_brightness;
311 _D("backlight transit start %d end %d DPMS ON", start, end);
312 backlight_ops.transit_brt(start, end, display_conf->brightness_change_step);
318 static void restore_brightness_func(void)
320 backlight_ops.set_brightness = set_brightness;
321 backlight_ops.get_brightness = get_brightness;
322 backlight_ops.transit_brt = change_brightness;
325 static struct _backlight_ops backlight_ops = {
326 .get_lcd_power = dpms_get_cached_state,
327 .set_brightness = set_brightness,
328 .get_brightness = get_brightness,
329 .restore_brightness_func = restore_brightness_func,
330 .transit_state = backlight_transit_state,
331 .transit_brt = change_brightness,
332 /* auto-test only function */
333 .get_brightness_raw = get_brightness, /* always fetch brightness from node even LBM mode */
336 int display_service_load(void)
340 if (display_dev_available)
343 r = hal_device_display_get_backend();
345 _E("There is no HAL for display.");
346 display_dev_available = false;
347 display_set_hal_backend_available(display_dev_available);
351 display_dev_available = true;
352 display_set_hal_backend_available(display_dev_available);
353 _D("Display device structure load success.");
357 int display_service_free(void)
359 display_dev_available = false;
360 return hal_device_display_put_backend();
363 int is_lcdon_blocked(void)
365 int state = backlight_ops.get_lcd_power();
367 if ((state == DPMS_DETACH) || (state == -EINVAL))
368 return LCDON_BLOCK_WHEN_DISPLAY_DETACHED;
370 return LCDON_BLOCK_NONE;
373 int init_sysfs(unsigned int flags)
375 register_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
377 if (battery_plgn->handle) {
378 fp_get_var_battery_status = dlsym(battery_plgn->handle, "get_var_battery_status");
379 if (fp_get_var_battery_status) {
380 battery = fp_get_var_battery_status();
382 _E("Failed to get battery status.");
384 _E("Failed to obtain address of get_var_battery_status, %s.", dlerror());
386 _I("There is no battery module.");
393 const struct device_ops *ops = NULL;
395 display_backlight_update_by_default_brightness();
399 ops = find_device("touchscreen");
400 if (!check_default(ops))
401 ops->start(NORMAL_MODE);
403 unregister_notifier(DEVICE_NOTIFIER_VITAL_STATE, vital_state_changed);
408 static void __CONSTRUCTOR__ initialize(void)
410 display_conf = get_var_display_config();
412 _E("Failed to get display configuration variable.");
414 battery_plgn = get_var_battery_plugin();
416 _E("Failed to get battery plugin variable.");