qdutils: Retrieve MDP revision and pipes information from driver.

Userspace can retrieve MDP revision number and number of different
types of MDP pipes (RGB,VG,DMA) information from driver. Add target
specific flag as previous MDP versions do not provide this support.

- Make use of this information while maintaining PipeBook.
- Move PipeBook related functions from overlay utils to PipeBook.

Change-Id: I46578bb27e515c4b9525d90b6619c11d7749914f
This commit is contained in:
Sushil Chauhan
2013-03-06 15:36:49 -08:00
parent f02fdc7d0c
commit 07a2c7660c
8 changed files with 154 additions and 131 deletions

View File

@@ -27,6 +27,7 @@ endif
ifeq ($(call is-board-platform-in-list, msm8974 msm8226), true) ifeq ($(call is-board-platform-in-list, msm8974 msm8226), true)
common_flags += -DVENUS_COLOR_FORMAT common_flags += -DVENUS_COLOR_FORMAT
common_flags += -DMDSS_TARGET
endif endif
common_deps := common_deps :=

View File

@@ -70,12 +70,13 @@ static void openFramebufferDevice(hwc_context_t *ctx)
void initContext(hwc_context_t *ctx) void initContext(hwc_context_t *ctx)
{ {
openFramebufferDevice(ctx); openFramebufferDevice(ctx);
overlay::Overlay::initOverlay();
ctx->mOverlay = overlay::Overlay::getInstance();
ctx->mRotMgr = new RotMgr();
ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion(); ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay(); ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType(); ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
overlay::Overlay::initOverlay();
ctx->mOverlay = overlay::Overlay::getInstance();
ctx->mRotMgr = new RotMgr();
//Is created and destroyed only once for primary //Is created and destroyed only once for primary
//For external it could get created and destroyed multiple times depending //For external it could get created and destroyed multiple times depending
//on what external we connect to. //on what external we connect to.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@@ -37,12 +37,7 @@ namespace overlay {
using namespace utils; using namespace utils;
Overlay::Overlay() { Overlay::Overlay() {
int numPipes = 0; PipeBook::NUM_PIPES = qdutils::MDPVersion::getInstance().getTotalPipes();
int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
if (mdpVersion > qdutils::MDP_V3_1) numPipes = 4;
if (mdpVersion >= qdutils::MDSS_V5) numPipes = 8;
PipeBook::NUM_PIPES = numPipes;
for(int i = 0; i < PipeBook::NUM_PIPES; i++) { for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
mPipeBook[i].init(); mPipeBook[i].init();
} }
@@ -74,8 +69,8 @@ void Overlay::configDone() {
//fds //fds
if(mPipeBook[i].valid()) { if(mPipeBook[i].valid()) {
char str[32]; char str[32];
sprintf(str, "Unset pipe=%s dpy=%d; ", getDestStr((eDest)i), sprintf(str, "Unset pipe=%s dpy=%d; ",
mPipeBook[i].mDisplay); PipeBook::getDestStr((eDest)i), mPipeBook[i].mDisplay);
strncat(mDumpStr, str, strlen(str)); strncat(mDumpStr, str, strlen(str));
} }
mPipeBook[i].destroy(); mPipeBook[i].destroy();
@@ -90,7 +85,7 @@ eDest Overlay::nextPipe(eMdpPipeType type, int dpy) {
for(int i = 0; i < PipeBook::NUM_PIPES; i++) { for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
//Match requested pipe type //Match requested pipe type
if(type == OV_MDP_PIPE_ANY || type == getPipeType((eDest)i)) { if(type == OV_MDP_PIPE_ANY || type == PipeBook::getPipeType((eDest)i)) {
//If the pipe is not allocated to any display or used by the //If the pipe is not allocated to any display or used by the
//requesting display already in previous round. //requesting display already in previous round.
if((mPipeBook[i].mDisplay == PipeBook::DPY_UNUSED || if((mPipeBook[i].mDisplay == PipeBook::DPY_UNUSED ||
@@ -111,7 +106,8 @@ eDest Overlay::nextPipe(eMdpPipeType type, int dpy) {
if(not mPipeBook[index].valid()) { if(not mPipeBook[index].valid()) {
mPipeBook[index].mPipe = new GenericPipe(dpy); mPipeBook[index].mPipe = new GenericPipe(dpy);
char str[32]; char str[32];
snprintf(str, 32, "Set pipe=%s dpy=%d; ", getDestStr(dest), dpy); snprintf(str, 32, "Set pipe=%s dpy=%d; ",
PipeBook::getDestStr(dest), dpy);
strncat(mDumpStr, str, strlen(str)); strncat(mDumpStr, str, strlen(str));
} }
} else { } else {
@@ -183,13 +179,13 @@ void Overlay::setSource(const utils::PipeArgs args,
validate(index); validate(index);
PipeArgs newArgs(args); PipeArgs newArgs(args);
if(dest == OV_VG0 || dest == OV_VG1) { if(PipeBook::getPipeType(dest) == OV_MDP_PIPE_VG) {
setMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_SHARE); setMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_SHARE);
} else { } else {
clearMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_SHARE); clearMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_SHARE);
} }
if(dest == OV_DMA0 || dest == OV_DMA1) { if(PipeBook::getPipeType(dest) == OV_MDP_PIPE_DMA) {
setMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_FORCE_DMA); setMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_FORCE_DMA);
} else { } else {
clearMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_FORCE_DMA); clearMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_FORCE_DMA);
@@ -205,10 +201,68 @@ Overlay* Overlay::getInstance() {
return sInstance; return sInstance;
} }
void Overlay::initOverlay() { // Clears any VG pipes allocated to the fb devices
if(utils::initOverlay() == -1) { // Generates a LUT for pipe types.
ALOGE("%s failed", __FUNCTION__); int Overlay::initOverlay() {
int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
int numPipesXType[OV_MDP_PIPE_ANY] = {0};
numPipesXType[OV_MDP_PIPE_RGB] =
qdutils::MDPVersion::getInstance().getRGBPipes();
numPipesXType[OV_MDP_PIPE_VG] =
qdutils::MDPVersion::getInstance().getVGPipes();
numPipesXType[OV_MDP_PIPE_DMA] =
qdutils::MDPVersion::getInstance().getDMAPipes();
int index = 0;
for(int X = 0; X < (int)OV_MDP_PIPE_ANY; X++) { //iterate over types
for(int j = 0; j < numPipesXType[X]; j++) { //iterate over num
PipeBook::pipeTypeLUT[index] = (utils::eMdpPipeType)X;
index++;
}
} }
if (mdpVersion < qdutils::MDSS_V5) {
msmfb_mixer_info_req req;
mdp_mixer_info *minfo = NULL;
char name[64];
int fd = -1;
for(int i = 0; i < NUM_FB_DEVICES; i++) {
snprintf(name, 64, FB_DEVICE_TEMPLATE, i);
ALOGD("initoverlay:: opening the device:: %s", name);
fd = ::open(name, O_RDWR, 0);
if(fd < 0) {
ALOGE("cannot open framebuffer(%d)", i);
return -1;
}
//Get the mixer configuration */
req.mixer_num = i;
if (ioctl(fd, MSMFB_MIXER_INFO, &req) == -1) {
ALOGE("ERROR: MSMFB_MIXER_INFO ioctl failed");
close(fd);
return -1;
}
minfo = req.info;
for (int j = 0; j < req.cnt; j++) {
ALOGD("ndx=%d num=%d z_order=%d", minfo->pndx, minfo->pnum,
minfo->z_order);
// except the RGB base layer with z_order of -1, clear any
// other pipes connected to mixer.
if((minfo->z_order) != -1) {
int index = minfo->pndx;
ALOGD("Unset overlay with index: %d at mixer %d", index, i);
if(ioctl(fd, MSMFB_OVERLAY_UNSET, &index) == -1) {
ALOGE("ERROR: MSMFB_OVERLAY_UNSET failed");
close(fd);
return -1;
}
}
minfo++;
}
close(fd);
fd = -1;
}
}
return 0;
} }
void Overlay::dump() const { void Overlay::dump() const {
@@ -254,5 +308,7 @@ int Overlay::PipeBook::NUM_PIPES = 0;
int Overlay::PipeBook::sPipeUsageBitmap = 0; int Overlay::PipeBook::sPipeUsageBitmap = 0;
int Overlay::PipeBook::sLastUsageBitmap = 0; int Overlay::PipeBook::sLastUsageBitmap = 0;
int Overlay::PipeBook::sAllocatedBitmap = 0; int Overlay::PipeBook::sAllocatedBitmap = 0;
utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
{utils::OV_MDP_PIPE_ANY};
}; // namespace overlay }; // namespace overlay

View File

@@ -68,7 +68,7 @@ public:
bool queueBuffer(int fd, uint32_t offset, utils::eDest dest); bool queueBuffer(int fd, uint32_t offset, utils::eDest dest);
/* Closes open pipes, called during startup */ /* Closes open pipes, called during startup */
static void initOverlay(); static int initOverlay();
/* Returns the singleton instance of overlay */ /* Returns the singleton instance of overlay */
static Overlay* getInstance(); static Overlay* getInstance();
/* Returns available ("unallocated") pipes for a display */ /* Returns available ("unallocated") pipes for a display */
@@ -116,7 +116,12 @@ private:
static bool isAllocated(int index); static bool isAllocated(int index);
static bool isNotAllocated(int index); static bool isNotAllocated(int index);
static utils::eMdpPipeType getPipeType(utils::eDest dest);
static const char* getDestStr(utils::eDest dest);
static int NUM_PIPES; static int NUM_PIPES;
static utils::eMdpPipeType pipeTypeLUT[utils::OV_MAX];
private: private:
//usage tracks if a successful commit happened. So a pipe could be //usage tracks if a successful commit happened. So a pipe could be
@@ -146,7 +151,7 @@ inline void Overlay::validate(int index) {
OVASSERT(index >=0 && index < PipeBook::NUM_PIPES, \ OVASSERT(index >=0 && index < PipeBook::NUM_PIPES, \
"%s, Index out of bounds: %d", __FUNCTION__, index); "%s, Index out of bounds: %d", __FUNCTION__, index);
OVASSERT(mPipeBook[index].valid(), "Pipe does not exist %s", OVASSERT(mPipeBook[index].valid(), "Pipe does not exist %s",
utils::getDestStr((utils::eDest)index)); PipeBook::getDestStr((utils::eDest)index));
} }
inline int Overlay::availablePipes(int dpy) { inline int Overlay::availablePipes(int dpy) {
@@ -212,6 +217,20 @@ inline bool Overlay::PipeBook::isNotAllocated(int index) {
return !isAllocated(index); return !isAllocated(index);
} }
inline utils::eMdpPipeType Overlay::PipeBook::getPipeType(utils::eDest dest) {
return pipeTypeLUT[(int)dest];
}
inline const char* Overlay::PipeBook::getDestStr(utils::eDest dest) {
switch(getPipeType(dest)) {
case utils::OV_MDP_PIPE_RGB: return "RGB";
case utils::OV_MDP_PIPE_VG: return "VG";
case utils::OV_MDP_PIPE_DMA: return "DMA";
default: return "Invalid";
}
return "Invalid";
}
}; // overlay }; // overlay
#endif // OVERLAY_H #endif // OVERLAY_H

View File

@@ -84,58 +84,6 @@ const char* const Res::barrierFile =
namespace utils { namespace utils {
//------------------ defines -----------------------------
#define FB_DEVICE_TEMPLATE "/dev/graphics/fb%u"
#define NUM_FB_DEVICES 3
//--------------------------------------------------------
/* clears any VG pipes allocated to the fb devices */
int initOverlay() {
int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
if (mdpVersion < qdutils::MDSS_V5) {
msmfb_mixer_info_req req;
mdp_mixer_info *minfo = NULL;
char name[64];
int fd = -1;
for(int i = 0; i < NUM_FB_DEVICES; i++) {
snprintf(name, 64, FB_DEVICE_TEMPLATE, i);
ALOGD("initoverlay:: opening the device:: %s", name);
fd = ::open(name, O_RDWR, 0);
if(fd < 0) {
ALOGE("cannot open framebuffer(%d)", i);
return -1;
}
//Get the mixer configuration */
req.mixer_num = i;
if (ioctl(fd, MSMFB_MIXER_INFO, &req) == -1) {
ALOGE("ERROR: MSMFB_MIXER_INFO ioctl failed");
close(fd);
return -1;
}
minfo = req.info;
for (int j = 0; j < req.cnt; j++) {
ALOGD("ndx=%d num=%d z_order=%d", minfo->pndx, minfo->pnum,
minfo->z_order);
// except the RGB base layer with z_order of -1, clear any
// other pipes connected to mixer.
if((minfo->z_order) != -1) {
int index = minfo->pndx;
ALOGD("Unset overlay with index: %d at mixer %d", index, i);
if(ioctl(fd, MSMFB_OVERLAY_UNSET, &index) == -1) {
ALOGE("ERROR: MSMFB_OVERLAY_UNSET failed");
close(fd);
return -1;
}
}
minfo++;
}
close(fd);
fd = -1;
}
}
return 0;
}
//-------------------------------------------------------- //--------------------------------------------------------
//Refer to graphics.h, gralloc_priv.h, msm_mdp.h //Refer to graphics.h, gralloc_priv.h, msm_mdp.h

View File

@@ -77,6 +77,9 @@
#define MDP_OV_PIPE_FORCE_DMA 0x4000 #define MDP_OV_PIPE_FORCE_DMA 0x4000
#endif #endif
#define FB_DEVICE_TEMPLATE "/dev/graphics/fb%u"
#define NUM_FB_DEVICES 3
namespace overlay { namespace overlay {
// fwd // fwd
@@ -127,11 +130,6 @@ enum { INPUT_3D_MASK = 0xFFFF0000,
enum { BARRIER_LAND = 1, enum { BARRIER_LAND = 1,
BARRIER_PORT = 2 }; BARRIER_PORT = 2 };
/* if SurfaceFlinger process gets killed in bypass mode, In initOverlay()
* close all the pipes if it is opened after reboot.
*/
int initOverlay(void);
inline uint32_t format3D(uint32_t x) { return x & 0xFF000; } inline uint32_t format3D(uint32_t x) { return x & 0xFF000; }
inline uint32_t format3DOutput(uint32_t x) { inline uint32_t format3DOutput(uint32_t x) {
return (x & 0xF000) >> SHIFT_OUT_3D; } return (x & 0xF000) >> SHIFT_OUT_3D; }
@@ -274,24 +272,27 @@ enum eZorder {
}; };
enum eMdpPipeType { enum eMdpPipeType {
OV_MDP_PIPE_RGB, OV_MDP_PIPE_RGB = 0,
OV_MDP_PIPE_VG, OV_MDP_PIPE_VG,
OV_MDP_PIPE_DMA, OV_MDP_PIPE_DMA,
OV_MDP_PIPE_ANY, //Any OV_MDP_PIPE_ANY, //Any
}; };
/* Used to identify destination pipes // Identify destination pipes
*/ // TODO Names useless, replace with int and change all interfaces
enum eDest { enum eDest {
OV_VG0 = 0, OV_P0 = 0,
OV_RGB0, OV_P1,
OV_VG1, OV_P2,
OV_RGB1, OV_P3,
OV_VG2, OV_P4,
OV_RGB2, OV_P5,
OV_DMA0, OV_P6,
OV_DMA1, OV_P7,
OV_P8,
OV_P9,
OV_INVALID, OV_INVALID,
OV_MAX = OV_INVALID,
}; };
/* Used when a buffer is split over 2 pipes and sent to display */ /* Used when a buffer is split over 2 pipes and sent to display */
@@ -350,6 +351,12 @@ struct PipeArgs {
eRotFlags rotFlags; eRotFlags rotFlags;
}; };
// Cannot use HW_OVERLAY_MAGNIFICATION_LIMIT, since at the time
// of integration, HW_OVERLAY_MAGNIFICATION_LIMIT was a define
enum { HW_OV_MAGNIFICATION_LIMIT = 20,
HW_OV_MINIFICATION_LIMIT = 8
};
inline void setMdpFlags(eMdpFlags& f, eMdpFlags v) { inline void setMdpFlags(eMdpFlags& f, eMdpFlags v) {
f = static_cast<eMdpFlags>(setBit(f, v)); f = static_cast<eMdpFlags>(setBit(f, v));
} }
@@ -390,12 +397,6 @@ int getDownscaleFactor(const int& src_w, const int& src_h,
int getMdpOrient(eTransform rotation); int getMdpOrient(eTransform rotation);
const char* getFormatString(int format); const char* getFormatString(int format);
// Cannot use HW_OVERLAY_MAGNIFICATION_LIMIT, since at the time
// of integration, HW_OVERLAY_MAGNIFICATION_LIMIT was a define
enum { HW_OV_MAGNIFICATION_LIMIT = 20,
HW_OV_MINIFICATION_LIMIT = 8
};
template <class T> template <class T>
inline void memset0(T& t) { ::memset(&t, 0, sizeof(T)); } inline void memset0(T& t) { ::memset(&t, 0, sizeof(T)); }
@@ -687,40 +688,6 @@ inline void even_floor(T& value) {
value--; value--;
} }
inline const char* getDestStr(eDest dest) {
switch(dest) {
case OV_VG0: return "VG0";
case OV_RGB0: return "RGB0";
case OV_VG1: return "VG1";
case OV_RGB1: return "RGB1";
case OV_VG2: return "VG2";
case OV_RGB2: return "RGB2";
case OV_DMA0: return "DMA0";
case OV_DMA1: return "DMA1";
default: return "Invalid";
}
return "Invalid";
}
inline eMdpPipeType getPipeType(eDest dest) {
switch(dest) {
case OV_VG0:
case OV_VG1:
case OV_VG2:
return OV_MDP_PIPE_VG;
case OV_RGB0:
case OV_RGB1:
case OV_RGB2:
return OV_MDP_PIPE_RGB;
case OV_DMA0:
case OV_DMA1:
return OV_MDP_PIPE_DMA;
default:
return OV_MDP_PIPE_ANY;
}
return OV_MDP_PIPE_ANY;
}
void preRotateSource(eTransform& tr, Whf& whf, Dim& srcCrop); void preRotateSource(eTransform& tr, Whf& whf, Dim& srcCrop);
void getDump(char *buf, size_t len, const char *prefix, const mdp_overlay& ov); void getDump(char *buf, size_t len, const char *prefix, const mdp_overlay& ov);
void getDump(char *buf, size_t len, const char *prefix, const msmfb_img& ov); void getDump(char *buf, size_t len, const char *prefix, const msmfb_img& ov);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@@ -28,7 +28,9 @@
*/ */
#include <cutils/log.h> #include <cutils/log.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/msm_mdp.h>
#include "mdp_version.h" #include "mdp_version.h"
ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::MDPVersion); ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::MDPVersion);
@@ -40,6 +42,11 @@ MDPVersion::MDPVersion()
int mdp_version = MDP_V_UNKNOWN; int mdp_version = MDP_V_UNKNOWN;
char panel_type = 0; char panel_type = 0;
struct fb_fix_screeninfo fb_finfo; struct fb_fix_screeninfo fb_finfo;
mMdpRev = 0;
mRGBPipes = mVGPipes = 0;
mDMAPipes = 0;
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_finfo) < 0) { if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_finfo) < 0) {
ALOGE("FBIOGET_FSCREENINFO failed"); ALOGE("FBIOGET_FSCREENINFO failed");
mdp_version = MDP_V_UNKNOWN; mdp_version = MDP_V_UNKNOWN;
@@ -57,8 +64,24 @@ MDPVersion::MDPVersion()
if (mdp_version < 100) if (mdp_version < 100)
mdp_version *= 10; mdp_version *= 10;
mRGBPipes = mVGPipes = 2;
} else if (!strncmp(fb_finfo.id, "mdssfb", 6)) { } else if (!strncmp(fb_finfo.id, "mdssfb", 6)) {
mdp_version = MDSS_V5; mdp_version = MDSS_V5;
#ifdef MDSS_TARGET
struct msmfb_metadata metadata;
memset(&metadata, 0 , sizeof(metadata));
metadata.op = metadata_op_get_caps;
if (ioctl(fb_fd, MSMFB_METADATA_GET, &metadata) == -1) {
ALOGE("Error retrieving MDP revision and pipes info");
mdp_version = MDP_V_UNKNOWN;
} else {
mMdpRev = metadata.data.caps.mdp_rev;
mRGBPipes = metadata.data.caps.rgb_pipes;
mVGPipes = metadata.data.caps.vig_pipes;
mDMAPipes = metadata.data.caps.dma_pipes;
}
#endif
} else { } else {
mdp_version = MDP_V_UNKNOWN; mdp_version = MDP_V_UNKNOWN;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@@ -72,10 +72,18 @@ public:
int getMDPVersion() {return mMDPVersion;} int getMDPVersion() {return mMDPVersion;}
char getPanelType() {return mPanelType;} char getPanelType() {return mPanelType;}
bool hasOverlay() {return mHasOverlay;} bool hasOverlay() {return mHasOverlay;}
uint8_t getTotalPipes() { return (mRGBPipes + mVGPipes + mDMAPipes);}
uint8_t getRGBPipes() { return mRGBPipes; }
uint8_t getVGPipes() { return mVGPipes; }
uint8_t getDMAPipes() { return mDMAPipes; }
private: private:
int mMDPVersion; int mMDPVersion;
char mPanelType; char mPanelType;
bool mHasOverlay; bool mHasOverlay;
uint32_t mMdpRev;
uint8_t mRGBPipes;
uint8_t mVGPipes;
uint8_t mDMAPipes;
}; };
}; //namespace qdutils }; //namespace qdutils
#endif //INCLUDE_LIBQCOMUTILS_MDPVER #endif //INCLUDE_LIBQCOMUTILS_MDPVER