d79b6e9011aabbc00e7c6d1ebf84884311478e74
[platform/core/system/deviced.git] / src / display / display-panel.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 #include <sys/time.h>
19 #include <libsyscommon/resource-manager.h>
20 #include <system/syscommon-plugin-deviced-display.h>
21 #include <system/syscommon-plugin-deviced-power-interface.h>
22 #include <system/syscommon-plugin-deviced-common-interface.h>
23
24 #include "shared/log.h"
25 #include "power/power.h"
26 #include "power/power-suspend.h"
27 #include "power/power-doze.h"
28 #include "ambient-mode.h"
29 #include "device-interface.h"
30 #include "display-lock.h"
31 #include "display-misc.h"
32 #include "display-panel.h"
33 #include "display-plugin.h"
34 #include "display-signal.h"
35 #include "display-state-transition.h"
36 #include "display-util.h"
37 #include "led/touch-key.h"
38
39 #define MAX_WHITE_BALANCE_GAIN                  2047
40 #define MAX_WHITE_BALANCE_OFFSET                2047
41 #define DEFAULT_WHITE_BALANCE_GAIN              1024
42 #define DEFAULT_WHITE_BALANCE_OFFSET            0
43
44 #define LCD_PHASED_MIN_BRIGHTNESS       1
45 #define LCD_PHASED_CHANGE_STEP          5
46
47 #define DIFF_TIMEVAL_MS(a, b) \
48         (((a.tv_sec * 1000000 + a.tv_usec) - \
49         (b.tv_sec * 1000000 + b.tv_usec)) \
50         / 1000)
51
52 static bool lcd_paneloff_mode = false;
53 static bool lcd_on_broadcasted = true;
54 static struct timeval lcd_on_timeval;
55
56 /* FIXME: This function is for temporary use, should be fixed after plugin refactoring */
57 int display_panel_set_dpms_state(int dpms_on, enum device_flags flags)
58 {
59
60         dpms_set_state(dpms_on);
61
62 #ifdef ENABLE_PM_LOG
63         enum deviced_display_state current;
64
65         if (display_state_get_current(&current) < 0)
66                 return 0;
67
68         if (dpms_on == DPMS_ON)
69                 pm_history_save(PM_LOG_LCD_ON_COMPLETE, current);
70         else if (dpms_on == DPMS_OFF || dpms_on == DPMS_FORCE_OFF)
71                 pm_history_save(PM_LOG_LCD_OFF_COMPLETE, current);
72         else
73                 pm_history_save(PM_LOG_LCD_CONTROL_FAIL, dpms_on);
74 #endif
75
76         return 0;
77 }
78
79 int display_panel_set_white_balance(enum hal_display_white_balance white_balance_type,
80                                         int value)
81 {
82         int ret = 0;
83
84         if (!display_is_hal_backend_available()) {
85                 _E("There is no display device.");
86                 return -ENOENT;
87         }
88
89         switch (white_balance_type) {
90         case HAL_DISPLAY_WHITE_BALANCE_R_GAIN:
91         case HAL_DISPLAY_WHITE_BALANCE_G_GAIN:
92         case HAL_DISPLAY_WHITE_BALANCE_B_GAIN:
93                 if (value > MAX_WHITE_BALANCE_GAIN)
94                         value = DEFAULT_WHITE_BALANCE_GAIN;
95                 break;
96         case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET:
97         case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET:
98         case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET:
99                 if (value > MAX_WHITE_BALANCE_OFFSET)
100                         value = DEFAULT_WHITE_BALANCE_OFFSET;
101                 break;
102         default:
103                 _E("Unknown white balance type");
104                 return -EINVAL;
105         }
106
107         ret = hal_device_display_set_white_balance(white_balance_type, value);
108         if (ret == -ENODEV)
109                 _E("Set white balance is not supported.");
110         else if (ret < 0)
111                 _E("Failed to set white balance value.");
112
113         return ret;
114 }
115
116 int display_panel_get_white_balance(enum hal_display_white_balance white_balance_type,
117                                         int* value)
118 {
119         int ret = 0;
120
121         if (!display_is_hal_backend_available()) {
122                 _E("There is no display device.");
123                 return -ENOENT;
124         }
125
126         switch (white_balance_type) {
127         case HAL_DISPLAY_WHITE_BALANCE_R_GAIN:
128         case HAL_DISPLAY_WHITE_BALANCE_G_GAIN:
129         case HAL_DISPLAY_WHITE_BALANCE_B_GAIN:
130         case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET:
131         case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET:
132         case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET:
133                 break;
134         default:
135                 _E("Unknown white balance type");
136                 return -EINVAL;
137         }
138
139         ret = hal_device_display_get_white_balance(white_balance_type, value);
140         if (ret == -ENODEV)
141                 _E("Get white balance is not supported.");
142         else if (ret < 0)
143                 _E("Failed to get white balance value.");
144
145         return ret;
146 }
147
148 int display_panel_set_panel_state_by_on_state(enum device_flags flags)
149 {
150         int ret = -1;
151         static int cnt;
152
153         _I("[DPMS XLIB Backlight] LCD on %#x cnt:%d", flags, cnt);
154
155         cnt++;
156         ret = display_panel_set_dpms_state(DPMS_ON, flags);
157
158 #ifdef ENABLE_PM_LOG
159         enum deviced_display_state current;
160
161         if (display_state_get_current(&current) < 0)
162                 return 0;
163
164         pm_history_save(PM_LOG_LCD_ON, current);
165 #endif
166         return ret;
167 }
168
169 int display_panel_set_panel_state_by_off_state(enum device_flags flags)
170 {
171         int ret = -1;
172         static int cnt, ambient_cnt;
173         int default_brightness = 0;
174
175         display_backlight_get_default_brightness(&default_brightness);
176
177         if (flags & AMBIENT_MODE) {
178                 _I("[DPMS XLIB Backlight] LCD suspend %#x cnt:%d", flags, ambient_cnt);
179                 ambient_cnt++;
180                 return 0;
181         }
182
183         _I("[DPMS XLIB Backlight] LCD off %#x cnt:%d", flags, cnt);
184         cnt++;
185
186         if (flags & LCD_PHASED_TRANSIT_MODE)
187                 display_backlight_change_brightness(default_brightness,
188                         LCD_PHASED_MIN_BRIGHTNESS, LCD_PHASED_CHANGE_STEP);
189
190         if (flags & FORCE_OFF_MODE)
191                 ret = display_panel_set_dpms_state(DPMS_FORCE_OFF, flags);
192         else
193                 ret = display_panel_set_dpms_state(DPMS_OFF, flags);
194
195 #ifdef ENABLE_PM_LOG
196         enum deviced_display_state current;
197
198         if (display_state_get_current(&current) < 0)
199                 return ret;
200
201         pm_history_save(PM_LOG_LCD_OFF, current);
202 #endif
203         return ret;
204 }
205
206 int display_panel_set_panel_state_by_standby_state(bool standby_on)
207 {
208         int ret = -1;
209
210         if ((dpms_get_cached_state() == DPMS_ON) || standby_on) {
211                 _I("LCD standby");
212                 ret = display_panel_set_dpms_state(DPMS_STANDBY, 0);
213         }
214
215         return ret;
216 }
217
218 /* FIXME: display_plugin_~ function return value should be handling after refactoring */
219 void display_panel_set_lcd_paneloff_mode(bool on)
220 {
221         _I("Lcd paneloff mode: %d", on);
222         lcd_paneloff_mode = on;
223
224         display_state_transition_request_state_transition_with_option(DEVICED_EVENT_DISPLAY, LCD_NORMAL);
225 }
226
227 /* FIXME: This function is temporary, it can be redefined or not */
228 void display_panel_get_lcd_paneloff_mode(bool *on)
229 {
230         if (!on) {
231                 _E("Inavlid parameter to get lcd paneloff mode");
232                 return;
233         }
234
235         *on = lcd_paneloff_mode;
236 }
237
238 void display_panel_lcd_on_procedure(int state, enum device_flags flag)
239 {
240         unsigned long flags = NORMAL_MODE;
241         display_util_get_device_flags(&flags);
242         flags |= flag;
243
244         if (display_plugin_lcd_on_procedure(state, flag) == 0)
245                 return;
246         /*
247          * Display on procedure
248          * step 1. leave doze
249          * step 2. broadcast lcd on signal with cause
250          * step 3. set brightness
251          * step 4. set pmstate of vconf
252          * step 5. display on operate
253          *  - a. display on
254          *  - b. TSP(touch screen) and touchkey enable
255          * step 6. broadcast lcd on complete signal
256          * step 7. key backlight enable
257          */
258         leave_doze();
259
260         _I("[lcdstep] 0x%lx", flags);
261
262         /* send LCDOn dbus signal */
263         if (!lcd_on_broadcasted)
264                 broadcast_lcd_on(SIGNAL_PRE, flags);
265
266         /* Update brightness level */
267         if (state == LCD_DIM)
268                 display_backlight_set_brightness_by_dim_brightness();
269         else if (state == LCD_NORMAL)
270                 display_backlight_update_by_default_brightness();
271
272         if (state == LCD_NORMAL)
273                 set_setting_pmstate(DEVICED_DISPLAY_STATE_ON);
274         else if (state == LCD_DIM)
275                 set_setting_pmstate(DEVICED_DISPLAY_STATE_DIM);
276
277         display_start_dependent_device(flags);
278
279         if (!lcd_on_broadcasted) {
280         broadcast_lcd_on(SIGNAL_POST, flags);
281                 lcd_on_broadcasted = true;
282         }
283
284         touchled_control_backlight(TOUCHLED_DIRECT_ON);
285
286         display_misc_set_touch_event_blocked(false);
287 }
288
289 void display_panel_lcd_off_procedure(enum device_flags flag)
290 {
291         unsigned long flags = NORMAL_MODE;
292         display_util_get_device_flags(&flags);
293         flags |= flag;
294
295         if (display_plugin_lcd_off_procedure(flag) == 0)
296                 return;
297         /*
298          * Display off procedure
299          * step 0. enhance mode off using nofity (e.g mdnie, HBM, LBM)
300          * step 1. broadcast lcd off signal with cause
301          * step 2. set pmstate of vconf
302          * step 3. display off operate
303          *  - a. display off
304          *  - b. TSP(touch screen) and touchkey disable
305          * step 4. broadcast lcd off complete siganl
306          * step 5. enter doze mode if it is enabled
307          */
308         _I("[lcdstep] 0x%lx", flags);
309
310         /* notification */
311
312         syscommon_notifier_emit_notify(DEVICE_NOTIFIER_LCD_OFF, NULL);
313
314         if (lcd_on_broadcasted) {
315                 broadcast_lcd_off(SIGNAL_PRE, flags);
316                 lcd_on_broadcasted = false;
317         }
318
319         /* operation */
320
321         display_misc_set_touch_event_blocked(true);
322
323         set_setting_pmstate(DEVICED_DISPLAY_STATE_OFF);
324
325         touchled_control_backlight(TOUCHLED_DIRECT_OFF);
326
327         display_stop_dependent_device(flags);
328
329         broadcast_lcd_off(SIGNAL_POST, flags);
330         syscommon_notifier_emit_notify(DEVICE_NOTIFIER_LCD_OFF_COMPLETE, NULL);
331
332         enter_doze();
333 }
334
335 void display_panel_lcd_on_direct(enum device_flags flags)
336 {
337         enum hal_device_power_transition_reason reason;
338
339         if (flags & LCD_ON_BY_POWER_KEY)
340                 reason = HAL_DEVICE_POWER_TRANSITION_REASON_POWER_KEY;
341         else if (flags & LCD_ON_BY_TOUCH)
342                 reason = HAL_DEVICE_POWER_TRANSITION_REASON_TOUCH_SCREEN;
343         else
344                 reason = HAL_DEVICE_POWER_TRANSITION_REASON_UNKNOWN;
345
346         syscommon_resman_set_resource_attr_uint64_4(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_POWER),
347                 DEVICED_POWER_ATTR_SET_UINT64_4_CURRENT_STATE,
348                 DEVICED_POWER_STATE_SLEEP, DEVICED_POWER_STATE_NORMAL, reason, 0);
349
350         set_pm_cur_state(DEVICED_DISPLAY_STATE_ON);
351
352         _D("lcd is on directly");
353         display_panel_update_lcd_on_timeval();
354         display_panel_lcd_on_procedure(LCD_NORMAL, flags);
355
356         display_state_transition_update_lock_screen_timeout(LOCK_SCREEN_INPUT_TIMEOUT);
357 }
358
359 /* FIXME: timer_refresh_cb seems legacy code, it can be removed after discussion */
360 static gboolean timer_refresh_cb(gpointer data)
361 {
362         display_state_set_current(DEVICED_DISPLAY_STATE_ON, DEVICED_EVENT_INPUT);
363         return 0;
364 }
365
366 int display_panel_custom_lcd_on(int timeout)
367 {
368         if (display_plugin_custom_lcd_on(timeout) == 0)
369                 return 0;
370
371         if (timeout <= 0)
372                 return -EINVAL;
373
374         if (display_panel_get_dpms_cached_state() != DPMS_ON)
375                 display_panel_lcd_on_direct(LCD_ON_BY_GESTURE);
376
377         _I("Custom lcd on timeout(%d ms).", timeout);
378         if (set_custom_lcdon_timeout(timeout))
379                 display_state_transition_update_display_state_timeout_by_priority();
380
381         display_state_set_current(DEVICED_DISPLAY_STATE_ON, DEVICED_EVENT_INPUT);
382
383         g_idle_add(timer_refresh_cb, NULL);
384
385         return 0;
386 }
387
388 int display_panel_custom_lcd_off(enum device_flags flag)
389 {
390         if (display_plugin_custom_lcd_off(flag) == 0)
391                 return 0;
392
393         /* check holdkey block flag in lock node */
394         if (display_lock_is_state_locked(DEVICED_DISPLAY_STATE_ON) || display_lock_is_state_locked(DEVICED_DISPLAY_STATE_DIM)) {
395                 /*
396                  * When another proccess is normal lock, device is received call then,
397                  * call app can be changed to lcd state by proximity.
398                  * If proximity is near then normal lock will be unlocked.
399                  */
400                 if (flag & LCD_OFF_BY_PROXIMITY) {
401                         _I("custom lcd off by proximity, delete normal lock");
402                         display_lock_release_lock_all(DEVICED_DISPLAY_STATE_ON);
403                 } else {
404                         _I("skip custom lcd off");
405                         return -ECANCELED;
406                 }
407         }
408
409         _I("custom lcd off by flag(%d)", flag);
410         if (display_panel_get_dpms_cached_state() == DPMS_ON)
411                 display_panel_lcd_off_procedure(flag);
412
413         if (set_custom_lcdon_timeout(0) == true)
414                 display_state_transition_update_display_state_timeout_by_priority();
415
416         display_state_set_current(DEVICED_DISPLAY_STATE_OFF, DEVICED_EVENT_INPUT);
417
418         return 0;
419 }
420
421 /** FIXME: handling method should be considered later,
422  *  because the handling is too similar for the same lcd on/off procedure, display state transition.
423 */
424 int display_panel_display_turn_on_by_reason(const char *reason, int timeout)
425 {
426         int flag;
427         int str_len;
428
429         if (display_plugin_display_on_by_reason(reason, timeout) == 0)
430                 return 0;
431
432         if (!reason)
433                 return -EINVAL;
434
435         str_len = strlen(reason);
436
437         if (!strncmp(reason, GESTURE_STR, str_len)) {
438                 flag = LCD_ON_BY_GESTURE;
439         } else if (!strncmp(reason, EVENT_STR, str_len)) {
440                 flag = LCD_ON_BY_EVENT;
441         } else {
442                 _E("Reason is unknown(%s)", reason);
443                 return -EINVAL;
444         }
445
446         if (timeout <= 0) {
447                 _E("Cannot setting timeout %d", timeout);
448                 return -EINVAL;
449         }
450
451         if (display_panel_get_dpms_cached_state() != DPMS_ON)
452                 display_panel_lcd_on_direct(flag);
453
454         _I("platform lcd on by %s (%d ms)", reason, timeout);
455         if (set_custom_lcdon_timeout(timeout) == true)
456                 display_state_transition_update_display_state_timeout_by_priority();
457
458         display_state_set_current(DEVICED_DISPLAY_STATE_ON, DEVICED_EVENT_INPUT);
459
460         return 0;
461 }
462
463 int display_panel_display_turn_off_by_reason(const char *reason)
464 {
465         int flag;
466         int str_len;
467
468         if (display_plugin_display_off_by_reason(reason) == 0)
469                 return 0;
470
471         if (!reason)
472                 return -EINVAL;
473
474         str_len = strlen(reason);
475
476         if (!strncmp(reason, GESTURE_STR, str_len)) {
477                 if (display_lock_is_state_locked(DEVICED_DISPLAY_STATE_ON) || display_lock_is_state_locked(DEVICED_DISPLAY_STATE_DIM)) {
478                         _I("skip platform lcd off by gesture");
479                         return -ECANCELED;
480                 }
481                 flag = LCD_OFF_BY_GESTURE;
482         } else if (!strncmp(reason, PALM_STR, str_len)) {
483                 display_lock_release_lock_all(DEVICED_DISPLAY_STATE_ON);
484                 display_lock_release_lock_all(DEVICED_DISPLAY_STATE_DIM);
485
486                 flag = LCD_OFF_BY_PALM;
487         } else {
488                 _E("Reason is unknown(%s)", reason);
489                 return -EINVAL;
490         }
491
492         _I("platform lcd off by %s", reason);
493         if (display_panel_get_dpms_cached_state() == DPMS_ON)
494                 display_panel_lcd_off_procedure(flag);
495
496         display_state_set_current(DEVICED_DISPLAY_STATE_OFF, DEVICED_EVENT_INPUT);
497
498         return 0;
499 }
500
501 bool display_panel_is_lcd_on_state_broadcasted(void)
502 {
503         return lcd_on_broadcasted;
504 }
505
506 /* FIXME: lcd on time calculation should be discussed, because it is only for lcd_on_direct routine */
507 void display_panel_update_lcd_on_timeval(void)
508 {
509         gettimeofday(&lcd_on_timeval, NULL);
510 }
511
512 int display_panel_calculate_diff_time_between_lcd_on_direct_and_state_action(int *diff_time)
513 {
514         struct timeval now_timeval;
515
516         if (!diff_time)
517                 return -EINVAL;
518
519         if (lcd_on_timeval.tv_sec != 0) {
520                 gettimeofday(&now_timeval, NULL);
521                 *diff_time = DIFF_TIMEVAL_MS(now_timeval, lcd_on_timeval);
522                 lcd_on_timeval.tv_sec = 0;
523                 return 0;
524         }
525
526         return -1;
527 }
528
529 /* FIXME: This function is deprecated, should be fixed after plugin refactoring */
530 int display_panel_get_dpms_state(void)
531 {
532         int ret;
533         enum display_state val;
534
535         ret = hal_device_display_get_state(&val);
536         if (ret < 0)
537                 return ret;
538
539         /**
540          * FIXME: Ambient mode is currently not the display core feature but wearable profile exclusive
541          *        feature. Therefore exclude this condition statement from the display core logic.
542          *        Please consider this condition statement when the ambient feature comes into the display core.
543          */
544         //if (val == DISPLAY_ON && ambient_get_state())
545         //      return DPMS_OFF;
546
547         switch (val) {
548                 case DISPLAY_ON:
549                         return DPMS_ON;
550                 case DISPLAY_STANDBY:
551                         return DPMS_STANDBY;
552                 case DISPLAY_SUSPEND:
553                         return DPMS_SUSPEND;
554                 case DISPLAY_OFF:
555                         return DPMS_OFF;
556                 case DISPLAY_DETACH:
557                         return DPMS_DETACH;
558                 default:
559                         return -EINVAL;
560         }
561 }
562
563 int display_panel_get_dpms_cached_state(void)
564 {
565         return dpms_get_cached_state();
566 }
567
568 bool display_panel_init_dpms(void)
569 {
570         return dpms_init();
571 }
572
573 void display_panel_exit_dpms(void)
574 {
575         dpms_exit();
576 }
577
578 void __display_panel_register_dpms_checklist(int mode, void (*checker)(void), const char *caller)
579 {
580         register_dpms_checklist(mode, checker, caller);
581 }
582
583 /* FIXME: This function is used for only wearable profile, should be fixed after plugin refactoring */
584 int display_panel_set_image_effect(enum display_image_effect effect)
585 {
586         int ret;
587
588         if (!display_is_hal_backend_available()) {
589                 _E("There is no display device.");
590                 return -ENOENT;
591         }
592
593         ret = hal_device_display_set_image_effect(effect);
594         if (ret < 0) {
595                 if (ret == -ENODEV)
596                         _E("Set image effect is not supported.");
597                 else
598                         _E("Failed to set image effect: %d", ret);
599                 return ret;
600         }
601
602         return 0;
603 }
604
605 /* FIXME: This function is deprecated, should be fixed after plugin refactoring */
606 int display_panel_get_image_effect(enum display_image_effect *effect)
607 {
608         int ret;
609         enum display_image_effect val;
610
611         if (!effect)
612                 return -EINVAL;
613
614         if (!display_is_hal_backend_available()) {
615                 _E("There is no display device.");
616                 return -ENOENT;
617         }
618
619         ret = hal_device_display_get_image_effect(&val);
620         if (ret < 0) {
621                 if (ret == -ENODEV)
622                         _E("Get image effect is not supported.");
623                 else
624                         _E("Failed to get image effect: %d", ret);
625                 return ret;
626         }
627
628         *effect = val;
629
630         return 0;
631 }
632
633 /* FIXME: This function is deprecated, should be fixed after plugin refactoring */
634 int display_panel_set_panel_mode(enum display_panel_mode mode)
635 {
636         int ret;
637
638         if (!display_is_hal_backend_available()) {
639                 _E("There is no display device.");
640                 return -ENOENT;
641         }
642
643         ret = hal_device_display_set_panel_mode(mode);
644         if (ret < 0) {
645                 if (ret == -ENODEV)
646                         _E("Set panel mode is not supported.");
647                 else
648                         _E("Failed to set panel mode(%d)", ret);
649                 return ret;
650         }
651
652         return 0;
653 }
654
655 /* FIXME: This function is deprecated, should be fixed after plugin refactoring */
656 int display_panel_get_panel_mode(enum display_panel_mode *mode)
657 {
658         int ret;
659         enum display_panel_mode val;
660
661         if (!mode)
662                 return -EINVAL;
663
664         if (!display_is_hal_backend_available()) {
665                 _E("There is no display device.");
666                 return -ENOENT;
667         }
668
669         ret = hal_device_display_get_panel_mode(&val);
670         if (ret < 0) {
671                 if (ret == -ENODEV)
672                         _E("Get panel mode is not supported.");
673                 else
674                         _E("Failed to get panel mode(%d)", ret);
675                 return ret;
676         }
677
678         *mode = val;
679
680         return 0;
681 }
682
683 /* FIXME: This function is deprecated, should be fixed after plugin refactoring */
684 int display_panel_set_frame_rate(int frame_rate)
685 {
686         int ret = 0;
687         static int fmin = -1, fmax = -1;
688
689         if (!display_is_hal_backend_available())
690                 return -ENOTSUP;
691
692         if (fmin < 0) {
693                 ret = hal_device_display_get_min_frame_rate(&fmin);
694                 if (ret < 0) {
695                         _E("Failed to get min frate rate: %d", ret);
696                         return ret;
697                 }
698         }
699         if ((ret != -ENODEV) && (frame_rate < fmin)) {
700                 _E("Invalid rate(%d). (Valid rate: %d <= rate)", frame_rate, fmin);
701                 return -EINVAL;
702         }
703
704         if (fmax < 0) {
705                 ret = hal_device_display_get_max_frame_rate(&fmax);
706                 if (ret < 0) {
707                         _E("Failed to get max frate rate: %d", ret);
708                         return ret;
709                 }
710         }
711         if ((ret != -ENODEV) && (frame_rate > fmax)) {
712                 _E("Invalid rate(%d). (Valid rate: rate <= %d)", frame_rate, fmax);
713                 return -EINVAL;
714         }
715
716         return hal_device_display_set_frame_rate(frame_rate);
717 }
718
719 /* FIXME: This function is deprecated, should be fixed after plugin refactoring */
720 int display_panel_get_frame_rate(int *frame_rate)
721 {
722         if (!frame_rate)
723                 return -EINVAL;
724
725         if (!display_is_hal_backend_available())
726                 return -ENOTSUP;
727
728         return hal_device_display_get_frame_rate(frame_rate);
729 }