display: Move set brightness with delay function from plugins to core display module
[platform/core/system/deviced.git] / src / display / display-backlight.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 #include <hal/device/hal-display.h>
20
21 #include "shared/log.h"
22 #include "power/power-suspend.h"
23 #include "core.h"
24 #include "display.h"
25 #include "display-backlight.h"
26 #include "display-dpms.h"
27
28 #define DUMP_MODE_WAITING_TIME          600000  /* milisecond */
29
30 static const struct display_config *display_conf;
31 static struct _backlight_ops *backlight_ops;
32
33 static int default_brightness;
34 static int custom_brightness;
35 static bool g_custom_status;
36 static int force_brightness;
37 static guint release_timer;
38
39 /* FIXME: This function is for temporary use, should be fixed after plugin refactoring */
40 int display_backlight_get_max_brightness(int *max_brightness)
41 {
42         static int max = -1;
43         int ret = 0;
44
45         if (!max_brightness)
46                 return -EINVAL;
47
48         if (max > 0) {
49                 *max_brightness = max;
50                 return 0;
51         }
52
53         if (!display_is_hal_backend_available()) {
54                 _E("There is no HAL for display.");
55                 return -ENOENT;
56         }
57
58         ret = hal_device_display_get_max_brightness(&max);
59         if (ret == -ENODEV) {
60                 _W("Get max brightness is not supported.");
61                 *max_brightness = DEFAULT_DISPLAY_MAX_BRIGHTNESS;
62                 return 0;
63         } else if (ret < 0) {
64                 _E("Failed to get max brightness: %d", ret);
65         }
66
67         return ret;
68 }
69
70 /* FIXME: This function is for temporary use, should be fixed after plugin refactoring */
71 int display_backlight_get_normalized_brightness(int raw_brightness,
72         int *normalized_brightness)
73 {
74         int quotient, remainder;
75         int max, ret;
76
77         if (!normalized_brightness)
78                 return -EINVAL;
79
80         ret = display_backlight_get_max_brightness(&max);
81         if (ret < 0) {
82                 _E("Failed to get max brightness.");
83                 return ret;
84         }
85
86         /**
87          * Thus the brightness value need to be calculated using real brightness.
88          *    ex) Let's suppose that the maximum brightness of driver is 255.
89          *      case 1) When the user sets the brightness to 41,
90          *              real brightness is
91          *                 41 * 255 / 100 = 104.55 = 104 (rounded off)
92          *      case 2) When the user gets the brightness,
93          *              the driver returns the brightness 104.
94          *              Thus the brightness to users is
95          *                 104 * 100 / 255 = 40.7843.... = 41 (rounded up)
96          */
97         quotient = raw_brightness * 100 / max;
98         remainder = raw_brightness * 100 % max;
99         if (remainder > 0)
100                 quotient++;
101
102         *normalized_brightness = quotient;
103         return 0;
104 }
105
106 int display_backlight_set_default_brightness(int brightness)
107 {
108         if (brightness < PM_MIN_BRIGHTNESS || brightness > PM_MAX_BRIGHTNESS) {
109                 if (display_conf)
110                         brightness = display_conf->pm_default_brightness;
111                 else
112                         return -EPERM;
113         }
114
115         default_brightness = brightness;
116         return 0;
117 }
118
119 /* FIXME: default_brightness value should be initialized by vconf_get_int */
120 int display_backlight_get_default_brightness(int *brightness)
121 {
122         *brightness = default_brightness;
123         return 0;
124 }
125
126 int display_backlight_set_brightness_by_dim_brightness(void)
127 {
128         int ret = 0;
129
130         ret = backlight_ops->set_brightness(PM_DIM_BRIGHTNESS);
131
132 #ifdef ENABLE_PM_LOG
133         if (!ret)
134                 pm_history_save(PM_LOG_LCD_DIM, get_pm_cur_state());
135         else
136                 pm_history_save(PM_LOG_LCD_DIM_FAIL, get_pm_cur_state());
137 #endif
138         return ret;
139 }
140
141 /* FIXME: display_dimstay_check function should be changed to plugin api call */
142 int display_backlight_update_by_default_brightness(void)
143 {
144         int ret = 0;
145         int default_brightness;
146         bool custom_status;
147
148         display_backlight_get_custom_status(&custom_status);
149         if (custom_status) {
150                 _I("Custom brightness mode, no update brightness");
151                 return 0;
152         }
153
154         if (display_dimstay_check()) {
155                 ret = display_backlight_set_brightness_by_dim_brightness();
156         } else {
157                 display_backlight_get_default_brightness(&default_brightness);
158                 ret = backlight_ops->set_brightness(default_brightness);
159         }
160
161         return ret;
162 }
163
164 /* FIXME: This custom_brightness policy can be changed, after plugin refactoring */
165 void display_backlight_set_custom_brightness(int brightness)
166 {
167         custom_brightness = brightness;
168 }
169
170 /* FIXME: display_dimstay_check function should be changed to plugin api call */
171 int display_backlight_update_by_custom_brightness(void)
172 {
173         int ret = 0;
174
175         if (custom_brightness < PM_MIN_BRIGHTNESS || custom_brightness > PM_MAX_BRIGHTNESS)
176                 return -EINVAL;
177
178         if (display_dimstay_check()) {
179                 ret = display_backlight_set_brightness_by_dim_brightness();
180         } else {
181                 _I("Custom brightness restored! %d", custom_brightness);
182                 ret = backlight_ops->set_brightness(custom_brightness);
183         }
184
185         return ret;
186 }
187
188 /* FIXME: This custom_status policy can be changed, after plugin refactoting*/
189 void display_backlight_set_custom_status(bool on)
190 {
191         g_custom_status = on;
192 }
193
194 /* FIXME: This custom_status policy can be changed, after plugin refactoting*/
195 void display_backlight_get_custom_status(bool *on)
196 {
197         *on = g_custom_status;
198 }
199
200 /* FIXME: This function is not tested */
201 int display_backlight_get_brightness_by_light_sensor(float lmax, float lmin,
202                                                         float light, int *brightness)
203 {
204         int raw_brightness, ret = 0;
205
206         if (!display_is_hal_backend_available())
207                 return -ENOTSUP;
208
209         ret = hal_device_display_get_auto_brightness(lmax, lmin, light, &raw_brightness);
210         if (ret < 0) {
211                 if (ret == -ENODEV)
212                         _E("Get auto brightness is not supported.");
213                 else
214                         _E("Failed to get brightness by light sensor: %d", ret);
215                 return ret;
216         }
217
218         ret = display_backlight_get_normalized_brightness(raw_brightness, brightness);
219         if (ret < 0) {
220                 _E("Failed to get normalized brightness.");
221                 return ret;
222         }
223
224         return 0;
225 }
226
227 static gboolean blink_cb(gpointer data)
228 {
229         static bool flag;
230
231         backlight_ops->set_brightness(flag ? PM_MAX_BRIGHTNESS : PM_MIN_BRIGHTNESS);
232         flag = !flag;
233
234         return G_SOURCE_CONTINUE;
235 }
236
237 void display_backlight_set_blink(int timeout)
238 {
239         static guint blink_timer;
240
241         if (blink_timer) {
242                 g_source_remove(blink_timer);
243                 blink_timer = 0;
244         }
245
246         if (timeout < 0) {
247                 _W("timeout value is invalid %d", timeout);
248                 return;
249         }
250
251         if (timeout == 0) {
252                 display_backlight_update_by_default_brightness();
253                 return;
254         }
255
256         blink_timer = g_timeout_add(timeout, blink_cb, NULL);
257 }
258
259 static gboolean release_blink_cb(gpointer data)
260 {
261         display_backlight_set_blink(0);
262
263         release_timer = 0;
264         return G_SOURCE_REMOVE;
265 }
266
267 void display_backlight_unset_blink(void)
268 {
269         if (release_timer) {
270                 g_source_remove(release_timer);
271                 release_timer = 0;
272         }
273
274         release_timer = g_timeout_add(DUMP_MODE_WAITING_TIME, release_blink_cb, NULL);
275 }
276
277 int display_backlight_set_brightness_with_delay(int brightness, int delay)
278 {
279         int ret = -1;
280
281         if (delay > 0)
282                 usleep(delay);
283
284         /* Update device brightness */
285         ret = backlight_ops->set_brightness(brightness);
286         _I("Set brightness(%d): %d", brightness, ret);
287
288         return ret;
289 }
290
291 /* FIXME: This function is only used for wearable plugin */
292 int display_backlight_set_force_brightness(int brightness)
293 {
294         if (brightness < PM_DIM_BRIGHTNESS ||  brightness > PM_MAX_BRIGHTNESS)
295                 return -EINVAL;
296
297         force_brightness = brightness;
298
299         return 0;
300 }
301
302 /* FIXME: This function is only used for wearable plugin */
303 void display_backlight_get_force_brightness(int *brightness)
304 {
305         *brightness = force_brightness;
306 }
307
308 /* FIXME: This code structure should be changed to plugin api call, after plugin refactoting*/
309 static void __CONSTRUCTOR__ initialize(void)
310 {
311         display_conf = get_var_display_config();
312         if (!display_conf)
313                 _W("Failed to get display configuration variable.");
314
315         backlight_ops = get_var_backlight_ops();
316         if (!backlight_ops)
317                 _W("Failed to get backlight operator variable.");
318
319 }