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