Merge "hwc_composer: Support of WFD Display." into jb
This commit is contained in:
commit
31168fad8f
@ -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();
|
||||
|
||||
|
@ -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__);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user