4 * Copyright (c) 2023 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.
21 #include <hal/device/hal-display.h>
23 #include "shared/device-notifier.h"
24 #include "shared/log.h"
25 #include "power/power-suspend.h"
27 #include "device-interface.h"
29 #include "display-state-transition.h"
30 #include "display-backlight.h"
31 #include "display-panel.h"
32 #include "display-plugin.h"
34 #define DUMP_MODE_WAITING_TIME 600000 /* milisecond */
35 #define LCD_PHASED_DELAY 10000 /* microsecond */
37 static int default_brightness;
38 static int custom_brightness;
39 static bool g_custom_status;
40 static int force_brightness;
41 static guint release_timer;
43 /* FIXME: This function is for temporary use, should be fixed after plugin refactoring */
44 int display_backlight_get_max_brightness(int *max_brightness)
53 *max_brightness = max;
57 if (!display_is_hal_backend_available()) {
58 _E("There is no HAL for display.");
62 ret = hal_device_display_get_max_brightness(&max);
64 _W("Get max brightness is not supported.");
65 *max_brightness = DEFAULT_DISPLAY_MAX_BRIGHTNESS;
68 _E("Failed to get max brightness: %d", ret);
74 /* FIXME: This function is for temporary use, should be fixed after plugin refactoring */
75 int display_backlight_get_normalized_brightness(int raw_brightness,
76 int *normalized_brightness)
78 int quotient, remainder;
81 if (!normalized_brightness)
84 ret = display_backlight_get_max_brightness(&max);
86 _E("Failed to get max brightness.");
91 * Thus the brightness value need to be calculated using real brightness.
92 * ex) Let's suppose that the maximum brightness of driver is 255.
93 * case 1) When the user sets the brightness to 41,
95 * 41 * 255 / 100 = 104.55 = 104 (rounded off)
96 * case 2) When the user gets the brightness,
97 * the driver returns the brightness 104.
98 * Thus the brightness to users is
99 * 104 * 100 / 255 = 40.7843.... = 41 (rounded up)
101 quotient = raw_brightness * 100 / max;
102 remainder = raw_brightness * 100 % max;
106 *normalized_brightness = quotient;
110 int display_backlight_set_brightness(int brightness)
112 int max_brightness, ret;
113 int default_brightness, force_brightness;
115 display_backlight_get_default_brightness(&default_brightness);
116 display_backlight_get_force_brightness(&force_brightness);
118 ret = display_plugin_backlight_set_brightness(brightness);
122 if (!display_is_hal_backend_available()) {
123 _E("There is no display device.");
127 ret = display_backlight_get_max_brightness(&max_brightness);
129 _E("Failed to get max brightness.");
133 if (force_brightness > 0 && brightness != PM_DIM_BRIGHTNESS) {
134 _I("brightness(%d), force brightness(%d)", brightness, force_brightness);
135 brightness = force_brightness;
138 if (get_pm_status_flag() & DIM_MASK)
139 brightness = PM_DIM_BRIGHTNESS;
141 /* Maximum Brightness to users is 100.
142 * Thus real brightness need to be calculated */
143 brightness = brightness * max_brightness / 100;
145 _I("set brightness %d (default:%d)", brightness, default_brightness);
146 syscommon_notifier_emit_notify(DEVICED_NOTIFIER_DISPLAY_BRIGHTNESS, (void *)&brightness);
148 return hal_device_display_set_brightness(brightness);
151 int display_backlight_get_brightness(int *brightness)
153 int brt = 0, ret = 0;
155 ret = display_plugin_backlight_get_brightness(brightness);
159 if (!display_is_hal_backend_available()) {
160 _E("There is no display device.");
164 ret = hal_device_display_get_brightness(&brt);
167 _E("Get brightness is not supported.");
169 _E("Failed to get brightness: %d", ret);
174 ret = display_backlight_get_normalized_brightness(brt, brightness);
176 _E("Failed to get normalized brightness.");
183 void display_backlight_change_brightness(int start, int end, int step)
189 ret = display_plugin_backlight_transit_brightness(start, end, step);
193 if (display_dimstay_check())
196 ret = display_backlight_get_brightness(&prev);
198 _E("Failed to get brightness: %d", ret);
205 if (get_pm_status_flag() & DIM_MASK)
206 end = PM_DIM_BRIGHTNESS;
208 _I("start %d end %d step %d", start, end, step);
210 if (!display_is_hal_backend_available()) {
211 ret = hal_device_display_set_multi_brightness(end, step, LCD_PHASED_DELAY);
212 if (ret != -ENODEV) {
214 _E("Failed to set_multi_brightness (%d)", ret);
216 display_backlight_set_brightness(end);
224 if (abs(diff) < step)
225 val = (diff > 0 ? 1 : -1);
227 val = (int)ceil((double)diff / step);
229 while (start != end) {
234 if ((val > 0 && start > end) || (val < 0 && start < end))
237 display_backlight_set_brightness_with_delay(start, LCD_PHASED_DELAY);
241 /* FIXME: display_backlight_get_brightness is duplicated, this code structure should be changed */
242 /* It was operated only AOD enter & leave. */
243 int display_backlight_change_brightness_by_dpms_state(enum dpms_state state)
247 int default_brightness;
250 assert(g_display_plugin.config);
252 display_backlight_get_default_brightness(&default_brightness);
254 ret = display_plugin_backlight_transit_state((int) state);
258 display_backlight_get_brightness(&brt);
260 if (state == DPMS_OFF) {
262 end = g_display_plugin.config->aod_enter_level;
265 * The value of display_backlight_get_brightness is system brightness.
266 * But when device is LBM, the value is not same with real brightness.
267 * So it should be read exactly value for transit smooth effect
269 display_backlight_get_brightness(&val);
271 if (val > g_display_plugin.config->aod_enter_level)
272 display_backlight_change_brightness(start, end, g_display_plugin.config->brightness_change_step);
274 /* prevent transit effect when another effect is already executed */
275 if (brt != g_display_plugin.config->aod_enter_level) {
276 _W("effect is already executed brt(%d) aod_level(%d)",
277 brt, g_display_plugin.config->aod_enter_level);
281 start = g_display_plugin.config->aod_enter_level;
282 end = default_brightness;
283 display_backlight_change_brightness(start, end, g_display_plugin.config->brightness_change_step);
289 int display_backlight_set_default_brightness(int brightness)
291 if (brightness < PM_MIN_BRIGHTNESS || brightness > PM_MAX_BRIGHTNESS) {
292 if (g_display_plugin.config)
293 brightness = g_display_plugin.config->pm_default_brightness;
298 default_brightness = brightness;
302 /* FIXME: default_brightness value should be initialized by vconf_get_int */
303 int display_backlight_get_default_brightness(int *brightness)
305 *brightness = default_brightness;
309 int display_backlight_set_brightness_by_dim_brightness(void)
313 ret = display_backlight_set_brightness(PM_DIM_BRIGHTNESS);
316 enum deviced_display_state current;
318 if (display_state_get_current(¤t) < 0)
322 pm_history_save(PM_LOG_LCD_DIM, current);
324 pm_history_save(PM_LOG_LCD_DIM_FAIL, current);
329 int display_backlight_update_by_default_brightness(void)
332 int default_brightness;
335 display_backlight_get_custom_status(&custom_status);
337 _I("Custom brightness mode, no update brightness");
341 if (display_dimstay_check()) {
342 ret = display_backlight_set_brightness_by_dim_brightness();
344 display_backlight_get_default_brightness(&default_brightness);
345 ret = display_backlight_set_brightness(default_brightness);
351 /* FIXME: This custom_brightness policy can be changed, after plugin refactoring */
352 void display_backlight_set_custom_brightness(int brightness)
354 custom_brightness = brightness;
357 int display_backlight_update_by_custom_brightness(void)
361 if (custom_brightness < PM_MIN_BRIGHTNESS || custom_brightness > PM_MAX_BRIGHTNESS)
364 if (display_dimstay_check()) {
365 ret = display_backlight_set_brightness_by_dim_brightness();
367 _I("Custom brightness restored! %d", custom_brightness);
368 ret = display_backlight_set_brightness(custom_brightness);
374 /* FIXME: This custom_status policy can be changed, after plugin refactoting*/
375 void display_backlight_set_custom_status(bool on)
377 g_custom_status = on;
380 /* FIXME: This custom_status policy can be changed, after plugin refactoting*/
381 void display_backlight_get_custom_status(bool *on)
383 *on = g_custom_status;
386 /* FIXME: This function is not tested */
387 int display_backlight_get_brightness_by_light_sensor(float lmax, float lmin,
388 float light, int *brightness)
390 int raw_brightness, ret = 0;
392 if (!display_is_hal_backend_available())
395 ret = hal_device_display_get_auto_brightness(lmax, lmin, light, &raw_brightness);
398 _E("Get auto brightness is not supported.");
400 _E("Failed to get brightness by light sensor: %d", ret);
404 ret = display_backlight_get_normalized_brightness(raw_brightness, brightness);
406 _E("Failed to get normalized brightness.");
413 static gboolean blink_cb(gpointer data)
417 display_backlight_set_brightness(flag ? PM_MAX_BRIGHTNESS : PM_MIN_BRIGHTNESS);
420 return G_SOURCE_CONTINUE;
423 void display_backlight_set_blink(int timeout)
425 static guint blink_timer;
428 g_source_remove(blink_timer);
433 _W("timeout value is invalid %d", timeout);
438 display_backlight_update_by_default_brightness();
442 blink_timer = g_timeout_add(timeout, blink_cb, NULL);
445 static gboolean release_blink_cb(gpointer data)
447 display_backlight_set_blink(0);
450 return G_SOURCE_REMOVE;
453 void display_backlight_unset_blink(void)
456 g_source_remove(release_timer);
460 release_timer = g_timeout_add(DUMP_MODE_WAITING_TIME, release_blink_cb, NULL);
463 int display_backlight_set_brightness_with_delay(int brightness, int delay)
470 /* Update device brightness */
471 ret = display_backlight_set_brightness(brightness);
472 _I("Set brightness(%d): %d", brightness, ret);
477 /* FIXME: This function is only used for wearable plugin */
478 int display_backlight_set_force_brightness(int brightness)
480 if (brightness < PM_DIM_BRIGHTNESS || brightness > PM_MAX_BRIGHTNESS)
483 force_brightness = brightness;
488 /* FIXME: This function is only used for wearable plugin */
489 void display_backlight_get_force_brightness(int *brightness)
491 *brightness = force_brightness;