• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <map>
28 #include <utility>
29 
30 #include "display_hdmi.h"
31 #include "hw_interface.h"
32 #include "hw_info_interface.h"
33 #include "fb/hw_hdmi.h"
34 
35 #define __CLASS__ "DisplayHDMI"
36 
37 namespace sdm {
38 
DisplayHDMI(DisplayEventHandler * event_handler,HWInfoInterface * hw_info_intf,BufferSyncHandler * buffer_sync_handler,CompManager * comp_manager,RotatorInterface * rotator_intf)39 DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
40                          BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
41                          RotatorInterface *rotator_intf)
42   : DisplayBase(kHDMI, event_handler, kDeviceHDMI, buffer_sync_handler, comp_manager,
43                 rotator_intf, hw_info_intf) {
44 }
45 
Init()46 DisplayError DisplayHDMI::Init() {
47   SCOPE_LOCK(locker_);
48 
49   DisplayError error = HWHDMI::Create(&hw_intf_, hw_info_intf_,
50                                       DisplayBase::buffer_sync_handler_);
51   if (error != kErrorNone) {
52     return error;
53   }
54 
55   uint32_t active_mode_index;
56   char value[64] = "0";
57   Debug::GetProperty("sdm.hdmi.s3d_mode", value);
58   HWS3DMode mode = (HWS3DMode)atoi(value);
59   if (mode > kS3DModeNone && mode < kS3DModeMax) {
60     active_mode_index = GetBestConfig(mode);
61   } else {
62     active_mode_index = GetBestConfig(kS3DModeNone);
63   }
64 
65   error = hw_intf_->SetDisplayAttributes(active_mode_index);
66   if (error != kErrorNone) {
67     HWHDMI::Destroy(hw_intf_);
68   }
69 
70   error = DisplayBase::Init();
71   if (error != kErrorNone) {
72     HWHDMI::Destroy(hw_intf_);
73   }
74 
75   GetScanSupport();
76   underscan_supported_ = (scan_support_ == kScanAlwaysUnderscanned) || (scan_support_ == kScanBoth);
77 
78   s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
79                             (kS3dFormatNone, kS3DModeNone));
80   s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
81                             (kS3dFormatLeftRight, kS3DModeLR));
82   s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
83                             (kS3dFormatRightLeft, kS3DModeRL));
84   s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
85                             (kS3dFormatTopBottom, kS3DModeTB));
86   s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
87                             (kS3dFormatFramePacking, kS3DModeFP));
88   return error;
89 }
90 
Deinit()91 DisplayError DisplayHDMI::Deinit() {
92   SCOPE_LOCK(locker_);
93 
94   DisplayError error = DisplayBase::Deinit();
95   HWHDMI::Destroy(hw_intf_);
96 
97   return error;
98 }
99 
Prepare(LayerStack * layer_stack)100 DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) {
101   SCOPE_LOCK(locker_);
102 
103   SetS3DMode(layer_stack);
104 
105   return DisplayBase::Prepare(layer_stack);
106 }
107 
Commit(LayerStack * layer_stack)108 DisplayError DisplayHDMI::Commit(LayerStack *layer_stack) {
109   SCOPE_LOCK(locker_);
110   return DisplayBase::Commit(layer_stack);
111 }
112 
Flush()113 DisplayError DisplayHDMI::Flush() {
114   SCOPE_LOCK(locker_);
115   return DisplayBase::Flush();
116 }
117 
GetDisplayState(DisplayState * state)118 DisplayError DisplayHDMI::GetDisplayState(DisplayState *state) {
119   SCOPE_LOCK(locker_);
120   return DisplayBase::GetDisplayState(state);
121 }
122 
GetNumVariableInfoConfigs(uint32_t * count)123 DisplayError DisplayHDMI::GetNumVariableInfoConfigs(uint32_t *count) {
124   SCOPE_LOCK(locker_);
125   return DisplayBase::GetNumVariableInfoConfigs(count);
126 }
127 
GetConfig(uint32_t index,DisplayConfigVariableInfo * variable_info)128 DisplayError DisplayHDMI::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
129   SCOPE_LOCK(locker_);
130   return DisplayBase::GetConfig(index, variable_info);
131 }
132 
GetActiveConfig(uint32_t * index)133 DisplayError DisplayHDMI::GetActiveConfig(uint32_t *index) {
134   SCOPE_LOCK(locker_);
135   return DisplayBase::GetActiveConfig(index);
136 }
137 
GetVSyncState(bool * enabled)138 DisplayError DisplayHDMI::GetVSyncState(bool *enabled) {
139   SCOPE_LOCK(locker_);
140   return DisplayBase::GetVSyncState(enabled);
141 }
142 
SetDisplayState(DisplayState state)143 DisplayError DisplayHDMI::SetDisplayState(DisplayState state) {
144   SCOPE_LOCK(locker_);
145   return DisplayBase::SetDisplayState(state);
146 }
147 
SetActiveConfig(DisplayConfigVariableInfo * variable_info)148 DisplayError DisplayHDMI::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
149   SCOPE_LOCK(locker_);
150   return kErrorNotSupported;
151 }
152 
SetActiveConfig(uint32_t index)153 DisplayError DisplayHDMI::SetActiveConfig(uint32_t index) {
154   SCOPE_LOCK(locker_);
155   return DisplayBase::SetActiveConfig(index);
156 }
157 
SetVSyncState(bool enable)158 DisplayError DisplayHDMI::SetVSyncState(bool enable) {
159   SCOPE_LOCK(locker_);
160   return kErrorNotSupported;
161 }
162 
SetIdleTimeoutMs(uint32_t timeout_ms)163 void DisplayHDMI::SetIdleTimeoutMs(uint32_t timeout_ms) { }
164 
SetMaxMixerStages(uint32_t max_mixer_stages)165 DisplayError DisplayHDMI::SetMaxMixerStages(uint32_t max_mixer_stages) {
166   SCOPE_LOCK(locker_);
167   return DisplayBase::SetMaxMixerStages(max_mixer_stages);
168 }
169 
SetDisplayMode(uint32_t mode)170 DisplayError DisplayHDMI::SetDisplayMode(uint32_t mode) {
171   SCOPE_LOCK(locker_);
172   return DisplayBase::SetDisplayMode(mode);
173 }
174 
IsScalingValid(const LayerRect & crop,const LayerRect & dst,bool rotate90)175 DisplayError DisplayHDMI::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
176                                          bool rotate90) {
177   SCOPE_LOCK(locker_);
178   return DisplayBase::IsScalingValid(crop, dst, rotate90);
179 }
180 
GetRefreshRateRange(uint32_t * min_refresh_rate,uint32_t * max_refresh_rate)181 DisplayError DisplayHDMI::GetRefreshRateRange(uint32_t *min_refresh_rate,
182                                               uint32_t *max_refresh_rate) {
183   SCOPE_LOCK(locker_);
184   return DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
185 }
186 
SetRefreshRate(uint32_t refresh_rate)187 DisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate) {
188   SCOPE_LOCK(locker_);
189   return kErrorNotSupported;
190 }
191 
IsUnderscanSupported()192 bool DisplayHDMI::IsUnderscanSupported() {
193   SCOPE_LOCK(locker_);
194   return DisplayBase::IsUnderscanSupported();
195 }
196 
SetPanelBrightness(int level)197 DisplayError DisplayHDMI::SetPanelBrightness(int level) {
198   SCOPE_LOCK(locker_);
199   return DisplayBase::SetPanelBrightness(level);
200 }
201 
OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level)202 DisplayError DisplayHDMI::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
203   SCOPE_LOCK(locker_);
204   return hw_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
205 }
206 
GetBestConfig(HWS3DMode s3d_mode)207 uint32_t DisplayHDMI::GetBestConfig(HWS3DMode s3d_mode) {
208   uint32_t best_index = 0, index;
209   uint32_t num_modes = 0;
210   HWDisplayAttributes best_attrib;
211 
212   hw_intf_->GetNumDisplayAttributes(&num_modes);
213 
214   // Get display attribute for each mode
215   HWDisplayAttributes *attrib = new HWDisplayAttributes[num_modes];
216   for (index = 0; index < num_modes; index++) {
217     hw_intf_->GetDisplayAttributes(index, &attrib[index]);
218   }
219 
220   // Select best config for s3d_mode. If s3d is not enabled, s3d_mode is kS3DModeNone
221   for (index = 0; index < num_modes; index ++) {
222     if (IS_BIT_SET(attrib[index].s3d_config, s3d_mode)) {
223       break;
224     }
225   }
226   if (index < num_modes) {
227     best_index = UINT32(index);
228     for (size_t index = best_index + 1; index < num_modes; index ++) {
229       if (!IS_BIT_SET(attrib[index].s3d_config, s3d_mode))
230         continue;
231 
232       // From the available configs, select the best
233       // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
234       if (attrib[index].y_pixels > attrib[best_index].y_pixels) {
235         best_index = UINT32(index);
236       } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) {
237         if (attrib[index].x_pixels > attrib[best_index].x_pixels) {
238           best_index = UINT32(index);
239         } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) {
240           if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) {
241             best_index = UINT32(index);
242           }
243         }
244       }
245     }
246   } else {
247     DLOGW("%s, could not support S3D mode from EDID info. S3D mode is %d",
248           __FUNCTION__, s3d_mode);
249   }
250   delete[] attrib;
251 
252   // Used for changing HDMI Resolution - override the best with user set config
253   uint32_t user_config = UINT32(Debug::GetHDMIResolution());
254   if (user_config) {
255     uint32_t config_index = 0;
256     // For the config, get the corresponding index
257     DisplayError error = hw_intf_->GetConfigIndex(user_config, &config_index);
258     if (error == kErrorNone)
259       return config_index;
260   }
261 
262   return best_index;
263 }
264 
GetScanSupport()265 void DisplayHDMI::GetScanSupport() {
266   DisplayError error = kErrorNone;
267   uint32_t video_format = 0;
268   uint32_t max_cea_format = 0;
269   HWScanInfo scan_info = HWScanInfo();
270   hw_intf_->GetHWScanInfo(&scan_info);
271 
272   uint32_t active_mode_index = 0;
273   hw_intf_->GetActiveConfig(&active_mode_index);
274 
275   error = hw_intf_->GetVideoFormat(active_mode_index, &video_format);
276   if (error != kErrorNone) {
277     return;
278   }
279 
280   error = hw_intf_->GetMaxCEAFormat(&max_cea_format);
281   if (error != kErrorNone) {
282     return;
283   }
284 
285   // The scan support for a given HDMI TV must be read from scan info corresponding to
286   // Preferred Timing if the preferred timing of the display is currently active, and if it is
287   // valid. In all other cases, we must read the scan support from CEA scan info if
288   // the resolution is a CEA resolution, or from IT scan info for all other resolutions.
289   if (active_mode_index == 0 && scan_info.pt_scan_support != kScanNotSupported) {
290     scan_support_ = scan_info.pt_scan_support;
291   } else if (video_format < max_cea_format) {
292     scan_support_ = scan_info.cea_scan_support;
293   } else {
294     scan_support_ = scan_info.it_scan_support;
295   }
296 }
297 
AppendDump(char * buffer,uint32_t length)298 void DisplayHDMI::AppendDump(char *buffer, uint32_t length) {
299   SCOPE_LOCK(locker_);
300   DisplayBase::AppendDump(buffer, length);
301 }
302 
SetCursorPosition(int x,int y)303 DisplayError DisplayHDMI::SetCursorPosition(int x, int y) {
304   SCOPE_LOCK(locker_);
305   return DisplayBase::SetCursorPosition(x, y);
306 }
307 
SetS3DMode(LayerStack * layer_stack)308 void DisplayHDMI::SetS3DMode(LayerStack *layer_stack) {
309   uint32_t s3d_layer_count = 0;
310   HWS3DMode s3d_mode = kS3DModeNone;
311   HWPanelInfo panel_info;
312   HWDisplayAttributes display_attributes;
313   uint32_t active_index = 0;
314   uint32_t layer_count = layer_stack->layer_count;
315 
316   // S3D mode is supported for the following scenarios:
317   // 1. Layer stack containing only one s3d layer which is not skip
318   // 2. Layer stack containing only one secure layer along with one s3d layer
319   for (uint32_t i = 0; i < layer_count; i++) {
320     Layer &layer = layer_stack->layers[i];
321     LayerBuffer *layer_buffer = layer.input_buffer;
322 
323     if (layer_buffer->s3d_format != kS3dFormatNone) {
324       s3d_layer_count++;
325       if (s3d_layer_count > 1 || layer.flags.skip) {
326         s3d_mode = kS3DModeNone;
327         break;
328       }
329 
330       std::map<LayerBufferS3DFormat, HWS3DMode>::iterator it =
331                 s3d_format_to_mode_.find(layer_buffer->s3d_format);
332       if (it != s3d_format_to_mode_.end()) {
333         s3d_mode = it->second;
334       }
335     } else if (layer_buffer->flags.secure && layer_count > 2) {
336         s3d_mode = kS3DModeNone;
337         break;
338     }
339   }
340 
341   if (hw_intf_->SetS3DMode(s3d_mode) != kErrorNone) {
342     hw_intf_->SetS3DMode(kS3DModeNone);
343     layer_stack->flags.s3d_mode_present = false;
344   } else if (s3d_mode != kS3DModeNone) {
345     layer_stack->flags.s3d_mode_present = true;
346   }
347 
348   hw_intf_->GetHWPanelInfo(&panel_info);
349   hw_intf_->GetActiveConfig(&active_index);
350   hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
351 
352   if (panel_info != hw_panel_info_) {
353     comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
354     hw_panel_info_ = panel_info;
355   }
356 }
357 
358 }  // namespace sdm
359 
360