1 /*
2 * Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are permitted
5 * provided that the following conditions are met:
6 *    * Redistributions of source code must retain the above copyright notice, this list of
7 *      conditions and the following disclaimer.
8 *    * Redistributions in binary form must reproduce the above copyright notice, this list of
9 *      conditions and the following disclaimer in the documentation and/or other materials provided
10 *      with the distribution.
11 *    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
12 *      endorse or promote products derived from this software without specific prior written
13 *      permission.
14 *
15 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24 
25 #include <utils/constants.h>
26 #include <utils/debug.h>
27 
28 #include "display_primary.h"
29 #include "hw_interface.h"
30 #include "hw_info_interface.h"
31 #include "fb/hw_primary.h"
32 
33 #define __CLASS__ "DisplayPrimary"
34 
35 namespace sdm {
36 
DisplayPrimary(DisplayEventHandler * event_handler,HWInfoInterface * hw_info_intf,BufferSyncHandler * buffer_sync_handler,CompManager * comp_manager,RotatorInterface * rotator_intf)37 DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
38                                BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
39                                RotatorInterface *rotator_intf)
40   : DisplayBase(kPrimary, event_handler, kDevicePrimary, buffer_sync_handler, comp_manager,
41                 rotator_intf, hw_info_intf) {
42 }
43 
Init()44 DisplayError DisplayPrimary::Init() {
45   SCOPE_LOCK(locker_);
46 
47   DisplayError error = HWPrimary::Create(&hw_intf_, hw_info_intf_,
48                                          DisplayBase::buffer_sync_handler_, this);
49 
50   if (error != kErrorNone) {
51     return error;
52   }
53 
54   error = DisplayBase::Init();
55   if (error != kErrorNone) {
56     HWPrimary::Destroy(hw_intf_);
57     return error;
58   }
59 
60   idle_timeout_ms_ = Debug::GetIdleTimeoutMs();
61 
62   if (hw_panel_info_.mode == kModeCommand && Debug::IsVideoModeEnabled()) {
63     error = hw_intf_->SetDisplayMode(kModeVideo);
64     if (error != kErrorNone) {
65       DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode,
66             kModeVideo);
67     }
68   }
69 
70   return error;
71 }
72 
Deinit()73 DisplayError DisplayPrimary::Deinit() {
74   SCOPE_LOCK(locker_);
75 
76   DisplayError error = DisplayBase::Deinit();
77   HWPrimary::Destroy(hw_intf_);
78 
79   return error;
80 }
81 
Prepare(LayerStack * layer_stack)82 DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) {
83   SCOPE_LOCK(locker_);
84   return DisplayBase::Prepare(layer_stack);
85 }
86 
Commit(LayerStack * layer_stack)87 DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
88   SCOPE_LOCK(locker_);
89   DisplayError error = kErrorNone;
90   HWPanelInfo panel_info;
91   HWDisplayAttributes display_attributes;
92   uint32_t active_index = 0;
93 
94   // Enabling auto refresh is async and needs to happen before commit ioctl
95   if (hw_panel_info_.mode == kModeCommand) {
96     hw_intf_->SetAutoRefresh(layer_stack->flags.single_buffered_layer_present);
97   }
98 
99   bool set_idle_timeout = comp_manager_->CanSetIdleTimeout(display_comp_ctx_);
100 
101   error = DisplayBase::Commit(layer_stack);
102   if (error != kErrorNone) {
103     return error;
104   }
105 
106   hw_intf_->GetHWPanelInfo(&panel_info);
107   hw_intf_->GetActiveConfig(&active_index);
108   hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
109 
110   if (panel_info != hw_panel_info_) {
111     error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
112     hw_panel_info_ = panel_info;
113   }
114 
115   if (hw_panel_info_.mode == kModeVideo) {
116     if (set_idle_timeout && !layer_stack->flags.single_buffered_layer_present) {
117       hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_);
118     } else {
119       hw_intf_->SetIdleTimeoutMs(0);
120     }
121   }
122 
123   return error;
124 }
125 
Flush()126 DisplayError DisplayPrimary::Flush() {
127   SCOPE_LOCK(locker_);
128   return DisplayBase::Flush();
129 }
130 
GetDisplayState(DisplayState * state)131 DisplayError DisplayPrimary::GetDisplayState(DisplayState *state) {
132   SCOPE_LOCK(locker_);
133   return DisplayBase::GetDisplayState(state);
134 }
135 
GetNumVariableInfoConfigs(uint32_t * count)136 DisplayError DisplayPrimary::GetNumVariableInfoConfigs(uint32_t *count) {
137   SCOPE_LOCK(locker_);
138   return DisplayBase::GetNumVariableInfoConfigs(count);
139 }
140 
GetConfig(uint32_t index,DisplayConfigVariableInfo * variable_info)141 DisplayError DisplayPrimary::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
142   SCOPE_LOCK(locker_);
143   return DisplayBase::GetConfig(index, variable_info);
144 }
145 
GetActiveConfig(uint32_t * index)146 DisplayError DisplayPrimary::GetActiveConfig(uint32_t *index) {
147   SCOPE_LOCK(locker_);
148   return DisplayBase::GetActiveConfig(index);
149 }
150 
GetVSyncState(bool * enabled)151 DisplayError DisplayPrimary::GetVSyncState(bool *enabled) {
152   SCOPE_LOCK(locker_);
153   return DisplayBase::GetVSyncState(enabled);
154 }
155 
IsUnderscanSupported()156 bool DisplayPrimary::IsUnderscanSupported() {
157   SCOPE_LOCK(locker_);
158   return DisplayBase::IsUnderscanSupported();
159 }
160 
SetDisplayState(DisplayState state)161 DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
162   SCOPE_LOCK(locker_);
163   DisplayError error = kErrorNone;
164   error = DisplayBase::SetDisplayState(state);
165   if (error != kErrorNone) {
166     return error;
167   }
168 
169   // Set vsync enable state to false, as driver disables vsync during display power off.
170   if (state == kStateOff) {
171     vsync_enable_ = false;
172   }
173 
174   return kErrorNone;
175 }
176 
SetActiveConfig(DisplayConfigVariableInfo * variable_info)177 DisplayError DisplayPrimary::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
178   SCOPE_LOCK(locker_);
179   return kErrorNotSupported;
180 }
181 
SetActiveConfig(uint32_t index)182 DisplayError DisplayPrimary::SetActiveConfig(uint32_t index) {
183   SCOPE_LOCK(locker_);
184   return DisplayBase::SetActiveConfig(index);
185 }
186 
SetVSyncState(bool enable)187 DisplayError DisplayPrimary::SetVSyncState(bool enable) {
188   SCOPE_LOCK(locker_);
189   DisplayError error = kErrorNone;
190   if (vsync_enable_ != enable) {
191     error = hw_intf_->SetVSyncState(enable);
192     if (error == kErrorNone) {
193       vsync_enable_ = enable;
194     }
195   }
196 
197   return error;
198 }
199 
SetIdleTimeoutMs(uint32_t timeout_ms)200 void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
201   SCOPE_LOCK(locker_);
202 
203   // Idle fallback feature is supported only for video mode panel.
204   if (hw_panel_info_.mode == kModeVideo) {
205     hw_intf_->SetIdleTimeoutMs(timeout_ms);
206   }
207   idle_timeout_ms_ = timeout_ms;
208 }
209 
SetMaxMixerStages(uint32_t max_mixer_stages)210 DisplayError DisplayPrimary::SetMaxMixerStages(uint32_t max_mixer_stages) {
211   SCOPE_LOCK(locker_);
212   return DisplayBase::SetMaxMixerStages(max_mixer_stages);
213 }
214 
SetDisplayMode(uint32_t mode)215 DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) {
216   SCOPE_LOCK(locker_);
217   DisplayError error = kErrorNone;
218   HWDisplayMode hw_display_mode = kModeDefault;
219 
220   if (!active_) {
221     DLOGW("Invalid display state = %d. Panel must be on.", state_);
222     return kErrorNotSupported;
223   }
224 
225   switch (mode) {
226   case kModeVideo:
227     hw_display_mode = kModeVideo;
228     break;
229   case kModeCommand:
230     hw_display_mode = kModeCommand;
231     break;
232   default:
233     DLOGW("Invalid panel mode parameters. Requested = %d", mode);
234     return kErrorParameters;
235   }
236 
237   if (hw_display_mode == hw_panel_info_.mode) {
238     DLOGW("Same display mode requested. Current = %d, Requested = %d", hw_panel_info_.mode,
239           hw_display_mode);
240     return kErrorNone;
241   }
242 
243   error = hw_intf_->SetDisplayMode(hw_display_mode);
244   if (error != kErrorNone) {
245     DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode,
246           hw_display_mode);
247     return error;
248   }
249 
250   // Disable PU if the previous PU state is on when switching to video mode, and re-enable PU when
251   // switching back to command mode.
252   bool toggle_partial_update = !(hw_display_mode == kModeVideo);
253   if (partial_update_control_) {
254     comp_manager_->ControlPartialUpdate(display_comp_ctx_, toggle_partial_update);
255   }
256 
257   if (hw_display_mode == kModeVideo) {
258     hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_);
259   } else if (hw_display_mode == kModeCommand) {
260     hw_intf_->SetIdleTimeoutMs(0);
261   }
262 
263   return error;
264 }
265 
SetPanelBrightness(int level)266 DisplayError DisplayPrimary::SetPanelBrightness(int level) {
267   SCOPE_LOCK(locker_);
268   return hw_intf_->SetPanelBrightness(level);
269 }
270 
IsScalingValid(const LayerRect & crop,const LayerRect & dst,bool rotate90)271 DisplayError DisplayPrimary::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
272                                             bool rotate90) {
273   SCOPE_LOCK(locker_);
274   return DisplayBase::IsScalingValid(crop, dst, rotate90);
275 }
276 
GetRefreshRateRange(uint32_t * min_refresh_rate,uint32_t * max_refresh_rate)277 DisplayError DisplayPrimary::GetRefreshRateRange(uint32_t *min_refresh_rate,
278                                                  uint32_t *max_refresh_rate) {
279   SCOPE_LOCK(locker_);
280   DisplayError error = kErrorNone;
281 
282   if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) {
283     *min_refresh_rate = hw_panel_info_.min_fps;
284     *max_refresh_rate = hw_panel_info_.max_fps;
285   } else {
286     error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
287   }
288 
289   return error;
290 }
291 
SetRefreshRate(uint32_t refresh_rate)292 DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
293   SCOPE_LOCK(locker_);
294 
295   if (!active_ || !hw_panel_info_.dynamic_fps) {
296     return kErrorNotSupported;
297   }
298 
299   if (refresh_rate < hw_panel_info_.min_fps || refresh_rate > hw_panel_info_.max_fps) {
300     DLOGE("Invalid Fps = %d request", refresh_rate);
301     return kErrorParameters;
302   }
303 
304   DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
305   if (error != kErrorNone) {
306     return error;
307   }
308 
309   HWDisplayAttributes display_attributes;
310   uint32_t active_index = 0;
311   error = hw_intf_->GetActiveConfig(&active_index);
312   if (error != kErrorNone) {
313     return error;
314   }
315 
316   error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
317   if (error != kErrorNone) {
318     return error;
319   }
320 
321   comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info_);
322 
323   return kErrorNone;
324 }
325 
AppendDump(char * buffer,uint32_t length)326 void DisplayPrimary::AppendDump(char *buffer, uint32_t length) {
327   SCOPE_LOCK(locker_);
328   DisplayBase::AppendDump(buffer, length);
329 }
330 
VSync(int64_t timestamp)331 DisplayError DisplayPrimary::VSync(int64_t timestamp) {
332   if (vsync_enable_) {
333     DisplayEventVSync vsync;
334     vsync.timestamp = timestamp;
335     event_handler_->VSync(vsync);
336   }
337 
338   return kErrorNone;
339 }
340 
SetCursorPosition(int x,int y)341 DisplayError DisplayPrimary::SetCursorPosition(int x, int y) {
342   SCOPE_LOCK(locker_);
343   return DisplayBase::SetCursorPosition(x, y);
344 }
345 
Blank(bool blank)346 DisplayError DisplayPrimary::Blank(bool blank) {
347   SCOPE_LOCK(locker_);
348   return kErrorNone;
349 }
350 
IdleTimeout()351 void DisplayPrimary::IdleTimeout() {
352   event_handler_->Refresh();
353   comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
354 }
355 
ThermalEvent(int64_t thermal_level)356 void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
357   SCOPE_LOCK(locker_);
358   comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
359 }
360 
GetPanelBrightness(int * level)361 DisplayError DisplayPrimary::GetPanelBrightness(int *level) {
362   SCOPE_LOCK(locker_);
363   return hw_intf_->GetPanelBrightness(level);
364 }
365 
366 }  // namespace sdm
367 
368