Merge "hwc_composer: Support of WFD Display." into jb

This commit is contained in:
Linux Build Service Account 2012-08-09 03:11:01 -07:00 committed by QuIC Gerrit Code Review
commit 31168fad8f
4 changed files with 131 additions and 57 deletions

View File

@ -77,6 +77,9 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list)
hwc_context_t* ctx = (hwc_context_t*)(dev);
ctx->overlayInUse = false;
if(ctx->mExtDisplay->getExternalDisplay())
ovutils::setExtType(ctx->mExtDisplay->getExternalDisplay());
//Prepare is called after a vsync, so unlock previous buffers here.
ctx->qbuf->unlockAllPrevious();

View File

@ -38,20 +38,20 @@
namespace qhwc {
#define DEVICE_ROOT "/sys/devices/virtual/graphics"
#define DEVICE_NODE "fb1"
#define SYSFS_EDID_MODES DEVICE_ROOT "/" DEVICE_NODE "/edid_modes"
#define SYSFS_HPD DEVICE_ROOT "/" DEVICE_NODE "/hpd"
static const char *extPanelName[MAX_DISPLAY_EXTERNAL_DEVICES] = {
HDMI_PANEL,
WFD_PANEL
};
ExternalDisplay::ExternalDisplay(hwc_context_t* ctx):mFd(-1),
mCurrentMode(-1), mHwcContext(ctx)
{
memset(&mVInfo, 0, sizeof(mVInfo));
//Enable HPD for HDMI
writeHPDOption(1);
if(isHDMIConfigured()) {
writeHPDOption(1);
}
}
ExternalDisplay::~ExternalDisplay()
@ -197,12 +197,16 @@ bool ExternalDisplay::readResolution()
return (strlen(mEDIDs) > 0);
}
bool ExternalDisplay::openFramebuffer()
const char* msmFbDevicePath[2] = { "/dev/graphics/fb1",
"/dev/graphics/fb2"};
bool ExternalDisplay::openFrameBuffer(int fbNum)
{
if (mFd == -1) {
mFd = open("/dev/graphics/fb1", O_RDWR);
mFd = open(msmFbDevicePath[fbNum-1], O_RDWR);
if (mFd < 0)
ALOGE("%s: /dev/graphics/fb1 not available", __FUNCTION__);
ALOGE("%s: %s not available", __FUNCTION__, msmFbDevicePath[fbNum-1]);
}
return (mFd > 0);
}
@ -294,7 +298,7 @@ void ExternalDisplay::setResolution(int ID)
{
struct fb_var_screeninfo info;
int ret = 0;
if (!openFramebuffer())
if (!openFrameBuffer(EXTERN_DISPLAY_FB1))
return;
ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo);
if(ret < 0) {
@ -354,32 +358,85 @@ void ExternalDisplay::setResolution(int ID)
}
}
/*
* This function queries the msm_fb_type for fb1 and checks whether it is
* HDMI or not
*
* Returns:
* 0 -> WFD device
* 1 -> HDMI device
*/
bool ExternalDisplay::isHDMIConfigured() {
bool configured = false;
FILE *displayDeviceFP = NULL;
char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
int ExternalDisplay::getExternalDisplay() const
{
return mExternalDisplay;
displayDeviceFP = fopen("/sys/class/graphics/fb1/msm_fb_type", "r");
if(displayDeviceFP) {
fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE, displayDeviceFP);
if(!strncmp(fbType, extPanelName[0], sizeof(extPanelName[0]))) {
configured = true;
}
fclose(displayDeviceFP);
}
return configured;
}
void ExternalDisplay::processUEventOffline(const char *str) {
const char *s1 = str + (strlen(str)-strlen(DEVICE_NODE_FB1));
// check if it is for FB1
if(strncmp(s1,DEVICE_NODE_FB1, strlen(DEVICE_NODE_FB1))== 0) {
enableHDMIVsync(EXTERN_DISPLAY_NONE);
closeFrameBuffer();
resetInfo();
setExternalDisplay(EXTERN_DISPLAY_NONE);
}
else if(strncmp(s1, DEVICE_NODE_FB2, strlen(DEVICE_NODE_FB2)) == 0) {
closeFrameBuffer();
setExternalDisplay(EXTERN_DISPLAY_NONE);
}
}
void ExternalDisplay::processUEventOnline(const char *str) {
const char *s1 = str + (strlen(str)-strlen(DEVICE_NODE_FB1));
// check if it is for FB1
if(strncmp(s1,DEVICE_NODE_FB1, strlen(DEVICE_NODE_FB1))== 0) {
if(isHDMIConfigured()) {
// HDMI connect event.
// Tear-down WFD if it is active.
if(mExternalDisplay == EXTERN_DISPLAY_FB2) {
closeFrameBuffer();
setExternalDisplay(EXTERN_DISPLAY_NONE);
}
}
readResolution();
//Get the best mode and set
setResolution(getBestMode());
enableHDMIVsync(EXTERN_DISPLAY_FB1);
setExternalDisplay(EXTERN_DISPLAY_FB1);
}
else if(strncmp(s1, DEVICE_NODE_FB2, strlen(DEVICE_NODE_FB2)) == 0) {
// WFD connect event
if(mExternalDisplay == EXTERN_DISPLAY_FB1) {
// HDMI has higher priority.
// Do Not Override.
}else {
// WFD is connected
openFrameBuffer(EXTERN_DISPLAY_FB2);
setExternalDisplay(EXTERN_DISPLAY_FB2);
}
}
}
void ExternalDisplay::setExternalDisplay(int connected)
{
hwc_context_t* ctx = mHwcContext;
if(ctx) {
ALOGD_IF(DEBUG, "%s: status = %d", __FUNCTION__,
connected);
if(connected) {
readResolution();
//Get the best mode and set
// TODO: DO NOT call this for WFD
setResolution(getBestMode());
//enable hdmi vsync
enableHDMIVsync(connected);
} else {
// Disable the hdmi vsync
enableHDMIVsync(connected);
closeFrameBuffer();
resetInfo();
}
// Store the external display
mExternalDisplay = connected;
const char* prop = (connected) ? "1" : "0";
@ -388,8 +445,7 @@ void ExternalDisplay::setExternalDisplay(int connected)
//Invalidate
hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0];
if(!proc) {
ALOGE("%s: HWC proc not registered",
__FUNCTION__);
ALOGE("%s: HWC proc not registered", __FUNCTION__);
} else {
/* Trigger redraw */
ALOGD_IF(DEBUG, "%s: Invalidate !!", __FUNCTION__);

View File

@ -27,6 +27,25 @@ struct hwc_context_t;
namespace qhwc {
#define DEVICE_ROOT "/sys/devices/virtual/graphics"
#define DEVICE_NODE_FB1 "fb1"
#define DEVICE_NODE_FB2 "fb2"
#define HDMI_PANEL "dtv panel"
#define WFD_PANEL "writeback panel"
#define EXTERN_DISPLAY_NONE 0
#define EXTERN_DISPLAY_FB1 1
#define EXTERN_DISPLAY_FB2 2
#define MAX_FRAME_BUFFER_NAME_SIZE 80
#define MAX_DISPLAY_EXTERNAL_DEVICES 2
#define HPD_ENABLE 1
#define HPD_DISABLE 0
#define DEVICE_ONLINE true
#define DEVICE_OFFLINE false
#define SYSFS_EDID_MODES DEVICE_ROOT "/" DEVICE_NODE_FB1 "/edid_modes"
#define SYSFS_HPD DEVICE_ROOT "/" DEVICE_NODE_FB1 "/hpd"
class ExternalDisplay
{
//Type of external display - OFF, HDMI, WFD
@ -44,16 +63,19 @@ class ExternalDisplay
public:
ExternalDisplay(hwc_context_t* ctx);
~ExternalDisplay();
int getExternalDisplay() const;
inline int getExternalDisplay() { return mExternalDisplay; }
void setExternalDisplay(int connected);
bool commit();
int enableHDMIVsync(int enable);
void processUEventOnline(const char *str);
void processUEventOffline(const char *str);
bool isHDMIConfigured();
private:
bool readResolution();
int parseResolution(char* edidStr, int* edidModes);
void setResolution(int ID);
bool openFramebuffer();
bool openFrameBuffer(int fbNum);
bool closeFrameBuffer();
bool writeHPDOption(int userOption) const;
bool isValidMode(int ID);

View File

@ -18,8 +18,8 @@
* limitations under the License.
*/
#define DEBUG 0
#ifndef HWC_OBSERVER_H
#define HWC_OBSERVER_H
#ifndef HWC_UEVENTS_H
#define HWC_UEVENTS_H
#include <hardware_legacy/uevent.h>
#include <utils/Log.h>
#include <sys/resource.h>
@ -32,12 +32,11 @@ namespace qhwc {
const char* MSMFB_DEVICE_FB0 = "change@/devices/virtual/graphics/fb0";
const char* MSMFB_DEVICE_FB1 = "change@/devices/virtual/graphics/fb1";
const char* MSMFB_HDMI_NODE = "fb1";
const char* MSMFB_FB_NODE = "fb";
static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
{
int vsync = 0;
char* hdmi;
int64_t timestamp = 0;
const char *str = udata;
hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0];
@ -48,12 +47,12 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
return;
}
if(hdmiconnected)
if(ctx->mExtDisplay->isHDMIConfigured() &&
(hdmiconnected == EXTERN_DISPLAY_FB1))
vsync = !strncmp(str, MSMFB_DEVICE_FB1, strlen(MSMFB_DEVICE_FB1));
else
vsync = !strncmp(str, MSMFB_DEVICE_FB0, strlen(MSMFB_DEVICE_FB0));
hdmi = strcasestr(str, MSMFB_HDMI_NODE);
if(vsync) {
str += strlen(str) + 1;
while(*str) {
@ -68,24 +67,18 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
return;
}
if(hdmi) {
// parse HDMI events
// The event will be of the form:
// change@/devices/virtual/graphics/fb1 ACTION=change
// DEVPATH=/devices/virtual/graphics/fb1
// SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29
// for now just parsing onlin/offline info is enough
str = udata;
int connected = 0;
if(!(strncmp(str,"online@",strlen("online@")))) {
connected = 1;
ctx->mExtDisplay->setExternalDisplay(connected);
} else if(!(strncmp(str,"offline@",strlen("offline@")))) {
connected = 0;
ctx->mExtDisplay->setExternalDisplay(connected);
}
// parse HDMI events
// The event will be of the form:
// change@/devices/virtual/graphics/fb1 ACTION=change
// DEVPATH=/devices/virtual/graphics/fb1
// SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29
// for now just parsing onlin/offline info is enough
str = udata;
if(!(strncmp(str,"online@",strlen("online@")))) {
ctx->mExtDisplay->processUEventOnline(str);
} else if(!(strncmp(str,"offline@",strlen("offline@")))) {
ctx->mExtDisplay->processUEventOffline(str);
}
}
static void *uevent_loop(void *param)
@ -113,4 +106,4 @@ void init_uevent_thread(hwc_context_t* ctx)
}
}; //namespace
#endif //HWC_OBSERVER_H
#endif //HWC_UEVENTS_H