1/*
2* Copyright (c) 2014 - 2017, 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
37#define __CLASS__ "DisplayPrimary"
38
39namespace sdm {
40
41DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
42                               BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager)
43  : DisplayBase(kPrimary, event_handler, kDevicePrimary, buffer_sync_handler, comp_manager,
44                hw_info_intf) {
45}
46
47DisplayError DisplayPrimary::Init() {
48  lock_guard<recursive_mutex> obj(recursive_mutex_);
49
50  DisplayError error = HWInterface::Create(kPrimary, hw_info_intf_, buffer_sync_handler_,
51                                           &hw_intf_);
52  if (error != kErrorNone) {
53    return error;
54  }
55
56  error = DisplayBase::Init();
57  if (error != kErrorNone) {
58    HWInterface::Destroy(hw_intf_);
59    return error;
60  }
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  avr_prop_disabled_ = Debug::IsAVRDisabled();
71
72  error = HWEventsInterface::Create(INT(display_type_), this, event_list_, &hw_events_intf_);
73  if (error != kErrorNone) {
74    DLOGE("Failed to create hardware events interface. Error = %d", error);
75    DisplayBase::Deinit();
76    HWInterface::Destroy(hw_intf_);
77  }
78
79  return error;
80}
81
82DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) {
83  lock_guard<recursive_mutex> obj(recursive_mutex_);
84  DisplayError error = kErrorNone;
85  uint32_t new_mixer_width = 0;
86  uint32_t new_mixer_height = 0;
87  uint32_t display_width = display_attributes_.x_pixels;
88  uint32_t display_height = display_attributes_.y_pixels;
89  bool needs_hv_flip = hw_panel_info_.panel_orientation.flip_horizontal &&
90                          hw_panel_info_.panel_orientation.flip_vertical;
91  LayerRect src_domain = {};
92  LayerTransform panel_transform = {};
93  DisplayConfigVariableInfo variable_info = {};
94
95  if (needs_hv_flip) {
96    DisplayBase::GetFrameBufferConfig(&variable_info);
97    src_domain.right = variable_info.x_pixels;
98    src_domain.bottom = variable_info.y_pixels;
99    panel_transform.flip_horizontal = hw_panel_info_.panel_orientation.flip_horizontal;
100    panel_transform.flip_vertical = hw_panel_info_.panel_orientation.flip_vertical;
101
102    for (Layer *layer : layer_stack->layers) {
103      // Modify destination based on panel flip
104      TransformHV(src_domain, layer->dst_rect, panel_transform, &layer->dst_rect);
105
106      if (layer->flags.solid_fill) {
107        continue;
108      }
109
110      layer->transform.flip_horizontal ^= (hw_panel_info_.panel_orientation.flip_horizontal);
111      layer->transform.flip_vertical ^= (hw_panel_info_.panel_orientation.flip_vertical);
112     // TODO(user): Check how to handle rotation, if panel has rotation.
113    }
114  }
115
116  if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
117    error = ReconfigureMixer(new_mixer_width, new_mixer_height);
118    if (error != kErrorNone) {
119      ReconfigureMixer(display_width, display_height);
120    }
121  }
122
123  // Clean hw layers for reuse.
124  hw_layers_ = HWLayers();
125  hw_layers_.hw_avr_info.enable = NeedsAVREnable();
126
127  return DisplayBase::Prepare(layer_stack);
128}
129
130DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
131  lock_guard<recursive_mutex> obj(recursive_mutex_);
132  DisplayError error = kErrorNone;
133  uint32_t app_layer_count = hw_layers_.info.app_layer_count;
134
135  // Enabling auto refresh is async and needs to happen before commit ioctl
136  if (hw_panel_info_.mode == kModeCommand) {
137    bool enable = (app_layer_count == 1) && layer_stack->flags.single_buffered_layer_present;
138    bool need_refresh = layer_stack->flags.single_buffered_layer_present && (app_layer_count > 1);
139
140    hw_intf_->SetAutoRefresh(enable);
141    if (need_refresh) {
142      event_handler_->Refresh();
143    }
144  }
145
146  error = DisplayBase::Commit(layer_stack);
147  if (error != kErrorNone) {
148    return error;
149  }
150
151  DisplayBase::ReconfigureDisplay();
152
153  int idle_time_ms = hw_layers_.info.set_idle_time_ms;
154  if (idle_time_ms >= 0) {
155    hw_intf_->SetIdleTimeoutMs(UINT32(idle_time_ms));
156  }
157
158  if (switch_to_cmd_) {
159    uint32_t pending;
160    switch_to_cmd_ = false;
161    ControlPartialUpdate(true /* enable */, &pending);
162  }
163
164  return error;
165}
166
167DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
168  lock_guard<recursive_mutex> obj(recursive_mutex_);
169  DisplayError error = kErrorNone;
170  error = DisplayBase::SetDisplayState(state);
171  if (error != kErrorNone) {
172    return error;
173  }
174
175  // Set vsync enable state to false, as driver disables vsync during display power off.
176  if (state == kStateOff) {
177    vsync_enable_ = false;
178  }
179
180  return kErrorNone;
181}
182
183void DisplayPrimary::SetIdleTimeoutMs(uint32_t active_ms) {
184  lock_guard<recursive_mutex> obj(recursive_mutex_);
185
186  if (comp_manager_->SetIdleTimeoutMs(display_comp_ctx_, active_ms) == kErrorNone) {
187    hw_intf_->SetIdleTimeoutMs(active_ms);
188  }
189}
190
191DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) {
192  DisplayError error = kErrorNone;
193
194  // Limit scope of mutex to this block
195  {
196    lock_guard<recursive_mutex> obj(recursive_mutex_);
197    HWDisplayMode hw_display_mode = static_cast<HWDisplayMode>(mode);
198    uint32_t pending = 0;
199
200    if (!active_) {
201      DLOGW("Invalid display state = %d. Panel must be on.", state_);
202      return kErrorNotSupported;
203    }
204
205    if (hw_display_mode != kModeCommand && hw_display_mode != kModeVideo) {
206      DLOGW("Invalid panel mode parameters. Requested = %d", hw_display_mode);
207      return kErrorParameters;
208    }
209
210    if (hw_display_mode == hw_panel_info_.mode) {
211      DLOGW("Same display mode requested. Current = %d, Requested = %d", hw_panel_info_.mode,
212            hw_display_mode);
213      return kErrorNone;
214    }
215
216    error = hw_intf_->SetDisplayMode(hw_display_mode);
217    if (error != kErrorNone) {
218      DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode,
219            hw_display_mode);
220      return error;
221    }
222
223    if (mode == kModeVideo) {
224      ControlPartialUpdate(false /* enable */, &pending);
225    } else if (mode == kModeCommand) {
226      // Flush idle timeout value currently set.
227      hw_intf_->SetIdleTimeoutMs(0);
228      switch_to_cmd_ = true;
229    }
230  }
231
232  // Request for a new draw cycle. New display mode will get applied on next draw cycle.
233  // New idle time will get configured as part of this.
234  event_handler_->Refresh();
235
236  return error;
237}
238
239DisplayError DisplayPrimary::SetPanelBrightness(int level) {
240  lock_guard<recursive_mutex> obj(recursive_mutex_);
241  return hw_intf_->SetPanelBrightness(level);
242}
243
244DisplayError DisplayPrimary::CachePanelBrightness(int level) {
245  lock_guard<recursive_mutex> obj(recursive_mutex_);
246  return hw_intf_->CachePanelBrightness(level);
247}
248
249DisplayError DisplayPrimary::GetRefreshRateRange(uint32_t *min_refresh_rate,
250                                                 uint32_t *max_refresh_rate) {
251  lock_guard<recursive_mutex> obj(recursive_mutex_);
252  DisplayError error = kErrorNone;
253
254  if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) {
255    *min_refresh_rate = hw_panel_info_.min_fps;
256    *max_refresh_rate = hw_panel_info_.max_fps;
257  } else {
258    error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
259  }
260
261  return error;
262}
263
264DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
265  lock_guard<recursive_mutex> obj(recursive_mutex_);
266
267  if (!active_ || !hw_panel_info_.dynamic_fps) {
268    return kErrorNotSupported;
269  }
270
271  if (refresh_rate < hw_panel_info_.min_fps || refresh_rate > hw_panel_info_.max_fps) {
272    DLOGE("Invalid Fps = %d request", refresh_rate);
273    return kErrorParameters;
274  }
275
276  DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
277  if (error != kErrorNone) {
278    return error;
279  }
280
281  return DisplayBase::ReconfigureDisplay();
282}
283
284DisplayError DisplayPrimary::VSync(int64_t timestamp) {
285  if (vsync_enable_) {
286    DisplayEventVSync vsync;
287    vsync.timestamp = timestamp;
288    event_handler_->VSync(vsync);
289  }
290
291  return kErrorNone;
292}
293
294void DisplayPrimary::IdleTimeout() {
295  event_handler_->Refresh();
296  comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
297  needs_validate_.set();
298}
299
300void DisplayPrimary::PingPongTimeout() {
301  lock_guard<recursive_mutex> obj(recursive_mutex_);
302  hw_intf_->DumpDebugData();
303}
304
305void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
306  lock_guard<recursive_mutex> obj(recursive_mutex_);
307  comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
308  if (thermal_level >= kMaxThermalLevel) {
309    needs_validate_.set();
310  }
311}
312
313void DisplayPrimary::IdlePowerCollapse() {
314  lock_guard<recursive_mutex> obj(recursive_mutex_);
315  comp_manager_->ProcessIdlePowerCollapse(display_comp_ctx_);
316}
317
318DisplayError DisplayPrimary::GetPanelBrightness(int *level) {
319  lock_guard<recursive_mutex> obj(recursive_mutex_);
320  return hw_intf_->GetPanelBrightness(level);
321}
322
323DisplayError DisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
324  lock_guard<recursive_mutex> obj(recursive_mutex_);
325  if (!pending) {
326    return kErrorParameters;
327  }
328
329  if (!hw_panel_info_.partial_update) {
330    // Nothing to be done.
331    DLOGI("partial update is not applicable for display=%d", display_type_);
332    return kErrorNotSupported;
333  }
334
335  *pending = 0;
336  if (enable == partial_update_control_) {
337    DLOGI("Same state transition is requested.");
338    return kErrorNone;
339  }
340
341  partial_update_control_ = enable;
342
343  if (!enable) {
344    // If the request is to turn off feature, new draw call is required to have
345    // the new setting into effect.
346    *pending = 1;
347  }
348
349  return kErrorNone;
350}
351
352DisplayError DisplayPrimary::DisablePartialUpdateOneFrame() {
353  lock_guard<recursive_mutex> obj(recursive_mutex_);
354  disable_pu_one_frame_ = true;
355
356  return kErrorNone;
357}
358
359bool DisplayPrimary::NeedsAVREnable() {
360  if (avr_prop_disabled_) {
361    return false;
362  }
363
364  return (hw_panel_info_.mode == kModeVideo && ((hw_panel_info_.dynamic_fps &&
365          hw_panel_info_.dfps_porch_mode) || (!hw_panel_info_.dynamic_fps &&
366          hw_panel_info_.min_fps != hw_panel_info_.max_fps)));
367}
368
369}  // namespace sdm
370
371