Home | History | Annotate | Download | only in core
      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