4 * Copyright (c) 2017 Samsung Electronics Co., Ltd. Ltd. All rights reserved.
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.
21 #include <hal/device/hal-display.h>
22 #include <libsyscommon/ini-parser.h>
24 #include "auto-brightness-sensorhub.h"
26 #include "display-info.h"
28 #include "device-interface.h"
29 #include "display-backlight.h"
30 #include "display-ops.h"
31 #include "shared/common.h"
32 #include "shared/device-notifier.h"
33 #include "shared/log.h"
35 #define SIGNAL_LBM_ON "LBMOn"
36 #define SIGNAL_LBM_OFF "LBMOff"
38 #define LCD_PHASED_DELAY 10000 /* microsecond */
40 #define LBM_TRANSIT_STEP 20
42 static struct lbm_config lbm_conf = {
47 .aod_brightness_level = 0,
50 static struct display_backlight_ops *backlight_ops;
51 static int lbm_setting_mode;
52 static int system_brightness;
53 static bool display_dev_available = false;
55 static int (*origin_set_brightness)(int);
57 static void broadcast_lbm_state(int state)
66 gdbus_signal_emit(NULL,
68 DEVICED_INTERFACE_DISPLAY,
73 static int get_level_by_brt(int brt)
76 for (iter = 0; iter < lbm_conf.brt_table_size; iter++) {
77 if (lbm_conf.brt_table[iter] == brt)
83 int lbm_down_brt(int brt)
88 if (lbm_conf.down_level == 0) {
89 _I("LBM down level setting is 0.");
93 if (lbm_conf.brt_table == NULL || lbm_setting_mode == 0) {
94 _I("LBM setting mode is %d.", lbm_setting_mode);
98 level = get_level_by_brt(brt);
99 down_level = level - lbm_conf.down_level;
104 return lbm_conf.brt_table[down_level];
107 static int lbm_get_brightness(int *val)
109 *val = system_brightness;
114 static int lbm_set_brightness(int val)
118 if(!display_dev_available) {
119 _E("There is no display device.");
123 if (get_pm_status_flag() & DIM_MASK)
126 brt = lbm_down_brt(val);
128 system_brightness = val;
130 _I("Set brightness(LBM on) system=%d, real=%d.", val, brt);
131 syscommon_notifier_emit_notify(DEVICED_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&val);
133 return hal_device_display_set_brightness(brt);
136 static void lbm_change_brightness(int start, int end, int step)
142 if (display_dimstay_check())
145 ret = display_backlight_get_brightness(&prev);
148 _E("Failed to get brightness, %d.", ret);
155 if (get_pm_status_flag() & DIM_MASK)
158 _I("Start %d, end %d, step %d.", start, end, step);
160 if (display_dev_available) {
161 diff = lbm_down_brt(end);
163 ret = hal_device_display_set_multi_brightness(diff, step, LCD_PHASED_DELAY);
164 if (ret != -ENODEV) {
166 _E("Failed to set_multi_brightness, %d.", ret);
168 display_backlight_set_brightness(end);
176 if (abs(diff) < step)
177 val = (diff > 0 ? 1 : -1);
179 val = (int)ceil((double)diff / step);
181 while (start != end) {
186 if ((val > 0 && start > end) ||
187 (val < 0 && start < end))
190 usleep(LCD_PHASED_DELAY);
191 display_backlight_set_brightness(start);
195 int lbm_set_state(int lbm)
197 _I("lbm_set_state, %d", lbm);
199 broadcast_lbm_state(lbm);
201 origin_set_brightness = backlight_ops->set_brightness;
202 backlight_ops->set_brightness = lbm_set_brightness;
203 backlight_ops->get_brightness = lbm_get_brightness;
204 backlight_ops->transit_brt = lbm_change_brightness;
206 backlight_ops->set_brightness = origin_set_brightness;
207 backlight_ops->get_brightness = NULL;
208 backlight_ops->transit_brt = NULL;
214 int lbm_get_state(void)
216 if (!lbm_conf.support)
219 return backlight_ops->set_brightness == lbm_set_brightness;
222 static void lbm_table_load(char *value, struct lbm_config *c)
228 if (!value || value[0] == '\0')
231 for (i = 0; *(value + i) != '\0'; i++) {
232 if (*(value + i) == ',')
236 c->brt_table = malloc(sizeof(int) * level_count);
238 _E("Failed to allocate memory.");
241 c->brt_table_size = level_count;
244 p = strtok_r(value, ",", &saveptr);
246 c->brt_table[i++] = atoi(p);
249 p = strtok_r(NULL, ",", &saveptr);
251 c->brt_table[i++] = atoi(p);
255 static int lbm_load_config(struct parse_result *result, void *user_data)
257 struct lbm_config *c = user_data;
259 _D("%s,%s,%s.", result->section, result->name, result->value);
264 if (!MATCH(result->section, "Display"))
267 if (MATCH(result->name, "LBMsupport")) {
268 c->support = (MATCH(result->value, "yes") ? 1 : 0);
269 _D("lbm support is %d", c->support);
270 } else if (MATCH(result->name, "Level")) {
271 SET_CONF(c->down_level, atoi(result->value));
272 _D("lbm down level is %d", c->down_level);
273 } else if (MATCH(result->name, "BrtTable")) {
274 lbm_table_load(result->value, c);
275 _D("LBM table loaded.");
281 static void lbm_mode_changed(keynode_t *key_nodes, void *data)
283 int mode = vconf_keynode_get_bool(key_nodes);
285 _I("LBM setting value is %s.", mode ? "enable" : "disable");
287 lbm_setting_mode = mode;
289 auto_brightness_control(BR_LBM_OFF, BR_IMPLICIT);
292 bool get_lbm_setting(void)
294 return lbm_setting_mode;
297 static GVariant *dbus_getlbm(GDBusConnection *conn,
298 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
299 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
303 lbm = lbm_get_state();
305 _E("Failed to get low brightness mode %d.", lbm);
307 _D("Get low brightness mode %d.", lbm);
309 return g_variant_new("(i)", lbm);
312 static const dbus_method_s dbus_methods[] = {
313 { "GetLBM", NULL, "i", dbus_getlbm },
316 static const dbus_interface_u dbus_interface = {
318 .name = DEVICED_INTERFACE_DISPLAY,
319 .methods = dbus_methods,
320 .nr_methods = ARRAY_SIZE(dbus_methods),
322 static void lbm_init(void *data)
326 /* load configutation */
327 ret = config_parse(DISPLAY_CONF_FILE, lbm_load_config, &lbm_conf);
329 _W("Failed to load %s, %d. Use default value.", DISPLAY_CONF_FILE, ret);
331 ret = vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_AUTOMATIC_LOW_BRIGHTNESS, &lbm_setting_mode);
333 _E("Failed to get VCONFKEY_SETAPPL_ACCESSIBILITY_AUTOMATIC_LOW_BRIGHTNESS, %d.", ret);
335 vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_AUTOMATIC_LOW_BRIGHTNESS, lbm_mode_changed, NULL);
337 ret = gdbus_add_object(NULL, DEVICED_PATH_DISPLAY, &dbus_interface);
339 _E("Failed to init dbus method, %d.", ret);
341 display_dev_available = display_is_hal_backend_available();
343 _I("LBM setting value is %d.", lbm_setting_mode);
346 static const struct display_ops display_lbm_ops = {
351 DISPLAY_OPS_REGISTER(&display_lbm_ops)
353 static void __CONSTRUCTOR__ initialize(void)
355 backlight_ops = get_var_backlight_ops();
357 _E("Failed to get backlight operator variable.");