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