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 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 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 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 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 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 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 160 bool DisplayHDMI::IsUnderscanSupported() { 161 lock_guard<recursive_mutex> obj(recursive_mutex_); 162 return underscan_supported_; 163 } 164 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 170 uint32_t DisplayHDMI::GetBestConfig(HWS3DMode s3d_mode) { 171 uint32_t best_index = 0, index; 172 uint32_t num_modes = 0; 173 174 hw_intf_->GetNumDisplayAttributes(&num_modes); 175 176 // Get display attribute for each mode 177 std::vector<HWDisplayAttributes> attrib(num_modes); 178 for (index = 0; index < num_modes; index++) { 179 hw_intf_->GetDisplayAttributes(index, &attrib[index]); 180 } 181 182 // Select best config for s3d_mode. If s3d is not enabled, s3d_mode is kS3DModeNone 183 for (index = 0; index < num_modes; index ++) { 184 if (attrib[index].s3d_config[s3d_mode]) { 185 break; 186 } 187 } 188 if (index < num_modes) { 189 best_index = UINT32(index); 190 for (size_t index = best_index + 1; index < num_modes; index ++) { 191 if (!attrib[index].s3d_config[s3d_mode]) 192 continue; 193 194 // From the available configs, select the best 195 // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60 196 if (attrib[index].y_pixels > attrib[best_index].y_pixels) { 197 best_index = UINT32(index); 198 } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) { 199 if (attrib[index].x_pixels > attrib[best_index].x_pixels) { 200 best_index = UINT32(index); 201 } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) { 202 if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) { 203 best_index = UINT32(index); 204 } 205 } 206 } 207 } 208 } else { 209 DLOGW("%s, could not support S3D mode from EDID info. S3D mode is %d", 210 __FUNCTION__, s3d_mode); 211 } 212 213 // Used for changing HDMI Resolution - override the best with user set config 214 uint32_t user_config = UINT32(Debug::GetHDMIResolution()); 215 if (user_config) { 216 uint32_t config_index = 0; 217 // For the config, get the corresponding index 218 DisplayError error = hw_intf_->GetConfigIndex(user_config, &config_index); 219 if (error == kErrorNone) 220 return config_index; 221 } 222 223 return best_index; 224 } 225 226 void DisplayHDMI::GetScanSupport() { 227 DisplayError error = kErrorNone; 228 uint32_t video_format = 0; 229 uint32_t max_cea_format = 0; 230 HWScanInfo scan_info = HWScanInfo(); 231 hw_intf_->GetHWScanInfo(&scan_info); 232 233 uint32_t active_mode_index = 0; 234 hw_intf_->GetActiveConfig(&active_mode_index); 235 236 error = hw_intf_->GetVideoFormat(active_mode_index, &video_format); 237 if (error != kErrorNone) { 238 return; 239 } 240 241 error = hw_intf_->GetMaxCEAFormat(&max_cea_format); 242 if (error != kErrorNone) { 243 return; 244 } 245 246 // The scan support for a given HDMI TV must be read from scan info corresponding to 247 // Preferred Timing if the preferred timing of the display is currently active, and if it is 248 // valid. In all other cases, we must read the scan support from CEA scan info if 249 // the resolution is a CEA resolution, or from IT scan info for all other resolutions. 250 if (active_mode_index == 0 && scan_info.pt_scan_support != kScanNotSupported) { 251 scan_support_ = scan_info.pt_scan_support; 252 } else if (video_format < max_cea_format) { 253 scan_support_ = scan_info.cea_scan_support; 254 } else { 255 scan_support_ = scan_info.it_scan_support; 256 } 257 } 258 259 void DisplayHDMI::SetS3DMode(LayerStack *layer_stack) { 260 uint32_t s3d_layer_count = 0; 261 HWS3DMode s3d_mode = kS3DModeNone; 262 uint32_t layer_count = UINT32(layer_stack->layers.size()); 263 264 // S3D mode is supported for the following scenarios: 265 // 1. Layer stack containing only one s3d layer which is not skip 266 // 2. Layer stack containing only one secure layer along with one s3d layer 267 for (uint32_t i = 0; i < layer_count; i++) { 268 Layer *layer = layer_stack->layers.at(i); 269 LayerBuffer *layer_buffer = layer->input_buffer; 270 271 if (layer_buffer->s3d_format != kS3dFormatNone) { 272 s3d_layer_count++; 273 if (s3d_layer_count > 1 || layer->flags.skip) { 274 s3d_mode = kS3DModeNone; 275 break; 276 } 277 278 std::map<LayerBufferS3DFormat, HWS3DMode>::iterator it = 279 s3d_format_to_mode_.find(layer_buffer->s3d_format); 280 if (it != s3d_format_to_mode_.end()) { 281 s3d_mode = it->second; 282 } 283 } else if (layer_buffer->flags.secure && layer_count > 2) { 284 s3d_mode = kS3DModeNone; 285 break; 286 } 287 } 288 289 if (hw_intf_->SetS3DMode(s3d_mode) != kErrorNone) { 290 hw_intf_->SetS3DMode(kS3DModeNone); 291 layer_stack->flags.s3d_mode_present = false; 292 } else if (s3d_mode != kS3DModeNone) { 293 layer_stack->flags.s3d_mode_present = true; 294 } 295 296 DisplayBase::ReconfigureDisplay(); 297 } 298 299 void DisplayHDMI::CECMessage(char *message) { 300 event_handler_->CECMessage(message); 301 } 302 303 DisplayError DisplayHDMI::VSync(int64_t timestamp) { 304 if (vsync_enable_) { 305 DisplayEventVSync vsync; 306 vsync.timestamp = timestamp; 307 event_handler_->VSync(vsync); 308 } 309 310 return kErrorNone; 311 } 312 313 } // namespace sdm 314 315