summaryrefslogtreecommitdiff
path: root/ips
diff options
context:
space:
mode:
authorAndy Qiu <junhai.qiu@intel.com>2013-09-12 15:19:06 -0700
committercactus <cactus@intel.com>2013-09-25 19:36:37 -0700
commit6a56bd739af22a3c34067426edbb3082504d8e03 (patch)
tree62c0e21199fb6885e5c6ff02ef6cec264b3fab47 /ips
parent44b16cd6030c452bac3e2d9e6bf44da759cb3ffe (diff)
downloadhwcomposer-6a56bd739af22a3c34067426edbb3082504d8e03.tar.gz
[hwc] enhance overlay management
BZ: 140456 This patch enables dynamic overlay assignment to different pipe. When overlay is assigned to a different pipe, HWC will first mark overlay is "disabled pending" and then query kernel whether it is fully disabled subsequently. Overlay can be re-enabled only when it is fully disabled, to avoid "overlay crash" issue. Change-Id: I26d3e94bc47770877aadf19992ea90e6c968e017 Signed-off-by: Andy Qiu <junhai.qiu@intel.com> Reviewed-on: http://android.intel.com:8080/131833 Reviewed-by: Patel, Hitesh K <hitesh.k.patel@intel.com> Tested-by: Patel, Hitesh K <hitesh.k.patel@intel.com> Reviewed-by: cactus <cactus@intel.com> Tested-by: cactus <cactus@intel.com>
Diffstat (limited to 'ips')
-rw-r--r--ips/common/OverlayPlaneBase.cpp65
-rw-r--r--ips/common/OverlayPlaneBase.h12
-rw-r--r--ips/tangier/TngOverlayPlane.cpp28
-rw-r--r--ips/tangier/TngOverlayPlane.h1
4 files changed, 101 insertions, 5 deletions
diff --git a/ips/common/OverlayPlaneBase.cpp b/ips/common/OverlayPlaneBase.cpp
index dcdb868..b9e2695 100644
--- a/ips/common/OverlayPlaneBase.cpp
+++ b/ips/common/OverlayPlaneBase.cpp
@@ -49,7 +49,10 @@ OverlayPlaneBase::OverlayPlaneBase(int index, int disp)
mActiveTTMBuffers(),
mBackBuffer(0),
mWsbm(0),
- mPipeConfig(0)
+ mPipeConfig(0),
+ mDisablePending(false),
+ mDisablePendingDevice(0),
+ mDisablePendingCount(0)
{
CTRACE();
}
@@ -94,6 +97,11 @@ bool OverlayPlaneBase::initialize(uint32_t bufferCount)
// disable overlay when created
flush(PLANE_DISABLE);
+
+ // overlay by default is in "disabled" status
+ mDisablePending = false;
+ mDisablePendingDevice = 0;
+ mDisablePendingCount = 0;
return true;
}
@@ -112,6 +120,25 @@ void OverlayPlaneBase::deinitialize()
DEINIT_AND_DELETE_OBJ(mWsbm);
}
+bool OverlayPlaneBase::setDataBuffer(uint32_t handle)
+{
+ if (mDisablePending) {
+ if (isFlushed() || mDisablePendingCount >= OVERLAY_DISABLING_COUNT_MAX) {
+ mDisablePending = false;
+ mDisablePendingDevice = 0;
+ mDisablePendingCount = 0;
+ enable();
+ } else {
+ mDisablePendingCount++;
+ WTRACE("overlay %d disabling on device %d is still pending, count: %d",
+ mIndex, mDisablePendingDevice, mDisablePendingCount);
+ return false;
+ }
+ }
+
+ return DisplayPlane::setDataBuffer(handle);
+}
+
void OverlayPlaneBase::invalidateBufferCache()
{
BufferMapper* mapper;
@@ -133,7 +160,7 @@ bool OverlayPlaneBase::assignToDevice(int disp)
uint32_t pipeConfig = 0;
RETURN_FALSE_IF_NOT_INIT();
- ATRACE("disp = %d", disp);
+ DTRACE("overlay %d assigned to disp %d", mIndex, disp);
switch (disp) {
case IDisplayDevice::DEVICE_EXTERNAL:
@@ -146,12 +173,18 @@ bool OverlayPlaneBase::assignToDevice(int disp)
}
// if pipe switching happened, then disable overlay first
- if (mPipeConfig != pipeConfig)
+ if (mPipeConfig != pipeConfig) {
+ DTRACE("overlay %d switched from %d to %d", mIndex, mDevice, disp);
disable();
+ }
mPipeConfig = pipeConfig;
mDevice = disp;
+ if (!mDisablePending) {
+ enable();
+ }
+
return true;
}
@@ -190,6 +223,19 @@ bool OverlayPlaneBase::reset()
{
RETURN_FALSE_IF_NOT_INIT();
+ if (mDisablePending) {
+ if (isFlushed() || mDisablePendingCount >= OVERLAY_DISABLING_COUNT_MAX) {
+ mDisablePending = false;
+ mDisablePendingDevice = 0;
+ mDisablePendingCount = 0;
+ } else {
+ mDisablePendingCount++;
+ WTRACE("overlay %d disabling is still pending on device %d, count %d",
+ mIndex, mDisablePendingDevice, mDisablePendingCount);
+ return false;
+ }
+ }
+
DisplayPlane::reset();
// invalidate active TTM buffers
@@ -200,8 +246,6 @@ bool OverlayPlaneBase::reset()
// reset back buffer
resetBackBuffer();
- // flush
- flush(PLANE_DISABLE);
return true;
}
@@ -232,10 +276,21 @@ bool OverlayPlaneBase::disable()
if (!(backBuffer->OCMD & 0x1))
return true;
+ if (mDisablePending) {
+ WTRACE("overlay %d disabling is still pending on device %d, skip disabling",
+ mIndex, mDisablePendingDevice);
+ return true;
+ }
+
backBuffer->OCMD &= ~0x1;
// flush
flush(PLANE_DISABLE);
+
+ // "disable" is asynchronous and needs at least one vsync to complete
+ mDisablePending = true;
+ mDisablePendingDevice = mDevice;
+ mDisablePendingCount = 0;
return true;
}
diff --git a/ips/common/OverlayPlaneBase.h b/ips/common/OverlayPlaneBase.h
index 46084b2..e18ee28 100644
--- a/ips/common/OverlayPlaneBase.h
+++ b/ips/common/OverlayPlaneBase.h
@@ -50,6 +50,8 @@ public:
OverlayPlaneBase(int index, int disp);
virtual ~OverlayPlaneBase();
+ virtual bool setDataBuffer(uint32_t handle);
+
virtual void invalidateBufferCache();
virtual bool assignToDevice(int disp);
@@ -69,6 +71,7 @@ public:
protected:
// generic overlay register flush
virtual bool flush(uint32_t flags) = 0;
+ virtual bool isFlushed() = 0;
virtual bool setDataBuffer(BufferMapper& mapper);
virtual bool bufferOffsetSetup(BufferMapper& mapper);
virtual uint32_t calculateSWidthSW(uint32_t offset, uint32_t width);
@@ -118,6 +121,15 @@ protected:
Wsbm *mWsbm;
// pipe config
uint32_t mPipeConfig;
+
+ // variables for asynchronous overlay disabling
+ enum {
+ // maximum wait count before aborting overlay disabling
+ OVERLAY_DISABLING_COUNT_MAX = 60,
+ };
+ bool mDisablePending;
+ bool mDisablePendingDevice;
+ int mDisablePendingCount;
};
} // namespace intel
diff --git a/ips/tangier/TngOverlayPlane.cpp b/ips/tangier/TngOverlayPlane.cpp
index e3cf7d7..bd9fcbe 100644
--- a/ips/tangier/TngOverlayPlane.cpp
+++ b/ips/tangier/TngOverlayPlane.cpp
@@ -185,6 +185,10 @@ bool TngOverlayPlane::flush(uint32_t flags)
// pipe select
arg.plane.ctx |= mPipeConfig;
+ if (flags & PLANE_DISABLE) {
+ DTRACE("disabling overlay %d on device %d", mIndex, mDevice);
+ }
+
// issue ioctl
Drm *drm = Hwcomposer::getInstance().getDrm();
bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
@@ -196,5 +200,29 @@ bool TngOverlayPlane::flush(uint32_t flags)
return true;
}
+bool TngOverlayPlane::isFlushed()
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ struct drm_psb_register_rw_arg arg;
+ memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
+
+ arg.overlay_read_mask = OVSTATUS_REGRBIT_OVR_UPDT;
+ arg.plane.type = DC_OVERLAY_PLANE;
+ arg.plane.index = mIndex;
+ arg.plane.ctx = 0;
+
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
+ if (ret == false) {
+ WTRACE("overlay read failed with error code %d", ret);
+ return false;
+ }
+
+ DTRACE("overlay %d flush status %s on device %d, current device %d",
+ mIndex, arg.plane.ctx ? "DONE" : "PENDING", mDisablePendingDevice, mDevice);
+ return arg.plane.ctx == 1;
+}
+
} // namespace intel
} // namespace android
diff --git a/ips/tangier/TngOverlayPlane.h b/ips/tangier/TngOverlayPlane.h
index 7c7e62c..22da8e0 100644
--- a/ips/tangier/TngOverlayPlane.h
+++ b/ips/tangier/TngOverlayPlane.h
@@ -56,6 +56,7 @@ public:
protected:
virtual bool setDataBuffer(BufferMapper& mapper);
virtual bool flush(uint32_t flags);
+ virtual bool isFlushed();
protected:
struct intel_dc_plane_ctx mContext;