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