1b166940edca6e312463461438e2aa66e9852c26aBenoit Goby/*
2b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * Copyright (C) 2010 The Android Open Source Project
3b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * Copyright (C) 2012, The Linux Foundation. All rights reserved.
4b166940edca6e312463461438e2aa66e9852c26aBenoit Goby *
5b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * Not a Contribution, Apache license notifications and license are
6b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * retained for attribution purposes only.
7b166940edca6e312463461438e2aa66e9852c26aBenoit Goby *
8b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * Licensed under the Apache License, Version 2.0 (the "License");
9b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * you may not use this file except in compliance with the License.
10b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * You may obtain a copy of the License at
11b166940edca6e312463461438e2aa66e9852c26aBenoit Goby *
12b166940edca6e312463461438e2aa66e9852c26aBenoit Goby *      http://www.apache.org/licenses/LICENSE-2.0
13b166940edca6e312463461438e2aa66e9852c26aBenoit Goby *
14b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * Unless required by applicable law or agreed to in writing, software
15b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * distributed under the License is distributed on an "AS IS" BASIS,
16b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * See the License for the specific language governing permissions and
18b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * limitations under the License.
19b166940edca6e312463461438e2aa66e9852c26aBenoit Goby */
20b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
21b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define DEBUG 0
22b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <ctype.h>
23b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <fcntl.h>
24b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <media/IAudioPolicyService.h>
25b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <media/AudioSystem.h>
26b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <utils/threads.h>
27b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <utils/Errors.h>
28b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <utils/Log.h>
29b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
30b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <linux/msm_mdp.h>
31b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <linux/fb.h>
32b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <sys/ioctl.h>
33b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <sys/poll.h>
34b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <sys/resource.h>
35b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include <cutils/properties.h>
36b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include "hwc_utils.h"
37b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include "external.h"
38b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include "overlayUtils.h"
39b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#include "overlay.h"
40b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
41b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyusing namespace android;
42b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
43b166940edca6e312463461438e2aa66e9852c26aBenoit Gobynamespace qhwc {
44b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
45b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define MAX_FRAME_BUFFER_NAME_SIZE      (80)
46b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define MAX_DISPLAY_DEVICES             (3)
47b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
48b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
49b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyconst char* msmFbDevicePath[] = {  "/dev/graphics/fb1",
50b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                   "/dev/graphics/fb2"};
51b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
52b166940edca6e312463461438e2aa66e9852c26aBenoit Goby/*
53b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * Updates extDeviceFbIndex Array with the correct frame buffer indices
54b166940edca6e312463461438e2aa66e9852c26aBenoit Goby * of avaiable external devices
55b166940edca6e312463461438e2aa66e9852c26aBenoit Goby *
56b166940edca6e312463461438e2aa66e9852c26aBenoit Goby */
57b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::updateExtDispDevFbIndex()
58b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
59b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    FILE *displayDeviceFP = NULL;
60b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
61b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
62b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
63b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    for(int j = 1; j < MAX_DISPLAY_DEVICES; j++) {
64b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        sprintf (msmFbTypePath,"/sys/class/graphics/fb%d/msm_fb_type", j);
65b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        displayDeviceFP = fopen(msmFbTypePath, "r");
66b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if(displayDeviceFP){
67b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
68b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                    displayDeviceFP);
69b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            if(strncmp(fbType, "dtv panel", strlen("dtv panel")) == 0){
70b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                ALOGD_IF(DEBUG,"hdmi framebuffer index is %d",j);
71b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                mHdmiFbNum = j;
72b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            } else if(strncmp(fbType, "writeback panel",
73b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                    strlen("writeback panel")) == 0){
74b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                ALOGD_IF(DEBUG,"wfd framebuffer index is %d",j);
75b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                mWfdFbNum = j;
76b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            }
77b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fclose(displayDeviceFP);
78b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
79b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
80b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    ALOGD_IF(DEBUG,"%s: mHdmiFbNum: %d mWfdFbNum: %d ",__FUNCTION__,
81b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                                       mHdmiFbNum, mWfdFbNum);
82b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
83b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
84b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyint ExternalDisplay::configureHDMIDisplay() {
85b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    openFrameBuffer(mHdmiFbNum);
86b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(mFd == -1)
87b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        return -1;
88b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    readCEUnderscanInfo();
89b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    readResolution();
90b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // TODO: Move this to activate
91b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    /* Used for changing the resolution
92b166940edca6e312463461438e2aa66e9852c26aBenoit Goby     * getUserMode will get the preferred
93b166940edca6e312463461438e2aa66e9852c26aBenoit Goby     * mode set thru adb shell */
94b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int mode = getUserMode();
95b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if (mode == -1) {
96b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        //Get the best mode and set
97b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mode = getBestMode();
98b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
99b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    setResolution(mode);
100b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    setDpyHdmiAttr();
101b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    setExternalDisplay(true, mHdmiFbNum);
102b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return 0;
103b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
104b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
105b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyint ExternalDisplay::configureWFDDisplay() {
106b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int ret = 0;
107b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(mConnectedFbNum == mHdmiFbNum) {
108b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGE("%s: Cannot process WFD connection while HDMI is active",
109b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                     __FUNCTION__);
110b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        return -1;
111b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
112b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    openFrameBuffer(mWfdFbNum);
113b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(mFd == -1)
114b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        return -1;
115b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo);
116b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(ret < 0) {
117b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD("In %s: FBIOGET_VSCREENINFO failed Err Str = %s", __FUNCTION__,
118b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                strerror(errno));
119b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
120b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    setDpyWfdAttr();
121b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    setExternalDisplay(true, mWfdFbNum);
122b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return 0;
123b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
124b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
125b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyint ExternalDisplay::teardownHDMIDisplay() {
126b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(mConnectedFbNum == mHdmiFbNum) {
127b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        // hdmi offline event..!
128b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        closeFrameBuffer();
129b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        resetInfo();
130b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        setExternalDisplay(false);
131b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
132b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return 0;
133b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
134b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
135b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyint ExternalDisplay::teardownWFDDisplay() {
136b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(mConnectedFbNum == mWfdFbNum) {
137b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        // wfd offline event..!
138b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        closeFrameBuffer();
139b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        memset(&mVInfo, 0, sizeof(mVInfo));
140b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        setExternalDisplay(false);
141b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
142b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return 0;
143b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
144b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
145b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::processUEventOnline(const char *str) {
146b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    const char *s1 = str + strlen("change@/devices/virtual/switch/");
147b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(!strncmp(s1,"hdmi",strlen(s1))) {
148b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        // hdmi online event..!
149b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        configureHDMIDisplay();
150b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        // set system property
151b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        property_set("hw.hdmiON", "1");
152b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }else if(!strncmp(s1,"wfd",strlen(s1))) {
153b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        // wfd online event..!
154b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        configureWFDDisplay();
155b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
156b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
157b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
158b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::processUEventOffline(const char *str) {
159b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    const char *s1 = str + strlen("change@/devices/virtual/switch/");
160b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(!strncmp(s1,"hdmi",strlen(s1))) {
161b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        teardownHDMIDisplay();
162b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        // unset system property
163b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        property_set("hw.hdmiON", "0");
164b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }else if(!strncmp(s1,"wfd",strlen(s1))) {
165b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        teardownWFDDisplay();
166b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
167b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
168b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
169b166940edca6e312463461438e2aa66e9852c26aBenoit GobyExternalDisplay::ExternalDisplay(hwc_context_t* ctx):mFd(-1),
170b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    mCurrentMode(-1), mConnected(0), mConnectedFbNum(0), mModeCount(0),
171b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    mUnderscanSupported(false), mHwcContext(ctx), mHdmiFbNum(-1),
172b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    mWfdFbNum(-1), mExtDpyNum(HWC_DISPLAY_EXTERNAL)
173b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
174b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    memset(&mVInfo, 0, sizeof(mVInfo));
175b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    //Determine the fb index for external display devices.
176b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    updateExtDispDevFbIndex();
177b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // disable HPD at start, it will be enabled later
178b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // when the display powers on
179b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // This helps for framework reboot or adb shell stop/start
180b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    writeHPDOption(0);
181b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
182b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
183b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
184b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::setEDIDMode(int resMode) {
185b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    ALOGD_IF(DEBUG,"resMode=%d ", resMode);
186b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {
187b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        Mutex::Autolock lock(mExtDispLock);
188b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        setExternalDisplay(false);
189b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        openFrameBuffer(mHdmiFbNum);
190b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        setResolution(resMode);
191b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
192b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    setExternalDisplay(true, mHdmiFbNum);
193b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
194b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
195b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::setHPD(uint32_t startEnd) {
196b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    ALOGD_IF(DEBUG,"HPD enabled=%d", startEnd);
197b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    writeHPDOption(startEnd);
198b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
199b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
200b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::setActionSafeDimension(int w, int h) {
201b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    ALOGD_IF(DEBUG,"ActionSafe w=%d h=%d", w, h);
202b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    Mutex::Autolock lock(mExtDispLock);
203b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char actionsafeWidth[PROPERTY_VALUE_MAX];
204b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char actionsafeHeight[PROPERTY_VALUE_MAX];
205b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    sprintf(actionsafeWidth, "%d", w);
206b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    property_set("hw.actionsafe.width", actionsafeWidth);
207b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    sprintf(actionsafeHeight, "%d", h);
208b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    property_set("hw.actionsafe.height", actionsafeHeight);
209b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    setExternalDisplay(true, mHdmiFbNum);
210b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
211b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
212b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyint ExternalDisplay::getModeCount() const {
213b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    ALOGD_IF(DEBUG,"HPD mModeCount=%d", mModeCount);
214b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    Mutex::Autolock lock(mExtDispLock);
215b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return mModeCount;
216b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
217b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
218b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::getEDIDModes(int *out) const {
219b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    Mutex::Autolock lock(mExtDispLock);
220b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    for(int i = 0;i < mModeCount;i++) {
221b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        out[i] = mEDIDModes[i];
222b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
223b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
224b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
225b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::readCEUnderscanInfo()
226b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
227b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int hdmiScanInfoFile = -1;
228b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int len = -1;
229b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char scanInfo[17];
230b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char *ce_info_str = NULL;
231b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    const char token[] = ", \n";
232b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int ce_info = -1;
233b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char sysFsScanInfoFilePath[128];
234b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    sprintf(sysFsScanInfoFilePath, "/sys/devices/virtual/graphics/fb%d/"
235b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                   "scan_info", mHdmiFbNum);
236b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
237b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    memset(scanInfo, 0, sizeof(scanInfo));
238b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    hdmiScanInfoFile = open(sysFsScanInfoFilePath, O_RDONLY, 0);
239b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if (hdmiScanInfoFile < 0) {
240b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD_IF(DEBUG, "%s: scan_info file '%s' not found",
241b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                __FUNCTION__, sysFsScanInfoFilePath);
242b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        return;
243b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    } else {
244b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        len = read(hdmiScanInfoFile, scanInfo, sizeof(scanInfo)-1);
245b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD("%s: Scan Info string: %s length = %d",
246b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                 __FUNCTION__, scanInfo, len);
247b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if (len <= 0) {
248b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            close(hdmiScanInfoFile);
249b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            ALOGE("%s: Scan Info file empty '%s'",
250b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                __FUNCTION__, sysFsScanInfoFilePath);
251b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return;
252b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
253b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        scanInfo[len] = '\0';  /* null terminate the string */
254b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
255b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    close(hdmiScanInfoFile);
256b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
257b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    /*
258b166940edca6e312463461438e2aa66e9852c26aBenoit Goby     * The scan_info contains the three fields
259b166940edca6e312463461438e2aa66e9852c26aBenoit Goby     * PT - preferred video format
260b166940edca6e312463461438e2aa66e9852c26aBenoit Goby     * IT - video format
261b166940edca6e312463461438e2aa66e9852c26aBenoit Goby     * CE video format - containing the underscan support information
262b166940edca6e312463461438e2aa66e9852c26aBenoit Goby     */
263b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
264b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    /* PT */
265b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    ce_info_str = strtok(scanInfo, token);
266b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if (ce_info_str) {
267b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        /* IT */
268b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ce_info_str = strtok(NULL, token);
269b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if (ce_info_str) {
270b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            /* CE */
271b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            ce_info_str = strtok(NULL, token);
272b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            if (ce_info_str)
273b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                ce_info = atoi(ce_info_str);
274b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
275b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
276b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
277b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if (ce_info_str) {
278b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        // ce_info contains the underscan information
279b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if (ce_info == EXT_SCAN_ALWAYS_UNDERSCANED ||
280b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            ce_info == EXT_SCAN_BOTH_SUPPORTED)
281b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            // if TV supported underscan, then driver will always underscan
282b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            // hence no need to apply action safe rectangle
283b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            mUnderscanSupported = true;
284b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    } else {
285b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGE("%s: scan_info string error", __FUNCTION__);
286b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
287b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
288b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // Store underscan support info in a system property
289b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    const char* prop = (mUnderscanSupported) ? "1" : "0";
290b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    property_set("hw.underscan_supported", prop);
291b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return;
292b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
293b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
294b166940edca6e312463461438e2aa66e9852c26aBenoit GobyExternalDisplay::~ExternalDisplay()
295b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
296b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    closeFrameBuffer();
297b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
298b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
299b166940edca6e312463461438e2aa66e9852c26aBenoit Gobystruct disp_mode_timing_type {
300b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int  video_format;
301b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
302b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int  active_h;
303b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int  active_v;
304b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
305b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int  front_porch_h;
306b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int  pulse_width_h;
307b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int  back_porch_h;
308b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
309b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int  front_porch_v;
310b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int  pulse_width_v;
311b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int  back_porch_v;
312b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
313b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int  pixel_freq;
314b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    bool interlaced;
315b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
316b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    void set_info(struct fb_var_screeninfo &info) const;
317b166940edca6e312463461438e2aa66e9852c26aBenoit Goby};
318b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
319b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid disp_mode_timing_type::set_info(struct fb_var_screeninfo &info) const
320b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
321b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.reserved[0] = 0;
322b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.reserved[1] = 0;
323b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.reserved[2] = 0;
324b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#ifndef FB_METADATA_VIDEO_INFO_CODE_SUPPORT
325b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.reserved[3] = (info.reserved[3] & 0xFFFF) | (video_format << 16);
326b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#endif
327b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.xoffset = 0;
328b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.yoffset = 0;
329b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.xres = active_h;
330b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.yres = active_v;
331b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
332b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.pixclock = pixel_freq*1000;
333b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.vmode = interlaced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
334b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
335b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.right_margin = front_porch_h;
336b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.hsync_len = pulse_width_h;
337b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.left_margin = back_porch_h;
338b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.lower_margin = front_porch_v;
339b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.vsync_len = pulse_width_v;
340b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    info.upper_margin = back_porch_v;
341b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
342b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
343b166940edca6e312463461438e2aa66e9852c26aBenoit Goby/* Video formates supported by the HDMI Standard */
344b166940edca6e312463461438e2aa66e9852c26aBenoit Goby/* Indicates the resolution, pix clock and the aspect ratio */
345b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m640x480p60_4_3         1
346b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m720x480p60_4_3         2
347b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m720x480p60_16_9        3
348b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1280x720p60_16_9       4
349b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1920x1080i60_16_9      5
350b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1440x480i60_4_3        6
351b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1440x480i60_16_9       7
352b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1920x1080p60_16_9      16
353b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m720x576p50_4_3         17
354b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m720x576p50_16_9        18
355b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1280x720p50_16_9       19
356b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1440x576i50_4_3        21
357b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1440x576i50_16_9       22
358b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1920x1080p50_16_9      31
359b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1920x1080p24_16_9      32
360b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1920x1080p25_16_9      33
361b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#define m1920x1080p30_16_9      34
362b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
363b166940edca6e312463461438e2aa66e9852c26aBenoit Gobystatic struct disp_mode_timing_type supported_video_mode_lut[] = {
364b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m640x480p60_4_3,     640,  480,  16,  96,  48, 10, 2, 33,  25200, false},
365b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m720x480p60_4_3,     720,  480,  16,  62,  60,  9, 6, 30,  27030, false},
366b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m720x480p60_16_9,    720,  480,  16,  62,  60,  9, 6, 30,  27030, false},
367b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1280x720p60_16_9,  1280,  720, 110,  40, 220,  5, 5, 20,  74250, false},
368b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1920x1080i60_16_9, 1920,  540,  88,  44, 148,  2, 5,  5,  74250, false},
369b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1440x480i60_4_3,   1440,  240,  38, 124, 114,  4, 3, 15,  27000, true},
370b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1440x480i60_16_9,  1440,  240,  38, 124, 114,  4, 3, 15,  27000, true},
371b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1920x1080p60_16_9, 1920, 1080,  88,  44, 148,  4, 5, 36, 148500, false},
372b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m720x576p50_4_3,     720,  576,  12,  64,  68,  5, 5, 39,  27000, false},
373b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m720x576p50_16_9,    720,  576,  12,  64,  68,  5, 5, 39,  27000, false},
374b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1280x720p50_16_9,  1280,  720, 440,  40, 220,  5, 5, 20,  74250, false},
375b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1440x576i50_4_3,   1440,  288,  24, 126, 138,  2, 3, 19,  27000, true},
376b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1440x576i50_16_9,  1440,  288,  24, 126, 138,  2, 3, 19,  27000, true},
377b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1920x1080p50_16_9, 1920, 1080, 528,  44, 148,  4, 5, 36, 148500, false},
378b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1920x1080p24_16_9, 1920, 1080, 638,  44, 148,  4, 5, 36,  74250, false},
379b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1920x1080p25_16_9, 1920, 1080, 528,  44, 148,  4, 5, 36,  74250, false},
380b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    {m1920x1080p30_16_9, 1920, 1080,  88,  44, 148,  4, 5, 36,  74250, false},
381b166940edca6e312463461438e2aa66e9852c26aBenoit Goby};
382b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
383b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyint ExternalDisplay::parseResolution(char* edidStr, int* edidModes)
384b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
385b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char delim = ',';
386b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int count = 0;
387b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char *start, *end;
388b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // EDIDs are string delimited by ','
389b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // Ex: 16,4,5,3,32,34,1
390b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // Parse this string to get mode(int)
391b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    start = (char*) edidStr;
392b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    end = &delim;
393b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    while(*end == delim) {
394b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        edidModes[count] = (int) strtol(start, &end, 10);
395b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        start = end+1;
396b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        count++;
397b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
398b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    ALOGD_IF(DEBUG, "In %s: count = %d", __FUNCTION__, count);
399b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    for (int i = 0; i < count; i++)
400b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD_IF(DEBUG, "Mode[%d] = %d", i, edidModes[i]);
401b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return count;
402b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
403b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
404b166940edca6e312463461438e2aa66e9852c26aBenoit Gobybool ExternalDisplay::readResolution()
405b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
406b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char sysFsEDIDFilePath[255];
407b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    sprintf(sysFsEDIDFilePath , "/sys/devices/virtual/graphics/fb%d/edid_modes",
408b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            mHdmiFbNum);
409b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
410b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int hdmiEDIDFile = open(sysFsEDIDFilePath, O_RDONLY, 0);
411b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int len = -1;
412b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
413b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if (hdmiEDIDFile < 0) {
414b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGE("%s: edid_modes file '%s' not found",
415b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                 __FUNCTION__, sysFsEDIDFilePath);
416b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        return false;
417b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    } else {
418b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        len = read(hdmiEDIDFile, mEDIDs, sizeof(mEDIDs)-1);
419b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD_IF(DEBUG, "%s: EDID string: %s length = %d",
420b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                 __FUNCTION__, mEDIDs, len);
421b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if ( len <= 0) {
422b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            ALOGE("%s: edid_modes file empty '%s'",
423b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                     __FUNCTION__, sysFsEDIDFilePath);
424b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
425b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        else {
426b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            while (len > 1 && isspace(mEDIDs[len-1]))
427b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                --len;
428b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            mEDIDs[len] = 0;
429b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
430b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
431b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    close(hdmiEDIDFile);
432b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(len > 0) {
433b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        // Get EDID modes from the EDID strings
434b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mModeCount = parseResolution(mEDIDs, mEDIDModes);
435b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__,
436b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                 mModeCount);
437b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
438b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
439b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return (strlen(mEDIDs) > 0);
440b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
441b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
442b166940edca6e312463461438e2aa66e9852c26aBenoit Gobybool ExternalDisplay::openFrameBuffer(int fbNum)
443b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
444b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if (mFd == -1) {
445b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mFd = open(msmFbDevicePath[fbNum-1], O_RDWR);
446b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if (mFd < 0)
447b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            ALOGE("%s: %s is not available", __FUNCTION__,
448b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                            msmFbDevicePath[fbNum-1]);
449b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if(mHwcContext) {
450b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            mHwcContext->dpyAttr[mExtDpyNum].fd = mFd;
451b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
452b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
453b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return (mFd > 0);
454b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
455b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
456b166940edca6e312463461438e2aa66e9852c26aBenoit Gobybool ExternalDisplay::closeFrameBuffer()
457b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
458b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int ret = 0;
459b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(mFd >= 0) {
460b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ret = close(mFd);
461b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mFd = -1;
462b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
463b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(mHwcContext) {
464b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mHwcContext->dpyAttr[mExtDpyNum].fd = mFd;
465b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
466b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return (ret == 0);
467b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
468b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
469b166940edca6e312463461438e2aa66e9852c26aBenoit Goby// clears the vinfo, edid, best modes
470b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::resetInfo()
471b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
472b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    memset(&mVInfo, 0, sizeof(mVInfo));
473b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    memset(mEDIDs, 0, sizeof(mEDIDs));
474b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    memset(mEDIDModes, 0, sizeof(mEDIDModes));
475b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    mModeCount = 0;
476b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    mCurrentMode = -1;
477b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    mUnderscanSupported = false;
478b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // Reset the underscan supported system property
479b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    const char* prop = "0";
480b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    property_set("hw.underscan_supported", prop);
481b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
482b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
483b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyint ExternalDisplay::getModeOrder(int mode)
484b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
485b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // XXX: We dont support interlaced modes but having
486b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // it here for for future
487b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    switch (mode) {
488b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        default:
489b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1440x480i60_4_3:
490b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 1; // 480i 4:3
491b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1440x480i60_16_9:
492b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 2; // 480i 16:9
493b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1440x576i50_4_3:
494b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 3; // i576i 4:3
495b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1440x576i50_16_9:
496b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 4; // 576i 16:9
497b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m640x480p60_4_3:
498b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 5; // 640x480 4:3
499b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m720x480p60_4_3:
500b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 6; // 480p 4:3
501b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m720x480p60_16_9:
502b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 7; // 480p 16:9
503b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m720x576p50_4_3:
504b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 8; // 576p 4:3
505b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m720x576p50_16_9:
506b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 9; // 576p 16:9
507b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080i60_16_9:
508b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 10; // 1080i 16:9
509b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1280x720p50_16_9:
510b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 11; // 720p@50Hz
511b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1280x720p60_16_9:
512b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 12; // 720p@60Hz
513b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080p24_16_9:
514b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 13; //1080p@24Hz
515b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080p25_16_9:
516b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 14; //108-p@25Hz
517b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080p30_16_9:
518b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 15; //1080p@30Hz
519b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080p50_16_9:
520b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 16; //1080p@50Hz
521b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080p60_16_9:
522b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            return 17; //1080p@60Hz
523b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
524b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
525b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
526b166940edca6e312463461438e2aa66e9852c26aBenoit Goby/// Returns the user mode set(if any) using adb shell
527b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyint ExternalDisplay::getUserMode() {
528b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    /* Based on the property set the resolution */
529b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char property_value[PROPERTY_VALUE_MAX];
530b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    property_get("hw.hdmi.resolution", property_value, "-1");
531b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int mode = atoi(property_value);
532b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // We dont support interlaced modes
533b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(isValidMode(mode) && !isInterlacedMode(mode)) {
534b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD_IF(DEBUG, "%s: setting the HDMI mode = %d", __FUNCTION__, mode);
535b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        return mode;
536b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
537b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return -1;
538b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
539b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
540b166940edca6e312463461438e2aa66e9852c26aBenoit Goby// Get the best mode for the current HD TV
541b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyint ExternalDisplay::getBestMode() {
542b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int bestOrder = 0;
543b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int bestMode = m640x480p60_4_3;
544b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    Mutex::Autolock lock(mExtDispLock);
545b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    // for all the edid read, get the best mode
546b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    for(int i = 0; i < mModeCount; i++) {
547b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        int mode = mEDIDModes[i];
548b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        int order = getModeOrder(mode);
549b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if (order > bestOrder) {
550b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            bestOrder = order;
551b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            bestMode = mode;
552b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
553b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
554b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return bestMode;
555b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
556b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
557b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyinline bool ExternalDisplay::isValidMode(int ID)
558b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
559b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    bool valid = false;
560b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    for (int i = 0; i < mModeCount; i++) {
561b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if(ID == mEDIDModes[i]) {
562b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            valid = true;
563b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            break;
564b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
565b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
566b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return valid;
567b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
568b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
569b166940edca6e312463461438e2aa66e9852c26aBenoit Goby// returns true if the mode(ID) is interlaced mode format
570b166940edca6e312463461438e2aa66e9852c26aBenoit Gobybool ExternalDisplay::isInterlacedMode(int ID) {
571b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    bool interlaced = false;
572b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    switch(ID) {
573b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1440x480i60_4_3:
574b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1440x480i60_16_9:
575b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1440x576i50_4_3:
576b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1440x576i50_16_9:
577b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080i60_16_9:
578b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            interlaced = true;
579b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        default:
580b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            interlaced = false;
581b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
582b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return interlaced;
583b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
584b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
585b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::setResolution(int ID)
586b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
587b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    struct fb_var_screeninfo info;
588b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int ret = 0;
589b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo);
590b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(ret < 0) {
591b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD("In %s: FBIOGET_VSCREENINFO failed Err Str = %s", __FUNCTION__,
592b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                                            strerror(errno));
593b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
594b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
595b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    ALOGD_IF(DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d),"
596b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            "(%d,%d,%d) %dMHz>", __FUNCTION__,
597b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            mVInfo.reserved[3], mVInfo.xres, mVInfo.yres,
598b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin,
599b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
600b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            mVInfo.pixclock/1000/1000);
601b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    //If its a new ID - update var_screeninfo
602b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if ((isValidMode(ID)) && mCurrentMode != ID) {
603b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        const struct disp_mode_timing_type *mode =
604b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            &supported_video_mode_lut[0];
605b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        unsigned count =  sizeof(supported_video_mode_lut)/sizeof
606b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            (*supported_video_mode_lut);
607b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        for (unsigned int i = 0; i < count; ++i) {
608b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            const struct disp_mode_timing_type *cur =
609b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                &supported_video_mode_lut[i];
610b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            if (cur->video_format == ID)
611b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                mode = cur;
612b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
613b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mode->set_info(mVInfo);
614b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD_IF(DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx %d"
615b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                 "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, ID,
616b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                 mode->video_format, mVInfo.xres, mVInfo.yres,
617b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                 mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin,
618b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                 mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
619b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                 mVInfo.pixclock/1000/1000);
620b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#ifdef FB_METADATA_VIDEO_INFO_CODE_SUPPORT
621b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        struct msmfb_metadata metadata;
622b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        memset(&metadata, 0 , sizeof(metadata));
623b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        metadata.op = metadata_op_vic;
624b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        metadata.data.video_info_code = mode->video_format;
625b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if (ioctl(mFd, MSMFB_METADATA_SET, &metadata) == -1) {
626b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            ALOGD("In %s: MSMFB_METADATA_SET failed Err Str = %s",
627b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                                 __FUNCTION__, strerror(errno));
628b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
629b166940edca6e312463461438e2aa66e9852c26aBenoit Goby#endif
630b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mVInfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
631b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ret = ioctl(mFd, FBIOPUT_VSCREENINFO, &mVInfo);
632b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if(ret < 0) {
633b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            ALOGD("In %s: FBIOPUT_VSCREENINFO failed Err Str = %s",
634b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                                 __FUNCTION__, strerror(errno));
635b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
636b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mCurrentMode = ID;
637b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
638b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
639b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
640b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::setExternalDisplay(bool connected, int extFbNum)
641b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
642b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    hwc_context_t* ctx = mHwcContext;
643b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(ctx) {
644b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD_IF(DEBUG, "%s: connected = %d", __FUNCTION__, connected);
645b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        // Store the external display
646b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mConnected = connected;
647b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mConnectedFbNum = extFbNum;
648b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mHwcContext->dpyAttr[mExtDpyNum].connected = connected;
649b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        // Update external fb number in Overlay context
650b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        overlay::Overlay::getInstance()->setExtFbNum(extFbNum);
651b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
652b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
653b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
654b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyint ExternalDisplay::getExtFbNum(int &fbNum) {
655b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int ret = -1;
656b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(mConnected) {
657b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        fbNum = mConnectedFbNum;
658b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ret = 0;
659b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
660b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return ret;
661b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
662b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
663b166940edca6e312463461438e2aa66e9852c26aBenoit Gobybool ExternalDisplay::writeHPDOption(int userOption) const
664b166940edca6e312463461438e2aa66e9852c26aBenoit Goby{
665b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    bool ret = true;
666b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    char sysFsHPDFilePath[255];
667b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    sprintf(sysFsHPDFilePath ,"/sys/devices/virtual/graphics/fb%d/hpd",
668b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                mHdmiFbNum);
669b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int hdmiHPDFile = open(sysFsHPDFilePath,O_RDWR, 0);
670b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if (hdmiHPDFile < 0) {
671b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGE("%s: state file '%s' not found : ret%d err str: %s", __FUNCTION__,
672b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                                sysFsHPDFilePath, hdmiHPDFile, strerror(errno));
673b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ret = false;
674b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    } else {
675b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        int err = -1;
676b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD_IF(DEBUG, "%s: option = %d", __FUNCTION__, userOption);
677b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if(userOption)
678b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            err = write(hdmiHPDFile, "1", 2);
679b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        else
680b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            err = write(hdmiHPDFile, "0" , 2);
681b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        if (err <= 0) {
682b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            ALOGE("%s: file write failed '%s'", __FUNCTION__, sysFsHPDFilePath);
683b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            ret = false;
684b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        }
685b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        close(hdmiHPDFile);
686b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
687b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    return ret;
688b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
689b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
690b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::setDpyWfdAttr() {
691b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(mHwcContext) {
692b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mHwcContext->dpyAttr[mExtDpyNum].xres = mVInfo.xres;
693b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mHwcContext->dpyAttr[mExtDpyNum].yres = mVInfo.yres;
694b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mHwcContext->dpyAttr[mExtDpyNum].vsync_period =
695b166940edca6e312463461438e2aa66e9852c26aBenoit Goby                1000000000l /60;
696b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD_IF(DEBUG,"%s: wfd...connected..!",__FUNCTION__);
697b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
698b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
699b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
700b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::setDpyHdmiAttr() {
701b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    int width = 0, height = 0, fps = 0;
702b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    getAttrForMode(width, height, fps);
703b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    if(mHwcContext) {
704b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        ALOGD("ExtDisplay setting xres = %d, yres = %d", width, height);
705b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = width;
706b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = height;
707b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period =
708b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            1000000000l / fps;
709b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
710b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
711b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
712b166940edca6e312463461438e2aa66e9852c26aBenoit Gobyvoid ExternalDisplay::getAttrForMode(int& width, int& height, int& fps) {
713b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    switch (mCurrentMode) {
714b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m640x480p60_4_3:
715b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            width = 640;
716b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            height = 480;
717b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fps = 60;
718b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            break;
719b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m720x480p60_4_3:
720b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m720x480p60_16_9:
721b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            width = 720;
722b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            height = 480;
723b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fps = 60;
724b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            break;
725b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m720x576p50_4_3:
726b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m720x576p50_16_9:
727b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            width = 720;
728b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            height = 576;
729b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fps = 50;
730b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            break;
731b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1280x720p50_16_9:
732b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            width = 1280;
733b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            height = 720;
734b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fps = 50;
735b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            break;
736b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1280x720p60_16_9:
737b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            width = 1280;
738b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            height = 720;
739b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fps = 60;
740b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            break;
741b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080p24_16_9:
742b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            width = 1920;
743b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            height = 1080;
744b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fps = 24;
745b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            break;
746b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080p25_16_9:
747b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            width = 1920;
748b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            height = 1080;
749b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fps = 25;
750b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            break;
751b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080p30_16_9:
752b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            width = 1920;
753b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            height = 1080;
754b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fps = 30;
755b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            break;
756b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080p50_16_9:
757b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            width = 1920;
758b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            height = 1080;
759b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fps = 50;
760b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            break;
761b166940edca6e312463461438e2aa66e9852c26aBenoit Goby        case m1920x1080p60_16_9:
762b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            width = 1920;
763b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            height = 1080;
764b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            fps = 60;
765b166940edca6e312463461438e2aa66e9852c26aBenoit Goby            break;
766b166940edca6e312463461438e2aa66e9852c26aBenoit Goby    }
767b166940edca6e312463461438e2aa66e9852c26aBenoit Goby}
768b166940edca6e312463461438e2aa66e9852c26aBenoit Goby
769b166940edca6e312463461438e2aa66e9852c26aBenoit Goby};
770