1/*
2* Copyright (c) 2014 - 2016, 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#include <utils/rect.h>
28#include <map>
29#include <algorithm>
30#include <functional>
31#include <vector>
32
33#include "display_primary.h"
34#include "hw_interface.h"
35#include "hw_info_interface.h"
36#include "fb/hw_primary.h"
37
38#define __CLASS__ "DisplayPrimary"
39
40namespace sdm {
41
42DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
43                               BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
44                               RotatorInterface *rotator_intf)
45  : DisplayBase(kPrimary, event_handler, kDevicePrimary, buffer_sync_handler, comp_manager,
46                rotator_intf, hw_info_intf) {
47}
48
49DisplayError DisplayPrimary::Init() {
50  lock_guard<recursive_mutex> obj(recursive_mutex_);
51
52  DisplayError error = HWPrimary::Create(&hw_intf_, hw_info_intf_,
53                                         DisplayBase::buffer_sync_handler_);
54
55  if (error != kErrorNone) {
56    return error;
57  }
58
59  error = DisplayBase::Init();
60  if (error != kErrorNone) {
61    HWPrimary::Destroy(hw_intf_);
62    return error;
63  }
64
65  idle_timeout_ms_ = Debug::GetIdleTimeoutMs();
66
67  if (hw_panel_info_.mode == kModeCommand && Debug::IsVideoModeEnabled()) {
68    error = hw_intf_->SetDisplayMode(kModeVideo);
69    if (error != kErrorNone) {
70      DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode,
71            kModeVideo);
72    }
73  }
74
75  error = HWEventsInterface::Create(INT(display_type_), this, &event_list_, &hw_events_intf_);
76  if (error != kErrorNone) {
77    DLOGE("Failed to create hardware events interface. Error = %d", error);
78    DisplayBase::Deinit();
79    HWPrimary::Destroy(hw_intf_);
80  }
81
82  return error;
83}
84
85DisplayError DisplayPrimary::Deinit() {
86  lock_guard<recursive_mutex> obj(recursive_mutex_);
87
88  DisplayError error = DisplayBase::Deinit();
89  HWPrimary::Destroy(hw_intf_);
90
91  return error;
92}
93
94DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) {
95  lock_guard<recursive_mutex> obj(recursive_mutex_);
96  DisplayError error = kErrorNone;
97  uint32_t new_mixer_width = 0;
98  uint32_t new_mixer_height = 0;
99  uint32_t display_width = display_attributes_.x_pixels;
100  uint32_t display_height = display_attributes_.y_pixels;
101
102  if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
103    error = ReconfigureMixer(new_mixer_width, new_mixer_height);
104    if (error != kErrorNone) {
105      ReconfigureMixer(display_width, display_height);
106    }
107  }
108
109  return DisplayBase::Prepare(layer_stack);
110}
111
112DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
113  lock_guard<recursive_mutex> obj(recursive_mutex_);
114  DisplayError error = kErrorNone;
115
116  // Enabling auto refresh is async and needs to happen before commit ioctl
117  if (hw_panel_info_.mode == kModeCommand) {
118    hw_intf_->SetAutoRefresh(layer_stack->flags.single_buffered_layer_present);
119  }
120
121  bool set_idle_timeout = comp_manager_->CanSetIdleTimeout(display_comp_ctx_);
122
123  error = DisplayBase::Commit(layer_stack);
124  if (error != kErrorNone) {
125    return error;
126  }
127
128  DisplayBase::ReconfigureDisplay();
129
130  if (hw_panel_info_.mode == kModeVideo) {
131    if (set_idle_timeout && !layer_stack->flags.single_buffered_layer_present) {
132      hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_);
133    } else {
134      hw_intf_->SetIdleTimeoutMs(0);
135    }
136  }
137
138  return error;
139}
140
141DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
142  lock_guard<recursive_mutex> obj(recursive_mutex_);
143  DisplayError error = kErrorNone;
144  error = DisplayBase::SetDisplayState(state);
145  if (error != kErrorNone) {
146    return error;
147  }
148
149  // Set vsync enable state to false, as driver disables vsync during display power off.
150  if (state == kStateOff) {
151    vsync_enable_ = false;
152  }
153
154  return kErrorNone;
155}
156
157void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
158  lock_guard<recursive_mutex> obj(recursive_mutex_);
159
160  // Idle fallback feature is supported only for video mode panel.
161  if (hw_panel_info_.mode == kModeVideo) {
162    hw_intf_->SetIdleTimeoutMs(timeout_ms);
163  }
164  idle_timeout_ms_ = timeout_ms;
165}
166
167DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) {
168  lock_guard<recursive_mutex> obj(recursive_mutex_);
169  DisplayError error = kErrorNone;
170  HWDisplayMode hw_display_mode = static_cast<HWDisplayMode>(mode);
171  uint32_t pending = 0;
172
173  if (!active_) {
174    DLOGW("Invalid display state = %d. Panel must be on.", state_);
175    return kErrorNotSupported;
176  }
177
178  if (hw_display_mode != kModeCommand && hw_display_mode != kModeVideo) {
179    DLOGW("Invalid panel mode parameters. Requested = %d", hw_display_mode);
180    return kErrorParameters;
181  }
182
183  if (hw_display_mode == hw_panel_info_.mode) {
184    DLOGW("Same display mode requested. Current = %d, Requested = %d", hw_panel_info_.mode,
185          hw_display_mode);
186    return kErrorNone;
187  }
188
189  error = hw_intf_->SetDisplayMode(hw_display_mode);
190  if (error != kErrorNone) {
191    DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode,
192          hw_display_mode);
193    return error;
194  }
195
196  if (mode == kModeVideo) {
197    ControlPartialUpdate(false /* enable */, &pending);
198    hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_);
199  } else if (mode == kModeCommand) {
200    ControlPartialUpdate(true /* enable */, &pending);
201    hw_intf_->SetIdleTimeoutMs(0);
202  }
203
204  return error;
205}
206
207DisplayError DisplayPrimary::SetPanelBrightness(int level) {
208  lock_guard<recursive_mutex> obj(recursive_mutex_);
209  return hw_intf_->SetPanelBrightness(level);
210}
211
212DisplayError DisplayPrimary::GetRefreshRateRange(uint32_t *min_refresh_rate,
213                                                 uint32_t *max_refresh_rate) {
214  lock_guard<recursive_mutex> obj(recursive_mutex_);
215  DisplayError error = kErrorNone;
216
217  if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) {
218    *min_refresh_rate = hw_panel_info_.min_fps;
219    *max_refresh_rate = hw_panel_info_.max_fps;
220  } else {
221    error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
222  }
223
224  return error;
225}
226
227DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
228  lock_guard<recursive_mutex> obj(recursive_mutex_);
229
230  if (!active_ || !hw_panel_info_.dynamic_fps) {
231    return kErrorNotSupported;
232  }
233
234  if (refresh_rate < hw_panel_info_.min_fps || refresh_rate > hw_panel_info_.max_fps) {
235    DLOGE("Invalid Fps = %d request", refresh_rate);
236    return kErrorParameters;
237  }
238
239  DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
240  if (error != kErrorNone) {
241    return error;
242  }
243
244  return DisplayBase::ReconfigureDisplay();
245}
246
247DisplayError DisplayPrimary::VSync(int64_t timestamp) {
248  if (vsync_enable_) {
249    DisplayEventVSync vsync;
250    vsync.timestamp = timestamp;
251    event_handler_->VSync(vsync);
252  }
253
254  return kErrorNone;
255}
256
257void DisplayPrimary::IdleTimeout() {
258  event_handler_->Refresh();
259  comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
260  AllDisplaysNeedValidate();
261}
262
263void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
264  lock_guard<recursive_mutex> obj(recursive_mutex_);
265  comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
266  if (thermal_level >= kMaxThermalLevel) {
267    AllDisplaysNeedValidate();
268  }
269}
270
271DisplayError DisplayPrimary::GetPanelBrightness(int *level) {
272  lock_guard<recursive_mutex> obj(recursive_mutex_);
273  return hw_intf_->GetPanelBrightness(level);
274}
275
276DisplayError DisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
277  lock_guard<recursive_mutex> obj(recursive_mutex_);
278  if (!pending) {
279    return kErrorParameters;
280  }
281
282  if (!hw_panel_info_.partial_update) {
283    // Nothing to be done.
284    DLOGI("partial update is not applicable for display=%d", display_type_);
285    return kErrorNotSupported;
286  }
287
288  *pending = 0;
289  if (enable == partial_update_control_) {
290    DLOGI("Same state transition is requested.");
291    return kErrorNone;
292  }
293
294  partial_update_control_ = enable;
295
296  if (!enable) {
297    // If the request is to turn off feature, new draw call is required to have
298    // the new setting into effect.
299    *pending = 1;
300  }
301
302  return kErrorNone;
303}
304
305DisplayError DisplayPrimary::DisablePartialUpdateOneFrame() {
306  lock_guard<recursive_mutex> obj(recursive_mutex_);
307  disable_pu_one_frame_ = true;
308
309  return kErrorNone;
310}
311
312}  // namespace sdm
313
314