external.cpp revision 0c8b7b5c841a7fad5df11b7e02d7cd792cfcc734
10c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed/*
20c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * Copyright (C) 2010 The Android Open Source Project
30c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
40c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed *
50c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * Not a Contribution, Apache license notifications and license are
60c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * retained for attribution purposes only.
70c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed *
80c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * Licensed under the Apache License, Version 2.0 (the "License");
90c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * you may not use this file except in compliance with the License.
100c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * You may obtain a copy of the License at
110c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed *
120c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed *      http://www.apache.org/licenses/LICENSE-2.0
130c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed *
140c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * Unless required by applicable law or agreed to in writing, software
150c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * distributed under the License is distributed on an "AS IS" BASIS,
160c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
170c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * See the License for the specific language governing permissions and
180c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed * limitations under the License.
190c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed */
200c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
210c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define EXT_OBSERVER_DEBUG 0
220c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <ctype.h>
230c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <binder/IPCThreadState.h>
240c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <binder/IServiceManager.h>
250c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <media/IAudioPolicyService.h>
260c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <media/AudioSystem.h>
270c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <utils/threads.h>
280c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <utils/Errors.h>
290c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <utils/Log.h>
300c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
310c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <linux/msm_mdp.h>
320c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <linux/fb.h>
330c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <sys/ioctl.h>
340c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <sys/poll.h>
350c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
360c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <hardware_legacy/uevent.h>
370c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include <cutils/properties.h>
380c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include "hwc_utils.h"
390c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#include "hwc_ext_observer.h"
400c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
410c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmednamespace qhwc {
420c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
430c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
440c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define DEVICE_ROOT "/sys/devices/virtual/graphics"
450c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define DEVICE_NODE "fb1"
460c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
470c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define SYSFS_CONNECTED         DEVICE_ROOT "/" DEVICE_NODE "/connected"
480c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define SYSFS_EDID_MODES        DEVICE_ROOT "/" DEVICE_NODE "/edid_modes"
490c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define SYSFS_HPD               DEVICE_ROOT "/" DEVICE_NODE "/hpd"
500c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
510c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
520c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedandroid::sp<ExtDisplayObserver> ExtDisplayObserver::
530c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                         sExtDisplayObserverInstance(0);
540c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
550c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer AhmedExtDisplayObserver::ExtDisplayObserver() : Thread(false),
560c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    fd(-1), mCurrentID(-1), mHwcContext(NULL)
570c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
580c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    //Enable HPD for HDMI
590c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    writeHPDOption(1);
600c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
610c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
620c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer AhmedExtDisplayObserver::~ExtDisplayObserver() {
630c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if (fd > 0)
640c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        close(fd);
650c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
660c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
670c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer AhmedExtDisplayObserver *ExtDisplayObserver::getInstance() {
680c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    ALOGD_IF(EXT_OBSERVER_DEBUG, "%s ", __FUNCTION__);
690c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if(sExtDisplayObserverInstance.get() == NULL)
700c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        sExtDisplayObserverInstance = new ExtDisplayObserver();
710c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    return sExtDisplayObserverInstance.get();
720c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
730c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
740c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedvoid ExtDisplayObserver::setHwcContext(hwc_context_t* hwcCtx) {
750c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__);
760c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if(hwcCtx) {
770c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        mHwcContext = hwcCtx;
780c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
790c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    return;
800c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
810c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedvoid ExtDisplayObserver::onFirstRef() {
820c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__);
830c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    run("ExtDisplayObserver", ANDROID_PRIORITY_DISPLAY);
840c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
850c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
860c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedint ExtDisplayObserver::readyToRun() {
870c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    //Initialize the uevent
880c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    uevent_init();
890c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: success", __FUNCTION__);
900c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    return android::NO_ERROR;
910c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
920c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
930c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedvoid ExtDisplayObserver::handleUEvent(char* str){
940c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int connected = 0;
950c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    // TODO: check for fb2(WFD) driver also
960c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if(!strcasestr(str, DEVICE_NODE))
970c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {
980c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
990c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        return;
1000c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
1010c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    // Event will be of the form:
1020c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    // change@/devices/virtual/graphics/fb1 ACTION=change
1030c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    // DEVPATH=/devices/virtual/graphics/fb1
1040c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    // SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29
1050c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    // for now just parse the online or offline are important for us.
1060c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if(!(strncmp(str,"online@",strlen("online@")))) {
1070c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__);
1080c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        connected = 1;
1090c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        readResolution();
1100c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        //Get the best mode and set
1110c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        // TODO: DO NOT call this for WFD
1120c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        setResolution(getBestMode());
1130c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    } else if(!(strncmp(str,"offline@",strlen("offline@")))) {
1140c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__);
1150c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        connected = 0;
1160c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        close(fd);
1170c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
1180c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    setExternalDisplayStatus(connected);
1190c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
1200c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1210c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedbool ExtDisplayObserver::threadLoop()
1220c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
1230c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    static char uEventString[1024];
1240c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    memset(uEventString, 0, sizeof(uEventString));
1250c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int count = uevent_next_event(uEventString, sizeof(uEventString));
1260c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if(count) {
1270c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: UeventString: %s len = %d",
1280c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                          __FUNCTION__, uEventString, count);
1290c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        handleUEvent(uEventString);
1300c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
1310c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    return true;
1320c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
1330c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1340c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedstruct disp_mode_timing_type {
1350c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int  video_format;
1360c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1370c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int  active_h;
1380c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int  active_v;
1390c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1400c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int  front_porch_h;
1410c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int  pulse_width_h;
1420c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int  back_porch_h;
1430c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1440c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int  front_porch_v;
1450c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int  pulse_width_v;
1460c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int  back_porch_v;
1470c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1480c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int  pixel_freq;
1490c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    bool interlaced;
1500c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1510c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    void set_info(struct fb_var_screeninfo &info) const;
1520c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed};
1530c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1540c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedvoid disp_mode_timing_type::set_info(struct fb_var_screeninfo &info) const
1550c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
1560c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.reserved[0] = 0;
1570c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.reserved[1] = 0;
1580c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.reserved[2] = 0;
1590c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.reserved[3] = video_format;
1600c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1610c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.xoffset = 0;
1620c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.yoffset = 0;
1630c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.xres = active_h;
1640c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.yres = active_v;
1650c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1660c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.pixclock = pixel_freq*1000;
1670c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.vmode = interlaced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
1680c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1690c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.right_margin = front_porch_h;
1700c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.hsync_len = pulse_width_h;
1710c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.left_margin = back_porch_h;
1720c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.lower_margin = front_porch_v;
1730c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.vsync_len = pulse_width_v;
1740c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    info.upper_margin = back_porch_v;
1750c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
1760c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1770c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed/* Video formates supported by the HDMI Standard */
1780c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed/* Indicates the resolution, pix clock and the aspect ratio */
1790c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m640x480p60_4_3         1
1800c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m720x480p60_4_3         2
1810c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m720x480p60_16_9        3
1820c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1280x720p60_16_9       4
1830c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1920x1080i60_16_9      5
1840c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1440x480i60_4_3        6
1850c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1440x480i60_16_9       7
1860c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1920x1080p60_16_9      16
1870c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m720x576p50_4_3         17
1880c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m720x576p50_16_9        18
1890c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1280x720p50_16_9       19
1900c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1440x576i50_4_3        21
1910c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1440x576i50_16_9       22
1920c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1920x1080p50_16_9      31
1930c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1920x1080p24_16_9      32
1940c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1920x1080p25_16_9      33
1950c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed#define m1920x1080p30_16_9      34
1960c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
1970c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedstatic struct disp_mode_timing_type supported_video_mode_lut[] = {
1980c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m640x480p60_4_3,     640,  480,  16,  96,  48, 10, 2, 33,  25200, false},
1990c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m720x480p60_4_3,     720,  480,  16,  62,  60,  9, 6, 30,  27030, false},
2000c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m720x480p60_16_9,    720,  480,  16,  62,  60,  9, 6, 30,  27030, false},
2010c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1280x720p60_16_9,  1280,  720, 110,  40, 220,  5, 5, 20,  74250, false},
2020c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1920x1080i60_16_9, 1920,  540,  88,  44, 148,  2, 5,  5,  74250, false},
2030c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1440x480i60_4_3,   1440,  240,  38, 124, 114,  4, 3, 15,  27000, true},
2040c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1440x480i60_16_9,  1440,  240,  38, 124, 114,  4, 3, 15,  27000, true},
2050c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1920x1080p60_16_9, 1920, 1080,  88,  44, 148,  4, 5, 36, 148500, false},
2060c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m720x576p50_4_3,     720,  576,  12,  64,  68,  5, 5, 39,  27000, false},
2070c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m720x576p50_16_9,    720,  576,  12,  64,  68,  5, 5, 39,  27000, false},
2080c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1280x720p50_16_9,  1280,  720, 440,  40, 220,  5, 5, 20,  74250, false},
2090c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1440x576i50_4_3,   1440,  288,  24, 126, 138,  2, 3, 19,  27000, true},
2100c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1440x576i50_16_9,  1440,  288,  24, 126, 138,  2, 3, 19,  27000, true},
2110c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1920x1080p50_16_9, 1920, 1080, 528,  44, 148,  4, 5, 36, 148500, false},
2120c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1920x1080p24_16_9, 1920, 1080, 638,  44, 148,  4, 5, 36,  74250, false},
2130c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1920x1080p25_16_9, 1920, 1080, 528,  44, 148,  4, 5, 36,  74250, false},
2140c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    {m1920x1080p30_16_9, 1920, 1080,  88,  44, 148,  4, 5, 36,  74250, false},
2150c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed};
2160c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedint ExtDisplayObserver::parseResolution(char* edidStr, int* edidModes, int len)
2170c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
2180c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    char delim = ',';
2190c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int count = 0;
2200c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    char *start, *end;
2210c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    // EDIDs are string delimited by ','
2220c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    // Ex: 16,4,5,3,32,34,1
2230c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    // Parse this string to get mode(int)
2240c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    start = (char*) edidStr;
2250c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    for(int i=0; i<len; i++) {
2260c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        edidModes[i] = (int) strtol(start, &end, 10);
2270c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        if(*end != delim) {
2280c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            // return as we reached end of string
2290c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return count;
2300c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        }
2310c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        start = end+1;
2320c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        count++;
2330c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
2340c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    return count;
2350c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
2360c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedbool ExtDisplayObserver::readResolution()
2370c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
2380c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int hdmiEDIDFile = open(SYSFS_EDID_MODES, O_RDONLY, 0);
2390c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int len = -1;
2400c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
2410c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    memset(mEDIDs, 0, sizeof(mEDIDs));
2420c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    memset(mEDIDModes, 0, sizeof(mEDIDModes));
2430c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    mModeCount = 0;
2440c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if (hdmiEDIDFile < 0) {
2450c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: edid_modes file '%s' not found",
2460c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                          __FUNCTION__, SYSFS_EDID_MODES);
2470c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        return false;
2480c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    } else {
2490c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        len = read(hdmiEDIDFile, mEDIDs, sizeof(mEDIDs)-1);
2500c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: EDID string: %s length = %d",
2510c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                               __FUNCTION__, mEDIDs, len);
2520c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        if ( len <= 0) {
2530c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: edid_modes file empty '%s'",
2540c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                           __FUNCTION__, SYSFS_EDID_MODES);
2550c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        }
2560c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        else {
2570c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            while (len > 1 && isspace(mEDIDs[len-1]))
2580c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                --len;
2590c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            mEDIDs[len] = 0;
2600c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        }
2610c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
2620c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    close(hdmiEDIDFile);
2630c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if(len > 0) {
2640c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        // GEt EDID modes from the EDID strings
2650c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        mModeCount = parseResolution(mEDIDs, mEDIDModes, len);
2660c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: mModeCount = %d", __FUNCTION__,
2670c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                                                  mModeCount);
2680c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
2690c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
2700c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    return (strlen(mEDIDs) > 0);
2710c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
2720c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
2730c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedbool ExtDisplayObserver::openFramebuffer()
2740c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
2750c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if (fd == -1) {
2760c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        fd = open("/dev/graphics/fb1", O_RDWR);
2770c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        if (fd < 0)
2780c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: /dev/graphics/fb1 not available"
2790c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                               "\n", __FUNCTION__);
2800c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
2810c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    return (fd > 0);
2820c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
2830c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
2840c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
2850c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedint ExtDisplayObserver::getModeOrder(int mode)
2860c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
2870c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    switch (mode) {
2880c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        default:
2890c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1440x480i60_4_3:
2900c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 1; // 480i 4:3
2910c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1440x480i60_16_9:
2920c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 2; // 480i 16:9
2930c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1440x576i50_4_3:
2940c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 3; // i576i 4:3
2950c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1440x576i50_16_9:
2960c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 4; // 576i 16:9
2970c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m640x480p60_4_3:
2980c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 5; // 640x480 4:3
2990c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m720x480p60_4_3:
3000c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 6; // 480p 4:3
3010c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m720x480p60_16_9:
3020c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 7; // 480p 16:9
3030c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m720x576p50_4_3:
3040c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 8; // 576p 4:3
3050c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m720x576p50_16_9:
3060c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 9; // 576p 16:9
3070c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1920x1080i60_16_9:
3080c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 10; // 1080i 16:9
3090c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1280x720p50_16_9:
3100c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 11; // 720p@50Hz
3110c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1280x720p60_16_9:
3120c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 12; // 720p@60Hz
3130c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1920x1080p24_16_9:
3140c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 13; //1080p@24Hz
3150c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1920x1080p25_16_9:
3160c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 14; //108-p@25Hz
3170c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1920x1080p30_16_9:
3180c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 15; //1080p@30Hz
3190c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1920x1080p50_16_9:
3200c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 16; //1080p@50Hz
3210c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        case m1920x1080p60_16_9:
3220c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            return 17; //1080p@60Hz
3230c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        }
3240c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
3250c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
3260c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed// Get the best mode for the current HD TV
3270c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedint ExtDisplayObserver::getBestMode() {
3280c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int bestOrder = 0;
3290c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int bestMode = m640x480p60_4_3;
3300c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
3310c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    // for all the edid read, get the best mode
3320c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    for(int i = 0; i < mModeCount; i++) {
3330c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        int mode = mEDIDModes[i];
3340c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        int order = getModeOrder(mode);
3350c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        if (order > bestOrder) {
3360c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            bestOrder = order;
3370c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            bestMode = mode;
3380c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        }
3390c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
3400c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    return bestMode;
3410c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
3420c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
3430c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedinline bool ExtDisplayObserver::isValidMode(int ID)
3440c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
3450c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    return ((ID >= m640x480p60_4_3) && (ID <= m1920x1080p30_16_9));
3460c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
3470c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
3480c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedvoid ExtDisplayObserver::setResolution(int ID)
3490c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
3500c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    struct fb_var_screeninfo info;
3510c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if (!openFramebuffer())
3520c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        return;
3530c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    //If its a valid mode and its a new ID - update var_screeninfo
3540c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if ((isValidMode(ID)) && mCurrentID != ID) {
3550c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        const struct disp_mode_timing_type *mode =
3560c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                                  &supported_video_mode_lut[0];
3570c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        unsigned count =  sizeof(supported_video_mode_lut)/sizeof
3580c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                                   (*supported_video_mode_lut);
3590c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        for (unsigned int i = 0; i < count; ++i) {
3600c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            const struct disp_mode_timing_type *cur =
3610c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                                 &supported_video_mode_lut[i];
3620c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            if (cur->video_format == ID)
3630c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                mode = cur;
3640c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        }
3650c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ioctl(fd, FBIOGET_VSCREENINFO, &info);
3660c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d),"
3670c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                "(%d,%d,%d) %dMHz>", __FUNCTION__,
3680c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                info.reserved[3], info.xres, info.yres,
3690c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                info.right_margin, info.hsync_len, info.left_margin,
3700c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                info.lower_margin, info.vsync_len, info.upper_margin,
3710c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                info.pixclock/1000/1000);
3720c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        mode->set_info(info);
3730c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx%d"
3740c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, ID,
3750c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                info.reserved[3], info.xres, info.yres,
3760c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                info.right_margin, info.hsync_len, info.left_margin,
3770c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                info.lower_margin, info.vsync_len, info.upper_margin,
3780c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                info.pixclock/1000/1000);
3790c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        info.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
3800c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ioctl(fd, FBIOPUT_VSCREENINFO, &info);
3810c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        mCurrentID = ID;
3820c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
3830c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    //Powerup
3840c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    ioctl(fd, FBIOBLANK, FB_BLANK_UNBLANK);
3850c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    ioctl(fd, FBIOGET_VSCREENINFO, &info);
3860c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    //Pan_Display
3870c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    ioctl(fd, FBIOPAN_DISPLAY, &info);
3880c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    property_set("hw.hdmiON", "1");
3890c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
3900c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
3910c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
3920c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedint  ExtDisplayObserver::getExternalDisplay() const
3930c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
3940c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed return mExternalDisplay;
3950c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
3960c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
3970c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedvoid ExtDisplayObserver::setExternalDisplayStatus(int connected)
3980c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
3990c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
4000c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    hwc_context_t* ctx = mHwcContext;
4010c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if(ctx) {
4020c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: status = %d", __FUNCTION__,
4030c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                                        connected);
4040c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        // Store the external display
4050c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        mExternalDisplay = connected;//(external_display_type)value;
4060c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        //Invalidate
4070c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0];
4080c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        if(!proc) {
4090c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: HWC proc not registered",
4100c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                                                __FUNCTION__);
4110c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        } else {
4120c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            /* Trigger redraw */
4130c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Invalidate !!", __FUNCTION__);
4140c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            proc->invalidate(proc);
4150c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        }
4160c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
4170c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    return;
4180c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
4190c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
4200c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmedbool ExtDisplayObserver::writeHPDOption(int userOption) const
4210c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed{
4220c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    bool ret = true;
4230c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    int hdmiHPDFile = open(SYSFS_HPD,O_RDWR, 0);
4240c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    if (hdmiHPDFile < 0) {
4250c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: state file '%s' not found : ret%d"
4260c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        "err str: %s",  __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno));
4270c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ret = false;
4280c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    } else {
4290c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        int err = -1;
4300c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: option = %d", __FUNCTION__,
4310c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                                            userOption);
4320c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        if(userOption)
4330c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            err = write(hdmiHPDFile, "1", 2);
4340c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        else
4350c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            err = write(hdmiHPDFile, "0" , 2);
4360c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        if (err <= 0) {
4370c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: file write failed '%s'",
4380c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed                                                __FUNCTION__, SYSFS_HPD);
4390c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed            ret = false;
4400c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        }
4410c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed        close(hdmiHPDFile);
4420c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    }
4430c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed    return ret;
4440c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed}
4450c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed};
4460c8b7b5c841a7fad5df11b7e02d7cd792cfcc734Naseer Ahmed
447