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