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
35namespace sdm {
36
37DisplayPrimary::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
44DisplayError 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
73DisplayError DisplayPrimary::Deinit() {
74  SCOPE_LOCK(locker_);
75
76  DisplayError error = DisplayBase::Deinit();
77  HWPrimary::Destroy(hw_intf_);
78
79  return error;
80}
81
82DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) {
83  SCOPE_LOCK(locker_);
84  return DisplayBase::Prepare(layer_stack);
85}
86
87DisplayError 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
126DisplayError DisplayPrimary::Flush() {
127  SCOPE_LOCK(locker_);
128  return DisplayBase::Flush();
129}
130
131DisplayError DisplayPrimary::GetDisplayState(DisplayState *state) {
132  SCOPE_LOCK(locker_);
133  return DisplayBase::GetDisplayState(state);
134}
135
136DisplayError DisplayPrimary::GetNumVariableInfoConfigs(uint32_t *count) {
137  SCOPE_LOCK(locker_);
138  return DisplayBase::GetNumVariableInfoConfigs(count);
139}
140
141DisplayError DisplayPrimary::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
142  SCOPE_LOCK(locker_);
143  return DisplayBase::GetConfig(index, variable_info);
144}
145
146DisplayError DisplayPrimary::GetActiveConfig(uint32_t *index) {
147  SCOPE_LOCK(locker_);
148  return DisplayBase::GetActiveConfig(index);
149}
150
151DisplayError DisplayPrimary::GetVSyncState(bool *enabled) {
152  SCOPE_LOCK(locker_);
153  return DisplayBase::GetVSyncState(enabled);
154}
155
156bool DisplayPrimary::IsUnderscanSupported() {
157  SCOPE_LOCK(locker_);
158  return DisplayBase::IsUnderscanSupported();
159}
160
161DisplayError 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
177DisplayError DisplayPrimary::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
178  SCOPE_LOCK(locker_);
179  return kErrorNotSupported;
180}
181
182DisplayError DisplayPrimary::SetActiveConfig(uint32_t index) {
183  SCOPE_LOCK(locker_);
184  return DisplayBase::SetActiveConfig(index);
185}
186
187DisplayError 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
200void 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
210DisplayError DisplayPrimary::SetMaxMixerStages(uint32_t max_mixer_stages) {
211  SCOPE_LOCK(locker_);
212  return DisplayBase::SetMaxMixerStages(max_mixer_stages);
213}
214
215DisplayError 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
266DisplayError DisplayPrimary::SetPanelBrightness(int level) {
267  SCOPE_LOCK(locker_);
268  return hw_intf_->SetPanelBrightness(level);
269}
270
271DisplayError DisplayPrimary::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
272                                            bool rotate90) {
273  SCOPE_LOCK(locker_);
274  return DisplayBase::IsScalingValid(crop, dst, rotate90);
275}
276
277DisplayError 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
292DisplayError 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
326void DisplayPrimary::AppendDump(char *buffer, uint32_t length) {
327  SCOPE_LOCK(locker_);
328  DisplayBase::AppendDump(buffer, length);
329}
330
331DisplayError 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
341DisplayError DisplayPrimary::SetCursorPosition(int x, int y) {
342  SCOPE_LOCK(locker_);
343  return DisplayBase::SetCursorPosition(x, y);
344}
345
346DisplayError DisplayPrimary::Blank(bool blank) {
347  SCOPE_LOCK(locker_);
348  return kErrorNone;
349}
350
351void DisplayPrimary::IdleTimeout() {
352  event_handler_->Refresh();
353  comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
354}
355
356void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
357  SCOPE_LOCK(locker_);
358  comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
359}
360
361DisplayError DisplayPrimary::GetPanelBrightness(int *level) {
362  SCOPE_LOCK(locker_);
363  return hw_intf_->GetPanelBrightness(level);
364}
365
366}  // namespace sdm
367
368