external.cpp revision 1589dee5c27293d278d3e549af8a4bda27e080f8
1ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed/*
2ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * Copyright (C) 2010 The Android Open Source Project
3ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
4ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed *
5ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * Not a Contribution, Apache license notifications and license are
6ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * retained for attribution purposes only.
7ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed *
8ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * Licensed under the Apache License, Version 2.0 (the "License");
9ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * you may not use this file except in compliance with the License.
10ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * You may obtain a copy of the License at
11ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed *
12ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed *      http://www.apache.org/licenses/LICENSE-2.0
13ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed *
14ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * Unless required by applicable law or agreed to in writing, software
15ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * distributed under the License is distributed on an "AS IS" BASIS,
16ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * See the License for the specific language governing permissions and
18ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed * limitations under the License.
19ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed */
20ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
211589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed#define DEBUG 0
22ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include <ctype.h>
231589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed#include <fcntl.h>
24ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include <media/IAudioPolicyService.h>
25ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include <media/AudioSystem.h>
26ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include <utils/threads.h>
27ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include <utils/Errors.h>
28ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include <utils/Log.h>
29ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
30ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include <linux/msm_mdp.h>
31ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include <linux/fb.h>
32ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include <sys/ioctl.h>
33ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include <sys/poll.h>
341589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed#include <sys/resource.h>
35ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include <cutils/properties.h>
36ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#include "hwc_utils.h"
371589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed#include "hwc_external.h"
38ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
39ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmednamespace qhwc {
40ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
41ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
42ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define DEVICE_ROOT "/sys/devices/virtual/graphics"
43ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define DEVICE_NODE "fb1"
44ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
45ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define SYSFS_CONNECTED         DEVICE_ROOT "/" DEVICE_NODE "/connected"
46ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define SYSFS_EDID_MODES        DEVICE_ROOT "/" DEVICE_NODE "/edid_modes"
47ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define SYSFS_HPD               DEVICE_ROOT "/" DEVICE_NODE "/hpd"
48ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
49ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
501589dee5c27293d278d3e549af8a4bda27e080f8Naseer AhmedExternalDisplay::ExternalDisplay(hwc_context_t* ctx):fd(-1),
511589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed    mCurrentID(-1), mHwcContext(ctx)
52ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed{
53ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    //Enable HPD for HDMI
54ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    writeHPDOption(1);
55ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
56ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
571589dee5c27293d278d3e549af8a4bda27e080f8Naseer AhmedExternalDisplay::~ExternalDisplay()
581589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed{
59ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    if (fd > 0)
60ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        close(fd);
61ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
62ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
63ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmedstruct disp_mode_timing_type {
64ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int  video_format;
65ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
66ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int  active_h;
67ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int  active_v;
68ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
69ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int  front_porch_h;
70ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int  pulse_width_h;
71ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int  back_porch_h;
72ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
73ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int  front_porch_v;
74ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int  pulse_width_v;
75ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int  back_porch_v;
76ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
77ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int  pixel_freq;
78ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    bool interlaced;
79ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
80ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    void set_info(struct fb_var_screeninfo &info) const;
81ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed};
82ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
83ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmedvoid disp_mode_timing_type::set_info(struct fb_var_screeninfo &info) const
84ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed{
85ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.reserved[0] = 0;
86ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.reserved[1] = 0;
87ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.reserved[2] = 0;
88ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.reserved[3] = video_format;
89ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
90ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.xoffset = 0;
91ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.yoffset = 0;
92ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.xres = active_h;
93ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.yres = active_v;
94ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
95ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.pixclock = pixel_freq*1000;
96ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.vmode = interlaced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
97ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
98ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.right_margin = front_porch_h;
99ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.hsync_len = pulse_width_h;
100ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.left_margin = back_porch_h;
101ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.lower_margin = front_porch_v;
102ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.vsync_len = pulse_width_v;
103ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    info.upper_margin = back_porch_v;
104ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
105ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
106ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed/* Video formates supported by the HDMI Standard */
107ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed/* Indicates the resolution, pix clock and the aspect ratio */
108ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m640x480p60_4_3         1
109ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m720x480p60_4_3         2
110ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m720x480p60_16_9        3
111ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1280x720p60_16_9       4
112ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1920x1080i60_16_9      5
113ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1440x480i60_4_3        6
114ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1440x480i60_16_9       7
115ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1920x1080p60_16_9      16
116ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m720x576p50_4_3         17
117ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m720x576p50_16_9        18
118ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1280x720p50_16_9       19
119ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1440x576i50_4_3        21
120ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1440x576i50_16_9       22
121ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1920x1080p50_16_9      31
122ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1920x1080p24_16_9      32
123ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1920x1080p25_16_9      33
124ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed#define m1920x1080p30_16_9      34
125ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
126ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmedstatic struct disp_mode_timing_type supported_video_mode_lut[] = {
127ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m640x480p60_4_3,     640,  480,  16,  96,  48, 10, 2, 33,  25200, false},
128ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m720x480p60_4_3,     720,  480,  16,  62,  60,  9, 6, 30,  27030, false},
129ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m720x480p60_16_9,    720,  480,  16,  62,  60,  9, 6, 30,  27030, false},
130ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1280x720p60_16_9,  1280,  720, 110,  40, 220,  5, 5, 20,  74250, false},
131ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1920x1080i60_16_9, 1920,  540,  88,  44, 148,  2, 5,  5,  74250, false},
132ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1440x480i60_4_3,   1440,  240,  38, 124, 114,  4, 3, 15,  27000, true},
133ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1440x480i60_16_9,  1440,  240,  38, 124, 114,  4, 3, 15,  27000, true},
134ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1920x1080p60_16_9, 1920, 1080,  88,  44, 148,  4, 5, 36, 148500, false},
135ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m720x576p50_4_3,     720,  576,  12,  64,  68,  5, 5, 39,  27000, false},
136ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m720x576p50_16_9,    720,  576,  12,  64,  68,  5, 5, 39,  27000, false},
137ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1280x720p50_16_9,  1280,  720, 440,  40, 220,  5, 5, 20,  74250, false},
138ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1440x576i50_4_3,   1440,  288,  24, 126, 138,  2, 3, 19,  27000, true},
139ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1440x576i50_16_9,  1440,  288,  24, 126, 138,  2, 3, 19,  27000, true},
140ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1920x1080p50_16_9, 1920, 1080, 528,  44, 148,  4, 5, 36, 148500, false},
141ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1920x1080p24_16_9, 1920, 1080, 638,  44, 148,  4, 5, 36,  74250, false},
142ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1920x1080p25_16_9, 1920, 1080, 528,  44, 148,  4, 5, 36,  74250, false},
143ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    {m1920x1080p30_16_9, 1920, 1080,  88,  44, 148,  4, 5, 36,  74250, false},
144ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed};
1451589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed
1461589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmedint ExternalDisplay::parseResolution(char* edidStr, int* edidModes, int len)
147ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed{
148ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    char delim = ',';
149ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int count = 0;
150ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    char *start, *end;
151ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    // EDIDs are string delimited by ','
152ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    // Ex: 16,4,5,3,32,34,1
153ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    // Parse this string to get mode(int)
154ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    start = (char*) edidStr;
155ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    for(int i=0; i<len; i++) {
156ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        edidModes[i] = (int) strtol(start, &end, 10);
157ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        if(*end != delim) {
158ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            // return as we reached end of string
159ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return count;
160ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        }
161ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        start = end+1;
162ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        count++;
163ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    }
164ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    return count;
165ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
1661589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmedbool ExternalDisplay::readResolution()
167ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed{
168ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int hdmiEDIDFile = open(SYSFS_EDID_MODES, O_RDONLY, 0);
169ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int len = -1;
170ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
171ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    memset(mEDIDs, 0, sizeof(mEDIDs));
172ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    memset(mEDIDModes, 0, sizeof(mEDIDModes));
173ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    mModeCount = 0;
174ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    if (hdmiEDIDFile < 0) {
1751589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        ALOGD_IF(DEBUG, "%s: edid_modes file '%s' not found",
1761589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 __FUNCTION__, SYSFS_EDID_MODES);
177ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        return false;
178ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    } else {
179ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        len = read(hdmiEDIDFile, mEDIDs, sizeof(mEDIDs)-1);
1801589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        ALOGD_IF(DEBUG, "%s: EDID string: %s length = %d",
1811589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 __FUNCTION__, mEDIDs, len);
182ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        if ( len <= 0) {
1831589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            ALOGD_IF(DEBUG, "%s: edid_modes file empty '%s'",
1841589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                     __FUNCTION__, SYSFS_EDID_MODES);
185ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        }
186ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        else {
187ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            while (len > 1 && isspace(mEDIDs[len-1]))
188ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed                --len;
189ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            mEDIDs[len] = 0;
190ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        }
191ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    }
192ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    close(hdmiEDIDFile);
193ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    if(len > 0) {
194ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        // GEt EDID modes from the EDID strings
195ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        mModeCount = parseResolution(mEDIDs, mEDIDModes, len);
1961589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__,
1971589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 mModeCount);
198ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    }
199ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
200ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    return (strlen(mEDIDs) > 0);
201ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
202ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
2031589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmedbool ExternalDisplay::openFramebuffer()
204ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed{
205ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    if (fd == -1) {
206ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        fd = open("/dev/graphics/fb1", O_RDWR);
207ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        if (fd < 0)
2081589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            ALOGD_IF(DEBUG, "%s: /dev/graphics/fb1 not available"
2091589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                     "\n", __FUNCTION__);
210ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    }
211ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    return (fd > 0);
212ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
213ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
214ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
2151589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmedint ExternalDisplay::getModeOrder(int mode)
216ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed{
217ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    switch (mode) {
218ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        default:
219ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1440x480i60_4_3:
220ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 1; // 480i 4:3
221ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1440x480i60_16_9:
222ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 2; // 480i 16:9
223ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1440x576i50_4_3:
224ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 3; // i576i 4:3
225ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1440x576i50_16_9:
226ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 4; // 576i 16:9
227ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m640x480p60_4_3:
228ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 5; // 640x480 4:3
229ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m720x480p60_4_3:
230ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 6; // 480p 4:3
231ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m720x480p60_16_9:
232ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 7; // 480p 16:9
233ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m720x576p50_4_3:
234ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 8; // 576p 4:3
235ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m720x576p50_16_9:
236ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 9; // 576p 16:9
237ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1920x1080i60_16_9:
238ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 10; // 1080i 16:9
239ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1280x720p50_16_9:
240ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 11; // 720p@50Hz
241ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1280x720p60_16_9:
242ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 12; // 720p@60Hz
243ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1920x1080p24_16_9:
244ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 13; //1080p@24Hz
245ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1920x1080p25_16_9:
246ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 14; //108-p@25Hz
247ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1920x1080p30_16_9:
248ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 15; //1080p@30Hz
249ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1920x1080p50_16_9:
250ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 16; //1080p@50Hz
251ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        case m1920x1080p60_16_9:
252ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            return 17; //1080p@60Hz
2531589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed    }
254ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
255ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
256ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed// Get the best mode for the current HD TV
2571589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmedint ExternalDisplay::getBestMode() {
258ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int bestOrder = 0;
259ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int bestMode = m640x480p60_4_3;
260ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
261ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    // for all the edid read, get the best mode
262ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    for(int i = 0; i < mModeCount; i++) {
263ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        int mode = mEDIDModes[i];
264ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        int order = getModeOrder(mode);
265ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        if (order > bestOrder) {
266ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            bestOrder = order;
267ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            bestMode = mode;
268ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        }
269ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    }
270ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    return bestMode;
2711589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed}
272ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
2731589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmedinline bool ExternalDisplay::isValidMode(int ID)
274ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed{
275ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    return ((ID >= m640x480p60_4_3) && (ID <= m1920x1080p30_16_9));
276ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
277ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
2781589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmedvoid ExternalDisplay::setResolution(int ID)
279ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed{
280ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    struct fb_var_screeninfo info;
281ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    if (!openFramebuffer())
282ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        return;
283ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    //If its a valid mode and its a new ID - update var_screeninfo
284ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    if ((isValidMode(ID)) && mCurrentID != ID) {
285ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        const struct disp_mode_timing_type *mode =
2861589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            &supported_video_mode_lut[0];
287ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        unsigned count =  sizeof(supported_video_mode_lut)/sizeof
2881589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            (*supported_video_mode_lut);
289ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        for (unsigned int i = 0; i < count; ++i) {
290ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            const struct disp_mode_timing_type *cur =
2911589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                &supported_video_mode_lut[i];
292ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            if (cur->video_format == ID)
293ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed                mode = cur;
294ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        }
295ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        ioctl(fd, FBIOGET_VSCREENINFO, &info);
2961589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        ALOGD_IF(DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d),"
2971589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 "(%d,%d,%d) %dMHz>", __FUNCTION__,
2981589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 info.reserved[3], info.xres, info.yres,
2991589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 info.right_margin, info.hsync_len, info.left_margin,
3001589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 info.lower_margin, info.vsync_len, info.upper_margin,
3011589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 info.pixclock/1000/1000);
302ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        mode->set_info(info);
3031589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        ALOGD_IF(DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx%d"
3041589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, ID,
3051589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 info.reserved[3], info.xres, info.yres,
3061589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 info.right_margin, info.hsync_len, info.left_margin,
3071589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 info.lower_margin, info.vsync_len, info.upper_margin,
3081589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 info.pixclock/1000/1000);
309ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        info.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
310ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        ioctl(fd, FBIOPUT_VSCREENINFO, &info);
311ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        mCurrentID = ID;
312ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    }
313ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    //Powerup
314ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    ioctl(fd, FBIOBLANK, FB_BLANK_UNBLANK);
315ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    ioctl(fd, FBIOGET_VSCREENINFO, &info);
316ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    //Pan_Display
317ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    ioctl(fd, FBIOPAN_DISPLAY, &info);
318ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    property_set("hw.hdmiON", "1");
319ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
320ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
321ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
3221589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmedint  ExternalDisplay::getExternalDisplay() const
323ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed{
3241589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed    return mExternalDisplay;
325ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
326ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
3271589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmedvoid ExternalDisplay::setExternalDisplayStatus(int connected)
328ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed{
329ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
330ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    hwc_context_t* ctx = mHwcContext;
331ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    if(ctx) {
3321589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        ALOGD_IF(DEBUG, "%s: status = %d", __FUNCTION__,
3331589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 connected);
3341589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        if(connected) {
3351589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            readResolution();
3361589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            //Get the best mode and set
3371589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            // TODO: DO NOT call this for WFD
3381589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            setResolution(getBestMode());
3391589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        } else {
3401589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            close(fd);
3411589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        }
342ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        // Store the external display
3431589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        mExternalDisplay = connected;
344ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        //Invalidate
345ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0];
346ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        if(!proc) {
3471589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            ALOGD_IF(DEBUG, "%s: HWC proc not registered",
3481589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                     __FUNCTION__);
349ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        } else {
350ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            /* Trigger redraw */
3511589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            ALOGD_IF(DEBUG, "%s: Invalidate !!", __FUNCTION__);
352ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            proc->invalidate(proc);
353ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        }
354ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    }
355ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    return;
356ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
357ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
3581589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmedbool ExternalDisplay::writeHPDOption(int userOption) const
359ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed{
360ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    bool ret = true;
361ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    int hdmiHPDFile = open(SYSFS_HPD,O_RDWR, 0);
362ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    if (hdmiHPDFile < 0) {
3631589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        ALOGD_IF(DEBUG, "%s: state file '%s' not found : ret%d"
3641589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 "err str: %s",  __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno));
365ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        ret = false;
366ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    } else {
367ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        int err = -1;
3681589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed        ALOGD_IF(DEBUG, "%s: option = %d", __FUNCTION__,
3691589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                 userOption);
370ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        if(userOption)
371ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            err = write(hdmiHPDFile, "1", 2);
372ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        else
373ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            err = write(hdmiHPDFile, "0" , 2);
374ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        if (err <= 0) {
3751589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed            ALOGD_IF(DEBUG, "%s: file write failed '%s'",
3761589dee5c27293d278d3e549af8a4bda27e080f8Naseer Ahmed                     __FUNCTION__, SYSFS_HPD);
377ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed            ret = false;
378ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        }
379ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed        close(hdmiHPDFile);
380ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    }
381ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed    return ret;
382ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed}
383ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed};
384ccf943e44f9e9d615a6019459625148830039f8dNaseer Ahmed
385