• 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 #include <vector>
30 
31 #include "display_hdmi.h"
32 #include "hw_interface.h"
33 #include "hw_info_interface.h"
34 #include "fb/hw_hdmi.h"
35 
36 #define __CLASS__ "DisplayHDMI"
37 
38 namespace sdm {
39 
DisplayHDMI(DisplayEventHandler * event_handler,HWInfoInterface * hw_info_intf,BufferSyncHandler * buffer_sync_handler,CompManager * comp_manager,RotatorInterface * rotator_intf)40 DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
41                          BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
42                          RotatorInterface *rotator_intf)
43   : DisplayBase(kHDMI, event_handler, kDeviceHDMI, buffer_sync_handler, comp_manager,
44                 rotator_intf, hw_info_intf) {
45 }
46 
Init()47 DisplayError DisplayHDMI::Init() {
48   lock_guard<recursive_mutex> obj(recursive_mutex_);
49 
50   DisplayError error = HWHDMI::Create(&hw_intf_, hw_info_intf_,
51                                       DisplayBase::buffer_sync_handler_);
52   if (error != kErrorNone) {
53     return error;
54   }
55 
56   uint32_t active_mode_index;
57   char value[64] = "0";
58   Debug::GetProperty("sdm.hdmi.s3d_mode", value);
59   HWS3DMode mode = (HWS3DMode)atoi(value);
60   if (mode > kS3DModeNone && mode < kS3DModeMax) {
61     active_mode_index = GetBestConfig(mode);
62   } else {
63     active_mode_index = GetBestConfig(kS3DModeNone);
64   }
65 
66   error = hw_intf_->SetDisplayAttributes(active_mode_index);
67   if (error != kErrorNone) {
68     HWHDMI::Destroy(hw_intf_);
69   }
70 
71   error = DisplayBase::Init();
72   if (error != kErrorNone) {
73     HWHDMI::Destroy(hw_intf_);
74     return error;
75   }
76 
77   GetScanSupport();
78   underscan_supported_ = (scan_support_ == kScanAlwaysUnderscanned) || (scan_support_ == kScanBoth);
79 
80   s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
81                             (kS3dFormatNone, kS3DModeNone));
82   s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
83                             (kS3dFormatLeftRight, kS3DModeLR));
84   s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
85                             (kS3dFormatRightLeft, kS3DModeRL));
86   s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
87                             (kS3dFormatTopBottom, kS3DModeTB));
88   s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
89                             (kS3dFormatFramePacking, kS3DModeFP));
90 
91   error = HWEventsInterface::Create(INT(display_type_), this, &event_list_, &hw_events_intf_);
92   if (error != kErrorNone) {
93     DisplayBase::Deinit();
94     HWHDMI::Destroy(hw_intf_);
95     DLOGE("Failed to create hardware events interface. Error = %d", error);
96   }
97 
98   return error;
99 }
100 
Deinit()101 DisplayError DisplayHDMI::Deinit() {
102   lock_guard<recursive_mutex> obj(recursive_mutex_);
103 
104   DisplayError error = DisplayBase::Deinit();
105   HWHDMI::Destroy(hw_intf_);
106 
107   return error;
108 }
109 
Prepare(LayerStack * layer_stack)110 DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) {
111   lock_guard<recursive_mutex> obj(recursive_mutex_);
112   DisplayError error = kErrorNone;
113   uint32_t new_mixer_width = 0;
114   uint32_t new_mixer_height = 0;
115   uint32_t display_width = display_attributes_.x_pixels;
116   uint32_t display_height = display_attributes_.y_pixels;
117 
118   if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
119     error = ReconfigureMixer(new_mixer_width, new_mixer_height);
120     if (error != kErrorNone) {
121       ReconfigureMixer(display_width, display_height);
122     }
123   }
124 
125   SetS3DMode(layer_stack);
126 
127   return DisplayBase::Prepare(layer_stack);
128 }
129 
GetRefreshRateRange(uint32_t * min_refresh_rate,uint32_t * max_refresh_rate)130 DisplayError DisplayHDMI::GetRefreshRateRange(uint32_t *min_refresh_rate,
131                                               uint32_t *max_refresh_rate) {
132   lock_guard<recursive_mutex> obj(recursive_mutex_);
133   DisplayError error = kErrorNone;
134 
135   if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) {
136     *min_refresh_rate = hw_panel_info_.min_fps;
137     *max_refresh_rate = hw_panel_info_.max_fps;
138   } else {
139     error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
140   }
141 
142   return error;
143 }
144 
SetRefreshRate(uint32_t refresh_rate)145 DisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate) {
146   lock_guard<recursive_mutex> obj(recursive_mutex_);
147 
148   if (!active_) {
149     return kErrorPermission;
150   }
151 
152   DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
153   if (error != kErrorNone) {
154     return error;
155   }
156 
157   return kErrorNone;
158 }
159 
IsUnderscanSupported()160 bool DisplayHDMI::IsUnderscanSupported() {
161   lock_guard<recursive_mutex> obj(recursive_mutex_);
162   return underscan_supported_;
163 }
164 
OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level)165 DisplayError DisplayHDMI::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
166   lock_guard<recursive_mutex> obj(recursive_mutex_);
167   return hw_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
168 }
169 
GetBestConfig(HWS3DMode s3d_mode)170 uint32_t DisplayHDMI::GetBestConfig(HWS3DMode s3d_mode) {
171   uint32_t best_index = 0, index;
172   uint32_t num_modes = 0;
173   HWDisplayAttributes best_attrib;
174 
175   hw_intf_->GetNumDisplayAttributes(&num_modes);
176 
177   // Get display attribute for each mode
178   std::vector<HWDisplayAttributes> attrib(num_modes);
179   for (index = 0; index < num_modes; index++) {
180     hw_intf_->GetDisplayAttributes(index, &attrib[index]);
181   }
182 
183   // Select best config for s3d_mode. If s3d is not enabled, s3d_mode is kS3DModeNone
184   for (index = 0; index < num_modes; index ++) {
185     if (attrib[index].s3d_config[s3d_mode]) {
186       break;
187     }
188   }
189   if (index < num_modes) {
190     best_index = UINT32(index);
191     for (size_t index = best_index + 1; index < num_modes; index ++) {
192       if (!attrib[index].s3d_config[s3d_mode])
193         continue;
194 
195       // From the available configs, select the best
196       // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
197       if (attrib[index].y_pixels > attrib[best_index].y_pixels) {
198         best_index = UINT32(index);
199       } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) {
200         if (attrib[index].x_pixels > attrib[best_index].x_pixels) {
201           best_index = UINT32(index);
202         } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) {
203           if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) {
204             best_index = UINT32(index);
205           }
206         }
207       }
208     }
209   } else {
210     DLOGW("%s, could not support S3D mode from EDID info. S3D mode is %d",
211           __FUNCTION__, s3d_mode);
212   }
213 
214   // Used for changing HDMI Resolution - override the best with user set config
215   uint32_t user_config = UINT32(Debug::GetHDMIResolution());
216   if (user_config) {
217     uint32_t config_index = 0;
218     // For the config, get the corresponding index
219     DisplayError error = hw_intf_->GetConfigIndex(user_config, &config_index);
220     if (error == kErrorNone)
221       return config_index;
222   }
223 
224   return best_index;
225 }
226 
GetScanSupport()227 void DisplayHDMI::GetScanSupport() {
228   DisplayError error = kErrorNone;
229   uint32_t video_format = 0;
230   uint32_t max_cea_format = 0;
231   HWScanInfo scan_info = HWScanInfo();
232   hw_intf_->GetHWScanInfo(&scan_info);
233 
234   uint32_t active_mode_index = 0;
235   hw_intf_->GetActiveConfig(&active_mode_index);
236 
237   error = hw_intf_->GetVideoFormat(active_mode_index, &video_format);
238   if (error != kErrorNone) {
239     return;
240   }
241 
242   error = hw_intf_->GetMaxCEAFormat(&max_cea_format);
243   if (error != kErrorNone) {
244     return;
245   }
246 
247   // The scan support for a given HDMI TV must be read from scan info corresponding to
248   // Preferred Timing if the preferred timing of the display is currently active, and if it is
249   // valid. In all other cases, we must read the scan support from CEA scan info if
250   // the resolution is a CEA resolution, or from IT scan info for all other resolutions.
251   if (active_mode_index == 0 && scan_info.pt_scan_support != kScanNotSupported) {
252     scan_support_ = scan_info.pt_scan_support;
253   } else if (video_format < max_cea_format) {
254     scan_support_ = scan_info.cea_scan_support;
255   } else {
256     scan_support_ = scan_info.it_scan_support;
257   }
258 }
259 
SetS3DMode(LayerStack * layer_stack)260 void DisplayHDMI::SetS3DMode(LayerStack *layer_stack) {
261   uint32_t s3d_layer_count = 0;
262   HWS3DMode s3d_mode = kS3DModeNone;
263   uint32_t layer_count = UINT32(layer_stack->layers.size());
264 
265   // S3D mode is supported for the following scenarios:
266   // 1. Layer stack containing only one s3d layer which is not skip
267   // 2. Layer stack containing only one secure layer along with one s3d layer
268   for (uint32_t i = 0; i < layer_count; i++) {
269     Layer *layer = layer_stack->layers.at(i);
270     LayerBuffer *layer_buffer = layer->input_buffer;
271 
272     if (layer_buffer->s3d_format != kS3dFormatNone) {
273       s3d_layer_count++;
274       if (s3d_layer_count > 1 || layer->flags.skip) {
275         s3d_mode = kS3DModeNone;
276         break;
277       }
278 
279       std::map<LayerBufferS3DFormat, HWS3DMode>::iterator it =
280                 s3d_format_to_mode_.find(layer_buffer->s3d_format);
281       if (it != s3d_format_to_mode_.end()) {
282         s3d_mode = it->second;
283       }
284     } else if (layer_buffer->flags.secure && layer_count > 2) {
285         s3d_mode = kS3DModeNone;
286         break;
287     }
288   }
289 
290   if (hw_intf_->SetS3DMode(s3d_mode) != kErrorNone) {
291     hw_intf_->SetS3DMode(kS3DModeNone);
292     layer_stack->flags.s3d_mode_present = false;
293   } else if (s3d_mode != kS3DModeNone) {
294     layer_stack->flags.s3d_mode_present = true;
295   }
296 
297   DisplayBase::ReconfigureDisplay();
298 }
299 
CECMessage(char * message)300 void DisplayHDMI::CECMessage(char *message) {
301   event_handler_->CECMessage(message);
302 }
303 
VSync(int64_t timestamp)304 DisplayError DisplayHDMI::VSync(int64_t timestamp) {
305   if (vsync_enable_) {
306     DisplayEventVSync vsync;
307     vsync.timestamp = timestamp;
308     event_handler_->VSync(vsync);
309   }
310 
311   return kErrorNone;
312 }
313 
314 }  // namespace sdm
315 
316