1 /* 2 * Copyright (c) 2014 - 2018, 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(HDMI_S3D_MODE_PROP, 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 return error; 98 } 99 100 DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) { 101 lock_guard<recursive_mutex> obj(recursive_mutex_); 102 DisplayError error = kErrorNone; 103 uint32_t new_mixer_width = 0; 104 uint32_t new_mixer_height = 0; 105 uint32_t display_width = display_attributes_.x_pixels; 106 uint32_t display_height = display_attributes_.y_pixels; 107 108 if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) { 109 error = ReconfigureMixer(new_mixer_width, new_mixer_height); 110 if (error != kErrorNone) { 111 ReconfigureMixer(display_width, display_height); 112 } 113 } 114 115 SetS3DMode(layer_stack); 116 117 // Clean hw layers for reuse. 118 hw_layers_ = HWLayers(); 119 120 return DisplayBase::Prepare(layer_stack); 121 } 122 123 DisplayError DisplayHDMI::GetRefreshRateRange(uint32_t *min_refresh_rate, 124 uint32_t *max_refresh_rate) { 125 lock_guard<recursive_mutex> obj(recursive_mutex_); 126 DisplayError error = kErrorNone; 127 128 if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) { 129 *min_refresh_rate = hw_panel_info_.min_fps; 130 *max_refresh_rate = hw_panel_info_.max_fps; 131 } else { 132 error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate); 133 } 134 135 return error; 136 } 137 138 DisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate) { 139 lock_guard<recursive_mutex> obj(recursive_mutex_); 140 141 if (!active_) { 142 return kErrorPermission; 143 } 144 145 DisplayError error = hw_intf_->SetRefreshRate(refresh_rate); 146 if (error != kErrorNone) { 147 return error; 148 } 149 150 return DisplayBase::ReconfigureDisplay(); 151 } 152 153 bool DisplayHDMI::IsUnderscanSupported() { 154 lock_guard<recursive_mutex> obj(recursive_mutex_); 155 return underscan_supported_; 156 } 157 158 DisplayError DisplayHDMI::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) { 159 lock_guard<recursive_mutex> obj(recursive_mutex_); 160 return hw_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level); 161 } 162 163 uint32_t DisplayHDMI::GetBestConfig(HWS3DMode s3d_mode) { 164 uint32_t best_index = 0, index; 165 uint32_t num_modes = 0; 166 167 hw_intf_->GetNumDisplayAttributes(&num_modes); 168 169 // Get display attribute for each mode 170 std::vector<HWDisplayAttributes> attrib(num_modes); 171 for (index = 0; index < num_modes; index++) { 172 hw_intf_->GetDisplayAttributes(index, &attrib[index]); 173 } 174 175 // Select best config for s3d_mode. If s3d is not enabled, s3d_mode is kS3DModeNone 176 for (index = 0; index < num_modes; index ++) { 177 if (attrib[index].s3d_config[s3d_mode]) { 178 break; 179 } 180 } 181 if (index < num_modes) { 182 best_index = UINT32(index); 183 for (size_t index = best_index + 1; index < num_modes; index ++) { 184 if (!attrib[index].s3d_config[s3d_mode]) 185 continue; 186 187 // From the available configs, select the best 188 // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60 189 if (attrib[index].y_pixels > attrib[best_index].y_pixels) { 190 best_index = UINT32(index); 191 } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) { 192 if (attrib[index].x_pixels > attrib[best_index].x_pixels) { 193 best_index = UINT32(index); 194 } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) { 195 if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) { 196 best_index = UINT32(index); 197 } 198 } 199 } 200 } 201 } else { 202 DLOGW("%s, could not support S3D mode from EDID info. S3D mode is %d", 203 __FUNCTION__, s3d_mode); 204 } 205 206 // Used for changing HDMI Resolution - override the best with user set config 207 uint32_t user_config = UINT32(Debug::GetHDMIResolution()); 208 if (user_config) { 209 uint32_t config_index = 0; 210 // For the config, get the corresponding index 211 DisplayError error = hw_intf_->GetConfigIndex(user_config, &config_index); 212 if (error == kErrorNone) 213 return config_index; 214 } 215 216 return best_index; 217 } 218 219 void DisplayHDMI::GetScanSupport() { 220 DisplayError error = kErrorNone; 221 uint32_t video_format = 0; 222 uint32_t max_cea_format = 0; 223 HWScanInfo scan_info = HWScanInfo(); 224 hw_intf_->GetHWScanInfo(&scan_info); 225 226 uint32_t active_mode_index = 0; 227 hw_intf_->GetActiveConfig(&active_mode_index); 228 229 error = hw_intf_->GetVideoFormat(active_mode_index, &video_format); 230 if (error != kErrorNone) { 231 return; 232 } 233 234 error = hw_intf_->GetMaxCEAFormat(&max_cea_format); 235 if (error != kErrorNone) { 236 return; 237 } 238 239 // The scan support for a given HDMI TV must be read from scan info corresponding to 240 // Preferred Timing if the preferred timing of the display is currently active, and if it is 241 // valid. In all other cases, we must read the scan support from CEA scan info if 242 // the resolution is a CEA resolution, or from IT scan info for all other resolutions. 243 if (active_mode_index == 0 && scan_info.pt_scan_support != kScanNotSupported) { 244 scan_support_ = scan_info.pt_scan_support; 245 } else if (video_format < max_cea_format) { 246 scan_support_ = scan_info.cea_scan_support; 247 } else { 248 scan_support_ = scan_info.it_scan_support; 249 } 250 } 251 252 void DisplayHDMI::SetS3DMode(LayerStack *layer_stack) { 253 uint32_t s3d_layer_count = 0; 254 HWS3DMode s3d_mode = kS3DModeNone; 255 uint32_t layer_count = UINT32(layer_stack->layers.size()); 256 257 // S3D mode is supported for the following scenarios: 258 // 1. Layer stack containing only one s3d layer which is not skip 259 // 2. Layer stack containing only one secure layer along with one s3d layer 260 for (uint32_t i = 0; i < layer_count; i++) { 261 Layer *layer = layer_stack->layers.at(i); 262 LayerBuffer &layer_buffer = layer->input_buffer; 263 264 if (layer_buffer.s3d_format != kS3dFormatNone) { 265 s3d_layer_count++; 266 if (s3d_layer_count > 1 || layer->flags.skip) { 267 s3d_mode = kS3DModeNone; 268 break; 269 } 270 271 std::map<LayerBufferS3DFormat, HWS3DMode>::iterator it = 272 s3d_format_to_mode_.find(layer_buffer.s3d_format); 273 if (it != s3d_format_to_mode_.end()) { 274 s3d_mode = it->second; 275 } 276 } else if (layer_buffer.flags.secure && layer_count > 2) { 277 s3d_mode = kS3DModeNone; 278 break; 279 } 280 } 281 282 if (hw_intf_->SetS3DMode(s3d_mode) != kErrorNone) { 283 hw_intf_->SetS3DMode(kS3DModeNone); 284 layer_stack->flags.s3d_mode_present = false; 285 } else if (s3d_mode != kS3DModeNone) { 286 layer_stack->flags.s3d_mode_present = true; 287 } 288 289 DisplayBase::ReconfigureDisplay(); 290 } 291 292 DisplayError DisplayHDMI::VSync(int64_t timestamp) { 293 if (vsync_enable_) { 294 DisplayEventVSync vsync; 295 vsync.timestamp = timestamp; 296 event_handler_->VSync(vsync); 297 } 298 299 return kErrorNone; 300 } 301 302 } // namespace sdm 303 304