Home | History | Annotate | Download | only in libexternal
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
      4  *
      5  * Not a Contribution, Apache license notifications and license are
      6  * retained for attribution purposes only.
      7  *
      8  * Licensed under the Apache License, Version 2.0 (the "License");
      9  * you may not use this file except in compliance with the License.
     10  * You may obtain a copy of the License at
     11  *
     12  *      http://www.apache.org/licenses/LICENSE-2.0
     13  *
     14  * Unless required by applicable law or agreed to in writing, software
     15  * distributed under the License is distributed on an "AS IS" BASIS,
     16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     17  * See the License for the specific language governing permissions and
     18  * limitations under the License.
     19  */
     20 
     21 #define DEBUG 0
     22 #include <ctype.h>
     23 #include <fcntl.h>
     24 #include <utils/threads.h>
     25 #include <utils/Errors.h>
     26 #include <utils/Log.h>
     27 
     28 #include <linux/msm_mdp.h>
     29 #include <video/msm_hdmi_modes.h>
     30 #include <linux/fb.h>
     31 #include <sys/ioctl.h>
     32 #include <cutils/properties.h>
     33 #include "hwc_utils.h"
     34 #include "external.h"
     35 #include "overlayUtils.h"
     36 #include "overlay.h"
     37 #include "mdp_version.h"
     38 #include "qd_utils.h"
     39 
     40 using namespace android;
     41 
     42 namespace qhwc {
     43 #define MAX_SYSFS_FILE_PATH             255
     44 #define UNKNOWN_STRING                  "unknown"
     45 #define SPD_NAME_LENGTH                 16
     46 /* Max. resolution assignable to when downscale */
     47 #define SUPPORTED_DOWNSCALE_EXT_AREA    (1920*1080)
     48 
     49 
     50 int ExternalDisplay::configure() {
     51     if(!openFrameBuffer()) {
     52         ALOGE("%s: Failed to open FB: %d", __FUNCTION__, mFbNum);
     53         return -1;
     54     }
     55     readCEUnderscanInfo();
     56     readResolution();
     57     // TODO: Move this to activate
     58     /* Used for changing the resolution
     59      * getUserMode will get the preferred
     60      * mode set thru adb shell */
     61     int mode = getUserMode();
     62     if (mode == -1) {
     63         //Get the best mode and set
     64         mode = getBestMode();
     65     }
     66     setResolution(mode);
     67     setAttributes();
     68     // set system property
     69     property_set("hw.hdmiON", "1");
     70     return 0;
     71 }
     72 
     73 void ExternalDisplay::getAttributes(int& width, int& height) {
     74     int fps = 0;
     75     getAttrForMode(width, height, fps);
     76 }
     77 
     78 int ExternalDisplay::teardown() {
     79     closeFrameBuffer();
     80     resetInfo();
     81     // unset system property
     82     property_set("hw.hdmiON", "0");
     83     return 0;
     84 }
     85 
     86 ExternalDisplay::ExternalDisplay(hwc_context_t* ctx):mFd(-1),
     87     mCurrentMode(-1), mModeCount(0),
     88     mUnderscanSupported(false), mHwcContext(ctx)
     89 {
     90     memset(&mVInfo, 0, sizeof(mVInfo));
     91     mFbNum = overlay::Overlay::getInstance()->getFbForDpy(HWC_DISPLAY_EXTERNAL);
     92     // disable HPD at start, it will be enabled later
     93     // when the display powers on
     94     // This helps for framework reboot or adb shell stop/start
     95     writeHPDOption(0);
     96 
     97     // for HDMI - retreive all the modes supported by the driver
     98     if(mFbNum != -1) {
     99         supported_video_mode_lut =
    100                         new msm_hdmi_mode_timing_info[HDMI_VFRMT_MAX];
    101         // Populate the mode table for supported modes
    102         MSM_HDMI_MODES_INIT_TIMINGS(supported_video_mode_lut);
    103         MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_mode_lut,
    104                                         MSM_HDMI_MODES_ALL);
    105         // Update the Source Product Information
    106         // Vendor Name
    107         setSPDInfo("vendor_name", "ro.product.manufacturer");
    108         // Product Description
    109         setSPDInfo("product_description", "ro.product.name");
    110     }
    111 }
    112 /* gets the product manufacturer and product name and writes it
    113  * to the sysfs node, so that the driver can get that information
    114  * Used to show QCOM 8974 instead of Input 1 for example
    115  */
    116 void ExternalDisplay::setSPDInfo(const char* node, const char* property) {
    117     ssize_t err = -1;
    118     char info[PROPERTY_VALUE_MAX];
    119     char sysFsSPDFilePath[MAX_SYSFS_FILE_PATH];
    120     memset(sysFsSPDFilePath, 0, sizeof(sysFsSPDFilePath));
    121     snprintf(sysFsSPDFilePath , sizeof(sysFsSPDFilePath),
    122                  "/sys/devices/virtual/graphics/fb%d/%s",
    123                  mFbNum, node);
    124     int spdFile = open(sysFsSPDFilePath, O_RDWR, 0);
    125     if (spdFile < 0) {
    126         ALOGE("%s: file '%s' not found : ret = %d"
    127               "err str: %s",  __FUNCTION__, sysFsSPDFilePath,
    128               spdFile, strerror(errno));
    129     } else {
    130         memset(info, 0, sizeof(info));
    131         property_get(property, info, UNKNOWN_STRING);
    132         ALOGD_IF(DEBUG, "In %s: %s = %s", __FUNCTION__, property, info);
    133         if (strncmp(info, UNKNOWN_STRING, SPD_NAME_LENGTH)) {
    134             err = write(spdFile, info, strlen(info));
    135             if (err <= 0) {
    136                 ALOGE("%s: file write failed for '%s'"
    137                       "err no = %d", __FUNCTION__, sysFsSPDFilePath, errno);
    138             }
    139         } else {
    140             ALOGD_IF(DEBUG, "%s: property_get failed for SPD %s",
    141                          __FUNCTION__, node);
    142         }
    143         close(spdFile);
    144     }
    145 }
    146 
    147 void ExternalDisplay::setHPD(uint32_t startEnd) {
    148     ALOGD_IF(DEBUG,"HPD enabled=%d", startEnd);
    149     writeHPDOption(startEnd);
    150 }
    151 
    152 void ExternalDisplay::setActionSafeDimension(int w, int h) {
    153     ALOGD_IF(DEBUG,"ActionSafe w=%d h=%d", w, h);
    154     char actionsafeWidth[PROPERTY_VALUE_MAX];
    155     char actionsafeHeight[PROPERTY_VALUE_MAX];
    156     snprintf(actionsafeWidth, sizeof(actionsafeWidth), "%d", w);
    157     property_set("persist.sys.actionsafe.width", actionsafeWidth);
    158     snprintf(actionsafeHeight, sizeof(actionsafeHeight), "%d", h);
    159     property_set("persist.sys.actionsafe.height", actionsafeHeight);
    160 }
    161 
    162 int ExternalDisplay::getModeCount() const {
    163     ALOGD_IF(DEBUG,"HPD mModeCount=%d", mModeCount);
    164     return mModeCount;
    165 }
    166 
    167 void ExternalDisplay::getEDIDModes(int *out) const {
    168     for(int i = 0;i < mModeCount;i++) {
    169         out[i] = mEDIDModes[i];
    170     }
    171 }
    172 
    173 void ExternalDisplay::readCEUnderscanInfo()
    174 {
    175     int hdmiScanInfoFile = -1;
    176     ssize_t len = -1;
    177     char scanInfo[17];
    178     char *ce_info_str = NULL;
    179     char *save_ptr;
    180     const char token[] = ", \n";
    181     int ce_info = -1;
    182     char sysFsScanInfoFilePath[MAX_SYSFS_FILE_PATH];
    183     snprintf(sysFsScanInfoFilePath, sizeof(sysFsScanInfoFilePath),
    184             "/sys/devices/virtual/graphics/fb%d/"
    185                                    "scan_info", mFbNum);
    186 
    187     memset(scanInfo, 0, sizeof(scanInfo));
    188     hdmiScanInfoFile = open(sysFsScanInfoFilePath, O_RDONLY, 0);
    189     if (hdmiScanInfoFile < 0) {
    190         ALOGD_IF(DEBUG, "%s: scan_info file '%s' not found",
    191                                 __FUNCTION__, sysFsScanInfoFilePath);
    192         return;
    193     } else {
    194         len = read(hdmiScanInfoFile, scanInfo, sizeof(scanInfo)-1);
    195         ALOGD("%s: Scan Info string: %s length = %zu",
    196                  __FUNCTION__, scanInfo, len);
    197         if (len <= 0) {
    198             close(hdmiScanInfoFile);
    199             ALOGE("%s: Scan Info file empty '%s'",
    200                                 __FUNCTION__, sysFsScanInfoFilePath);
    201             return;
    202         }
    203         scanInfo[len] = '\0';  /* null terminate the string */
    204         close(hdmiScanInfoFile);
    205     }
    206 
    207     /*
    208      * The scan_info contains the three fields
    209      * PT - preferred video format
    210      * IT - video format
    211      * CE video format - containing the underscan support information
    212      */
    213 
    214     /* PT */
    215     ce_info_str = strtok_r(scanInfo, token, &save_ptr);
    216     if (ce_info_str) {
    217         /* IT */
    218         ce_info_str = strtok_r(NULL, token, &save_ptr);
    219         if (ce_info_str) {
    220             /* CE */
    221             ce_info_str = strtok_r(NULL, token, &save_ptr);
    222             if (ce_info_str)
    223                 ce_info = atoi(ce_info_str);
    224         }
    225     }
    226 
    227     if (ce_info_str) {
    228         // ce_info contains the underscan information
    229         if (ce_info == EXT_SCAN_ALWAYS_UNDERSCANED ||
    230             ce_info == EXT_SCAN_BOTH_SUPPORTED)
    231             // if TV supported underscan, then driver will always underscan
    232             // hence no need to apply action safe rectangle
    233             mUnderscanSupported = true;
    234     } else {
    235         ALOGE("%s: scan_info string error", __FUNCTION__);
    236     }
    237 
    238     // Store underscan support info in a system property
    239     const char* prop = (mUnderscanSupported) ? "1" : "0";
    240     property_set("hw.underscan_supported", prop);
    241     return;
    242 }
    243 
    244 ExternalDisplay::~ExternalDisplay()
    245 {
    246     delete [] supported_video_mode_lut;
    247     closeFrameBuffer();
    248 }
    249 
    250 /*
    251  * sets the fb_var_screeninfo from the hdmi_mode_timing_info
    252  */
    253 void setDisplayTiming(struct fb_var_screeninfo &info,
    254                                 const msm_hdmi_mode_timing_info* mode)
    255 {
    256     info.reserved[0] = 0;
    257     info.reserved[1] = 0;
    258     info.reserved[2] = 0;
    259 #ifndef FB_METADATA_VIDEO_INFO_CODE_SUPPORT
    260     info.reserved[3] = (info.reserved[3] & 0xFFFF) |
    261               (mode->video_format << 16);
    262 #endif
    263     info.xoffset = 0;
    264     info.yoffset = 0;
    265     info.xres = mode->active_h;
    266     info.yres = mode->active_v;
    267 
    268     info.pixclock = (mode->pixel_freq)*1000;
    269     info.vmode = mode->interlaced ?
    270                     FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
    271 
    272     info.right_margin = mode->front_porch_h;
    273     info.hsync_len = mode->pulse_width_h;
    274     info.left_margin = mode->back_porch_h;
    275     info.lower_margin = mode->front_porch_v;
    276     info.vsync_len = mode->pulse_width_v;
    277     info.upper_margin = mode->back_porch_v;
    278 }
    279 
    280 int ExternalDisplay::parseResolution(char* edidStr, int* edidModes)
    281 {
    282     char delim = ',';
    283     int count = 0;
    284     char *start, *end;
    285     // EDIDs are string delimited by ','
    286     // Ex: 16,4,5,3,32,34,1
    287     // Parse this string to get mode(int)
    288     start = (char*) edidStr;
    289     end = &delim;
    290     while(*end == delim) {
    291         edidModes[count] = (int) strtol(start, &end, 10);
    292         start = end+1;
    293         count++;
    294     }
    295     ALOGD_IF(DEBUG, "In %s: count = %d", __FUNCTION__, count);
    296     for (int i = 0; i < count; i++)
    297         ALOGD_IF(DEBUG, "Mode[%d] = %d", i, edidModes[i]);
    298     return count;
    299 }
    300 
    301 bool ExternalDisplay::readResolution()
    302 {
    303     char sysFsEDIDFilePath[MAX_SYSFS_FILE_PATH];
    304     snprintf(sysFsEDIDFilePath , sizeof(sysFsEDIDFilePath),
    305             "/sys/devices/virtual/graphics/fb%d/edid_modes", mFbNum);
    306 
    307     int hdmiEDIDFile = open(sysFsEDIDFilePath, O_RDONLY, 0);
    308     ssize_t len = -1;
    309     char edidStr[128] = {'\0'};
    310 
    311     if (hdmiEDIDFile < 0) {
    312         ALOGE("%s: edid_modes file '%s' not found",
    313                  __FUNCTION__, sysFsEDIDFilePath);
    314         return false;
    315     } else {
    316         len = read(hdmiEDIDFile, edidStr, sizeof(edidStr)-1);
    317         ALOGD_IF(DEBUG, "%s: EDID string: %s length = %zu",
    318                  __FUNCTION__, edidStr, len);
    319         if ( len <= 0) {
    320             ALOGE("%s: edid_modes file empty '%s'",
    321                      __FUNCTION__, sysFsEDIDFilePath);
    322             edidStr[0] = '\0';
    323         }
    324         else {
    325             while (len > 1 && isspace(edidStr[len-1])) {
    326                 --len;
    327             }
    328             edidStr[len] = '\0';
    329         }
    330         close(hdmiEDIDFile);
    331     }
    332     if(len > 0) {
    333         // Get EDID modes from the EDID strings
    334         mModeCount = parseResolution(edidStr, mEDIDModes);
    335         ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__,
    336                  mModeCount);
    337     }
    338 
    339     return (len > 0);
    340 }
    341 
    342 bool ExternalDisplay::openFrameBuffer()
    343 {
    344     if (mFd == -1) {
    345         char strDevPath[MAX_SYSFS_FILE_PATH];
    346         snprintf(strDevPath, MAX_SYSFS_FILE_PATH, "/dev/graphics/fb%d", mFbNum);
    347         mFd = open(strDevPath, O_RDWR);
    348         if (mFd < 0)
    349             ALOGE("%s: %s is not available", __FUNCTION__, strDevPath);
    350         mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].fd = mFd;
    351     }
    352     return (mFd > 0);
    353 }
    354 
    355 bool ExternalDisplay::closeFrameBuffer()
    356 {
    357     int ret = 0;
    358     if(mFd >= 0) {
    359         ret = close(mFd);
    360         mFd = -1;
    361     }
    362     mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].fd = mFd;
    363     return (ret == 0);
    364 }
    365 
    366 // clears the vinfo, edid, best modes
    367 void ExternalDisplay::resetInfo()
    368 {
    369     memset(&mVInfo, 0, sizeof(mVInfo));
    370     memset(mEDIDModes, 0, sizeof(mEDIDModes));
    371     mModeCount = 0;
    372     mCurrentMode = -1;
    373     mUnderscanSupported = false;
    374     // Reset the underscan supported system property
    375     const char* prop = "0";
    376     property_set("hw.underscan_supported", prop);
    377 }
    378 
    379 int ExternalDisplay::getModeOrder(int mode)
    380 {
    381     // XXX: We dont support interlaced modes but having
    382     // it here for future
    383     switch (mode) {
    384         default:
    385         case HDMI_VFRMT_1440x480i60_4_3:
    386             return 1; // 480i 4:3
    387         case HDMI_VFRMT_1440x480i60_16_9:
    388             return 2; // 480i 16:9
    389         case HDMI_VFRMT_1440x576i50_4_3:
    390             return 3; // i576i 4:3
    391         case HDMI_VFRMT_1440x576i50_16_9:
    392             return 4; // 576i 16:9
    393         case HDMI_VFRMT_1920x1080i60_16_9:
    394             return 5; // 1080i 16:9
    395         case HDMI_VFRMT_640x480p60_4_3:
    396             return 6; // 640x480 4:3
    397         case HDMI_VFRMT_720x480p60_4_3:
    398             return 7; // 480p 4:3
    399         case HDMI_VFRMT_720x480p60_16_9:
    400             return 8; // 480p 16:9
    401         case HDMI_VFRMT_720x576p50_4_3:
    402             return 9; // 576p 4:3
    403         case HDMI_VFRMT_720x576p50_16_9:
    404             return 10; // 576p 16:9
    405         case HDMI_VFRMT_1024x768p60_4_3:
    406             return 11; // 768p 4:3 Vesa format
    407         case HDMI_VFRMT_1280x1024p60_5_4:
    408             return 12; // 1024p Vesa format
    409         case HDMI_VFRMT_1280x720p50_16_9:
    410             return 13; // 720p@50Hz
    411         case HDMI_VFRMT_1280x720p60_16_9:
    412             return 14; // 720p@60Hz
    413         case HDMI_VFRMT_1920x1080p24_16_9:
    414             return 15; //1080p@24Hz
    415         case HDMI_VFRMT_1920x1080p25_16_9:
    416             return 16; //108-p@25Hz
    417         case HDMI_VFRMT_1920x1080p30_16_9:
    418             return 17; //1080p@30Hz
    419         case HDMI_VFRMT_1920x1080p50_16_9:
    420             return 18; //1080p@50Hz
    421         case HDMI_VFRMT_1920x1080p60_16_9:
    422             return 19; //1080p@60Hz
    423         case HDMI_VFRMT_2560x1600p60_16_9:
    424             return 20; //WQXGA@60Hz541
    425         case HDMI_VFRMT_3840x2160p24_16_9:
    426             return 21;//2160@24Hz
    427         case HDMI_VFRMT_3840x2160p25_16_9:
    428             return 22;//2160@25Hz
    429         case HDMI_VFRMT_3840x2160p30_16_9:
    430             return 23; //2160@30Hz
    431         case HDMI_VFRMT_4096x2160p24_16_9:
    432             return 24; //4kx2k@24Hz
    433     }
    434 }
    435 
    436 /// Returns the user mode set(if any) using adb shell
    437 int ExternalDisplay::getUserMode() {
    438     /* Based on the property set the resolution */
    439     char property_value[PROPERTY_VALUE_MAX];
    440     property_get("hw.hdmi.resolution", property_value, "-1");
    441     int mode = atoi(property_value);
    442     // We dont support interlaced modes
    443     if(isValidMode(mode) && !isInterlacedMode(mode)) {
    444         ALOGD_IF(DEBUG, "%s: setting the HDMI mode = %d", __FUNCTION__, mode);
    445         return mode;
    446     }
    447     return -1;
    448 }
    449 
    450 // Get the best mode for the current HD TV
    451 int ExternalDisplay::getBestMode() {
    452     int bestOrder = 0;
    453     int bestMode = HDMI_VFRMT_640x480p60_4_3;
    454     // for all the edid read, get the best mode
    455     for(int i = 0; i < mModeCount; i++) {
    456         int mode = mEDIDModes[i];
    457         int order = getModeOrder(mode);
    458         if (order > bestOrder) {
    459             bestOrder = order;
    460             bestMode = mode;
    461         }
    462     }
    463     return bestMode;
    464 }
    465 
    466 inline bool ExternalDisplay::isValidMode(int ID)
    467 {
    468     bool valid = false;
    469     for (int i = 0; i < mModeCount; i++) {
    470         if(ID == mEDIDModes[i]) {
    471             valid = true;
    472             break;
    473         }
    474     }
    475     return valid;
    476 }
    477 
    478 // returns true if the mode(ID) is interlaced mode format
    479 bool ExternalDisplay::isInterlacedMode(int ID) {
    480     bool interlaced = false;
    481     switch(ID) {
    482         case HDMI_VFRMT_1440x480i60_4_3:
    483         case HDMI_VFRMT_1440x480i60_16_9:
    484         case HDMI_VFRMT_1440x576i50_4_3:
    485         case HDMI_VFRMT_1440x576i50_16_9:
    486         case HDMI_VFRMT_1920x1080i60_16_9:
    487             interlaced = true;
    488             break;
    489         default:
    490             interlaced = false;
    491             break;
    492     }
    493     return interlaced;
    494 }
    495 
    496 void ExternalDisplay::setResolution(int ID)
    497 {
    498     int ret = 0;
    499     ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo);
    500     if(ret < 0) {
    501         ALOGD("In %s: FBIOGET_VSCREENINFO failed Err Str = %s", __FUNCTION__,
    502                                                             strerror(errno));
    503     }
    504     ALOGD_IF(DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d),"
    505             "(%d,%d,%d) %dMHz>", __FUNCTION__,
    506             mVInfo.reserved[3], mVInfo.xres, mVInfo.yres,
    507             mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin,
    508             mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
    509             mVInfo.pixclock/1000/1000);
    510     //If its a new ID - update var_screeninfo
    511     if ((isValidMode(ID)) && mCurrentMode != ID) {
    512         const struct msm_hdmi_mode_timing_info *mode =
    513             &supported_video_mode_lut[0];
    514         for (unsigned int i = 0; i < HDMI_VFRMT_MAX; ++i) {
    515             const struct msm_hdmi_mode_timing_info *cur =
    516                                         &supported_video_mode_lut[i];
    517             if (cur->video_format == (uint32_t)ID) {
    518                 mode = cur;
    519                 break;
    520             }
    521         }
    522         setDisplayTiming(mVInfo, mode);
    523         ALOGD_IF(DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx %d"
    524                  "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, ID,
    525                  mode->video_format, mVInfo.xres, mVInfo.yres,
    526                  mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin,
    527                  mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
    528                  mVInfo.pixclock/1000/1000);
    529 #ifdef FB_METADATA_VIDEO_INFO_CODE_SUPPORT
    530         struct msmfb_metadata metadata;
    531         memset(&metadata, 0 , sizeof(metadata));
    532         metadata.op = metadata_op_vic;
    533         metadata.data.video_info_code = mode->video_format;
    534         if (ioctl(mFd, MSMFB_METADATA_SET, &metadata) == -1) {
    535             ALOGD("In %s: MSMFB_METADATA_SET failed Err Str = %s",
    536                                                  __FUNCTION__, strerror(errno));
    537         }
    538 #endif
    539         mVInfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
    540         ret = ioctl(mFd, FBIOPUT_VSCREENINFO, &mVInfo);
    541         if(ret < 0) {
    542             ALOGD("In %s: FBIOPUT_VSCREENINFO failed Err Str = %s",
    543                                                  __FUNCTION__, strerror(errno));
    544         }
    545         mCurrentMode = ID;
    546     }
    547 }
    548 
    549 bool ExternalDisplay::writeHPDOption(int userOption) const
    550 {
    551     bool ret = true;
    552     if(mFbNum != -1) {
    553         char sysFsHPDFilePath[MAX_SYSFS_FILE_PATH];
    554         snprintf(sysFsHPDFilePath ,sizeof(sysFsHPDFilePath),
    555                  "/sys/devices/virtual/graphics/fb%d/hpd", mFbNum);
    556         int hdmiHPDFile = open(sysFsHPDFilePath,O_RDWR, 0);
    557         if (hdmiHPDFile < 0) {
    558             ALOGE("%s: state file '%s' not found : ret%d err str: %s",
    559                   __FUNCTION__, sysFsHPDFilePath, hdmiHPDFile, strerror(errno));
    560             ret = false;
    561         } else {
    562             ssize_t err = -1;
    563             ALOGD_IF(DEBUG, "%s: option = %d", __FUNCTION__, userOption);
    564             if(userOption)
    565                 err = write(hdmiHPDFile, "1", 2);
    566             else
    567                 err = write(hdmiHPDFile, "0" , 2);
    568             if (err <= 0) {
    569                 ALOGE("%s: file write failed '%s'", __FUNCTION__,
    570                       sysFsHPDFilePath);
    571                 ret = false;
    572             }
    573             close(hdmiHPDFile);
    574         }
    575     }
    576     return ret;
    577 }
    578 
    579 
    580 void ExternalDisplay::setAttributes() {
    581     int width = 0, height = 0, fps = 0;
    582     getAttrForMode(width, height, fps);
    583     ALOGD("ExtDisplay setting xres = %d, yres = %d", width, height);
    584     if(mHwcContext) {
    585         // Always set dpyAttr res to mVInfo res
    586         mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = width;
    587         mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = height;
    588         mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode = false;
    589         if(!qdutils::MDPVersion::getInstance().is8x26()
    590                 && mHwcContext->mMDPDownscaleEnabled) {
    591             int priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
    592             int priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
    593             // if primary resolution is more than the hdmi resolution
    594             // configure dpy attr to primary resolution and set
    595             // downscale mode
    596             // Restrict this upto 1080p resolution max
    597             if(((priW * priH) > (width * height)) &&
    598                ((priW * priH) <= SUPPORTED_DOWNSCALE_EXT_AREA)) {
    599                 // tmpW and tmpH will hold the primary dimensions before we
    600                 // update the aspect ratio if necessary.
    601                 int tmpW = priW;
    602                 int tmpH = priH;
    603                 // HDMI is always in landscape, so always assign the higher
    604                 // dimension to hdmi's xres
    605                 if(priH > priW) {
    606                     tmpW = priH;
    607                     tmpH = priW;
    608                 }
    609                 // The aspect ratios of the external and primary displays
    610                 // can be different. As a result, directly assigning primary
    611                 // resolution could lead to an incorrect final image.
    612                 // We get around this by calculating a new resolution by
    613                 // keeping aspect ratio intact.
    614                 hwc_rect r = {0, 0, 0, 0};
    615                 getAspectRatioPosition(tmpW, tmpH, width, height, r);
    616                 mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres =
    617                                                               r.right - r.left;
    618                 mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres =
    619                                                               r.bottom - r.top;
    620                 // Set External Display MDP Downscale mode indicator
    621                 mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode =true;
    622             }
    623         }
    624         mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period =
    625                 (int) 1000000000l / fps;
    626     }
    627 }
    628 
    629 void ExternalDisplay::getAttrForMode(int& width, int& height, int& fps) {
    630     switch (mCurrentMode) {
    631         case HDMI_VFRMT_640x480p60_4_3:
    632             width = 640;
    633             height = 480;
    634             fps = 60;
    635             break;
    636         case HDMI_VFRMT_720x480p60_4_3:
    637         case HDMI_VFRMT_720x480p60_16_9:
    638             width = 720;
    639             height = 480;
    640             fps = 60;
    641             break;
    642         case HDMI_VFRMT_720x576p50_4_3:
    643         case HDMI_VFRMT_720x576p50_16_9:
    644             width = 720;
    645             height = 576;
    646             fps = 50;
    647             break;
    648         case HDMI_VFRMT_1280x720p50_16_9:
    649             width = 1280;
    650             height = 720;
    651             fps = 50;
    652             break;
    653         case HDMI_VFRMT_1280x720p60_16_9:
    654             width = 1280;
    655             height = 720;
    656             fps = 60;
    657             break;
    658         case HDMI_VFRMT_1280x1024p60_5_4:
    659             width = 1280;
    660             height = 1024;
    661             fps = 60;
    662             break;
    663         case HDMI_VFRMT_1024x768p60_4_3:
    664             width = 1024;
    665             height = 768;
    666             fps = 60;
    667             break;
    668         case HDMI_VFRMT_1920x1080p24_16_9:
    669             width = 1920;
    670             height = 1080;
    671             fps = 24;
    672             break;
    673         case HDMI_VFRMT_1920x1080p25_16_9:
    674             width = 1920;
    675             height = 1080;
    676             fps = 25;
    677             break;
    678         case HDMI_VFRMT_1920x1080p30_16_9:
    679             width = 1920;
    680             height = 1080;
    681             fps = 30;
    682             break;
    683         case HDMI_VFRMT_1920x1080p50_16_9:
    684             width = 1920;
    685             height = 1080;
    686             fps = 50;
    687             break;
    688         case HDMI_VFRMT_1920x1080p60_16_9:
    689             width = 1920;
    690             height = 1080;
    691             fps = 60;
    692             break;
    693         case HDMI_VFRMT_2560x1600p60_16_9:
    694             width = 2560;
    695             height = 1600;
    696             fps = 60;
    697             break;
    698         case HDMI_VFRMT_3840x2160p24_16_9:
    699             width = 3840;
    700             height = 2160;
    701             fps = 24;
    702             break;
    703         case HDMI_VFRMT_3840x2160p25_16_9:
    704             width = 3840;
    705             height = 2160;
    706             fps = 25;
    707             break;
    708         case HDMI_VFRMT_3840x2160p30_16_9:
    709             width = 3840;
    710             height = 2160;
    711             fps = 30;
    712             break;
    713         case HDMI_VFRMT_4096x2160p24_16_9:
    714             width = 4096;
    715             height = 2160;
    716             fps = 24;
    717             break;
    718 
    719     }
    720 }
    721 
    722 };
    723