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 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 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 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 300 void DisplayHDMI::CECMessage(char *message) { 301 event_handler_->CECMessage(message); 302 } 303 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