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