14a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh/*
24a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
34a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*
44a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* Redistribution and use in source and binary forms, with or without modification, are permitted
54a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* provided that the following conditions are met:
64a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*    * Redistributions of source code must retain the above copyright notice, this list of
74a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*      conditions and the following disclaimer.
84a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*    * Redistributions in binary form must reproduce the above copyright notice, this list of
94a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*      conditions and the following disclaimer in the documentation and/or other materials provided
104a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*      with the distribution.
114a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
124a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*      endorse or promote products derived from this software without specific prior written
134a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*      permission.
144a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*
154a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
164a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
174a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
184a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
194a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
204a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
214a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
224a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
234a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh*/
244a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
254a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <utils/constants.h>
264a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <utils/debug.h>
274a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <map>
284a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <utility>
294a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include <vector>
304a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
314a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include "display_hdmi.h"
324a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include "hw_interface.h"
334a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#include "hw_info_interface.h"
344a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
354a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh#define __CLASS__ "DisplayHDMI"
364a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
374a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanhnamespace sdm {
384a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
394a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
404a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                         BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
414a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                         CompManager *comp_manager)
424a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  : DisplayBase(kHDMI, event_handler, kDeviceHDMI, buffer_sync_handler, buffer_allocator,
434a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                comp_manager, hw_info_intf) {
444a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
454a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
464a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError DisplayHDMI::Init() {
474a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  lock_guard<recursive_mutex> obj(recursive_mutex_);
484a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
494a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError error = HWInterface::Create(kHDMI, hw_info_intf_, buffer_sync_handler_,
504a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                                           buffer_allocator_, &hw_intf_);
514a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (error != kErrorNone) {
524a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    return error;
534a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
544a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
554a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t active_mode_index;
564a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  char value[64] = "0";
574a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  Debug::GetProperty("sdm.hdmi.s3d_mode", value);
584a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  HWS3DMode mode = (HWS3DMode)atoi(value);
594a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (mode > kS3DModeNone && mode < kS3DModeMax) {
604a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    active_mode_index = GetBestConfig(mode);
614a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  } else {
624a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    active_mode_index = GetBestConfig(kS3DModeNone);
634a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
644a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
654a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  error = hw_intf_->SetDisplayAttributes(active_mode_index);
664a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (error != kErrorNone) {
674a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    HWInterface::Destroy(hw_intf_);
684a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
694a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
704a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  error = DisplayBase::Init();
714a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (error != kErrorNone) {
724a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    HWInterface::Destroy(hw_intf_);
734a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    return error;
744a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
754a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
764a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  GetScanSupport();
774a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  underscan_supported_ = (scan_support_ == kScanAlwaysUnderscanned) || (scan_support_ == kScanBoth);
784a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
794a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
804a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                            (kS3dFormatNone, kS3DModeNone));
814a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
824a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                            (kS3dFormatLeftRight, kS3DModeLR));
834a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
844a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                            (kS3dFormatRightLeft, kS3DModeRL));
854a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
864a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                            (kS3dFormatTopBottom, kS3DModeTB));
874a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
884a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                            (kS3dFormatFramePacking, kS3DModeFP));
894a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
904a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  error = HWEventsInterface::Create(INT(display_type_), this, event_list_, &hw_events_intf_);
914a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (error != kErrorNone) {
924a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    DisplayBase::Deinit();
934a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    HWInterface::Destroy(hw_intf_);
944a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    DLOGE("Failed to create hardware events interface. Error = %d", error);
954a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
964a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
974a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return error;
984a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
994a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1004a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) {
1014a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  lock_guard<recursive_mutex> obj(recursive_mutex_);
1024a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError error = kErrorNone;
1034a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t new_mixer_width = 0;
1044a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t new_mixer_height = 0;
1054a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t display_width = display_attributes_.x_pixels;
1064a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t display_height = display_attributes_.y_pixels;
1074a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1084a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
1094a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    error = ReconfigureMixer(new_mixer_width, new_mixer_height);
1104a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    if (error != kErrorNone) {
1114a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      ReconfigureMixer(display_width, display_height);
1124a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    }
1134a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
1144a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1154a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  SetS3DMode(layer_stack);
1164a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1174a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  // Clean hw layers for reuse.
1184a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  hw_layers_ = HWLayers();
1194a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1204a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return DisplayBase::Prepare(layer_stack);
1214a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
1224a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1234a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError DisplayHDMI::GetRefreshRateRange(uint32_t *min_refresh_rate,
1244a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                                              uint32_t *max_refresh_rate) {
1254a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  lock_guard<recursive_mutex> obj(recursive_mutex_);
1264a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError error = kErrorNone;
1274a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1284a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (hw_panel_info_.min_fps && hw_panel_info_.max_fps) {
1294a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    *min_refresh_rate = hw_panel_info_.min_fps;
1304a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    *max_refresh_rate = hw_panel_info_.max_fps;
1314a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  } else {
1324a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    error = DisplayBase::GetRefreshRateRange(min_refresh_rate, max_refresh_rate);
1334a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
1344a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1354a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return error;
1364a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
1374a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1384a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate) {
1394a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  lock_guard<recursive_mutex> obj(recursive_mutex_);
1404a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1414a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (!active_) {
1424a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    return kErrorPermission;
1434a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
1444a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1454a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
1464a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (error != kErrorNone) {
1474a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    return error;
1484a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
1494a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1504a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return DisplayBase::ReconfigureDisplay();
1514a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
1524a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1534a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanhbool DisplayHDMI::IsUnderscanSupported() {
1544a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  lock_guard<recursive_mutex> obj(recursive_mutex_);
1554a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return underscan_supported_;
1564a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
1574a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1584a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError DisplayHDMI::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
1594a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  lock_guard<recursive_mutex> obj(recursive_mutex_);
1604a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return hw_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
1614a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
1624a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1634a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanhuint32_t DisplayHDMI::GetBestConfig(HWS3DMode s3d_mode) {
1644a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t best_index = 0, index;
1654a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t num_modes = 0;
1664a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1674a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  hw_intf_->GetNumDisplayAttributes(&num_modes);
1684a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1694a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  // Get display attribute for each mode
1704a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  std::vector<HWDisplayAttributes> attrib(num_modes);
1714a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  for (index = 0; index < num_modes; index++) {
1724a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    hw_intf_->GetDisplayAttributes(index, &attrib[index]);
1734a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
1744a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1754a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  // Select best config for s3d_mode. If s3d is not enabled, s3d_mode is kS3DModeNone
1764a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  for (index = 0; index < num_modes; index ++) {
1774a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    if (attrib[index].s3d_config[s3d_mode]) {
1784a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      break;
1794a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    }
1804a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
1814a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (index < num_modes) {
1824a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    best_index = UINT32(index);
1834a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    for (size_t index = best_index + 1; index < num_modes; index ++) {
1844a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      if (!attrib[index].s3d_config[s3d_mode])
1854a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        continue;
1864a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
1874a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      // From the available configs, select the best
1884a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
1894a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      if (attrib[index].y_pixels > attrib[best_index].y_pixels) {
1904a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        best_index = UINT32(index);
1914a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) {
1924a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        if (attrib[index].x_pixels > attrib[best_index].x_pixels) {
1934a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh          best_index = UINT32(index);
1944a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) {
1954a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh          if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) {
1964a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh            best_index = UINT32(index);
1974a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh          }
1984a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        }
1994a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      }
2004a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    }
2014a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  } else {
2024a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    DLOGW("%s, could not support S3D mode from EDID info. S3D mode is %d",
2034a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh          __FUNCTION__, s3d_mode);
2044a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
2054a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2064a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  // Used for changing HDMI Resolution - override the best with user set config
2074a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t user_config = UINT32(Debug::GetHDMIResolution());
2084a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (user_config) {
2094a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    uint32_t config_index = 0;
2104a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    // For the config, get the corresponding index
2114a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    DisplayError error = hw_intf_->GetConfigIndex(user_config, &config_index);
2124a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    if (error == kErrorNone)
2134a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      return config_index;
2144a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
2154a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2164a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return best_index;
2174a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
2184a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2194a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanhvoid DisplayHDMI::GetScanSupport() {
2204a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayError error = kErrorNone;
2214a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t video_format = 0;
2224a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t max_cea_format = 0;
2234a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  HWScanInfo scan_info = HWScanInfo();
2244a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  hw_intf_->GetHWScanInfo(&scan_info);
2254a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2264a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t active_mode_index = 0;
2274a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  hw_intf_->GetActiveConfig(&active_mode_index);
2284a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2294a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  error = hw_intf_->GetVideoFormat(active_mode_index, &video_format);
2304a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (error != kErrorNone) {
2314a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    return;
2324a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
2334a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2344a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  error = hw_intf_->GetMaxCEAFormat(&max_cea_format);
2354a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (error != kErrorNone) {
2364a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    return;
2374a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
2384a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2394a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  // The scan support for a given HDMI TV must be read from scan info corresponding to
2404a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  // Preferred Timing if the preferred timing of the display is currently active, and if it is
2414a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  // valid. In all other cases, we must read the scan support from CEA scan info if
2424a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  // the resolution is a CEA resolution, or from IT scan info for all other resolutions.
2434a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (active_mode_index == 0 && scan_info.pt_scan_support != kScanNotSupported) {
2444a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    scan_support_ = scan_info.pt_scan_support;
2454a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  } else if (video_format < max_cea_format) {
2464a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    scan_support_ = scan_info.cea_scan_support;
2474a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  } else {
2484a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    scan_support_ = scan_info.it_scan_support;
2494a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
2504a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
2514a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2524a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanhvoid DisplayHDMI::SetS3DMode(LayerStack *layer_stack) {
2534a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t s3d_layer_count = 0;
2544a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  HWS3DMode s3d_mode = kS3DModeNone;
2554a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  uint32_t layer_count = UINT32(layer_stack->layers.size());
2564a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2574a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  // S3D mode is supported for the following scenarios:
2584a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  // 1. Layer stack containing only one s3d layer which is not skip
2594a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  // 2. Layer stack containing only one secure layer along with one s3d layer
2604a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  for (uint32_t i = 0; i < layer_count; i++) {
2614a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    Layer *layer = layer_stack->layers.at(i);
2624a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    LayerBuffer &layer_buffer = layer->input_buffer;
2634a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2644a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    if (layer_buffer.s3d_format != kS3dFormatNone) {
2654a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      s3d_layer_count++;
2664a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      if (s3d_layer_count > 1 || layer->flags.skip) {
2674a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        s3d_mode = kS3DModeNone;
2684a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        break;
2694a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      }
2704a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2714a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      std::map<LayerBufferS3DFormat, HWS3DMode>::iterator it =
2724a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh                s3d_format_to_mode_.find(layer_buffer.s3d_format);
2734a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      if (it != s3d_format_to_mode_.end()) {
2744a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        s3d_mode = it->second;
2754a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh      }
2764a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    } else if (layer_buffer.flags.secure && layer_count > 2) {
2774a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        s3d_mode = kS3DModeNone;
2784a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh        break;
2794a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    }
2804a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
2814a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2824a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (hw_intf_->SetS3DMode(s3d_mode) != kErrorNone) {
2834a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    hw_intf_->SetS3DMode(kS3DModeNone);
2844a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    layer_stack->flags.s3d_mode_present = false;
2854a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  } else if (s3d_mode != kS3DModeNone) {
2864a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    layer_stack->flags.s3d_mode_present = true;
2874a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
2884a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2894a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  DisplayBase::ReconfigureDisplay();
2904a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
2914a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2924a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain VongsouvanhDisplayError DisplayHDMI::VSync(int64_t timestamp) {
2934a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  if (vsync_enable_) {
2944a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    DisplayEventVSync vsync;
2954a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    vsync.timestamp = timestamp;
2964a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh    event_handler_->VSync(vsync);
2974a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  }
2984a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
2994a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh  return kErrorNone;
3004a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}
3014a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh
3024a1efd0680d2e9b61739e1eaeffd89174d6d2605Alain Vongsouvanh}  // namespace sdm
303