summaryrefslogtreecommitdiff
path: root/moorefield_hdmi/ips
diff options
context:
space:
mode:
authorGuilhem IMBERTON <guilhem.imberton@intel.com>2015-04-03 13:57:46 +0200
committerHeather Lee Wilson <hwilson@google.com>2015-04-09 12:11:42 -0700
commit5094bbf4cbe9b244d79ce5ec52a9285978fff311 (patch)
treef3c9f619ca67165bee2817109110faaaae9c4cf4 /moorefield_hdmi/ips
parent8b0063f7f46289983bd1bf9ca61662b4a2ddf5b6 (diff)
downloadhwcomposer-5094bbf4cbe9b244d79ce5ec52a9285978fff311.tar.gz
Moving Moorefield HWComposer in dedicated directory
Fugu HWComposer has been widely modified to fit HDMI only. The current version does not support Marvin product based on Merrifield platform. We are moving both HWComposer to dedicated folders as a first integration step. Merge will happen later. Change-Id: Iebe90a7bd95c017eca63310fd23b32d53dfccb72 Signed-off-by: Guilhem IMBERTON <guilhem.imberton@intel.com>
Diffstat (limited to 'moorefield_hdmi/ips')
-rw-r--r--moorefield_hdmi/ips/anniedale/AnnCursorPlane.cpp248
-rw-r--r--moorefield_hdmi/ips/anniedale/AnnCursorPlane.h59
-rwxr-xr-xmoorefield_hdmi/ips/anniedale/AnnOverlayPlane.cpp916
-rwxr-xr-xmoorefield_hdmi/ips/anniedale/AnnOverlayPlane.h85
-rwxr-xr-xmoorefield_hdmi/ips/anniedale/AnnPlaneManager.cpp424
-rw-r--r--moorefield_hdmi/ips/anniedale/AnnPlaneManager.h48
-rwxr-xr-xmoorefield_hdmi/ips/anniedale/AnnRGBPlane.cpp384
-rwxr-xr-xmoorefield_hdmi/ips/anniedale/AnnRGBPlane.h61
-rwxr-xr-xmoorefield_hdmi/ips/anniedale/PlaneCapabilities.cpp244
-rw-r--r--moorefield_hdmi/ips/common/BlankControl.cpp43
-rw-r--r--moorefield_hdmi/ips/common/BlankControl.h36
-rw-r--r--moorefield_hdmi/ips/common/DrmConfig.cpp79
-rw-r--r--moorefield_hdmi/ips/common/DrmControl.cpp58
-rw-r--r--moorefield_hdmi/ips/common/DrmControl.h38
-rw-r--r--moorefield_hdmi/ips/common/GrallocBufferBase.cpp92
-rw-r--r--moorefield_hdmi/ips/common/GrallocBufferBase.h41
-rw-r--r--moorefield_hdmi/ips/common/GrallocBufferMapperBase.cpp72
-rw-r--r--moorefield_hdmi/ips/common/GrallocBufferMapperBase.h52
-rw-r--r--moorefield_hdmi/ips/common/GrallocSubBuffer.h35
-rw-r--r--moorefield_hdmi/ips/common/HdcpControl.cpp380
-rw-r--r--moorefield_hdmi/ips/common/HdcpControl.h87
-rw-r--r--moorefield_hdmi/ips/common/OverlayHardware.h160
-rwxr-xr-xmoorefield_hdmi/ips/common/OverlayPlaneBase.cpp1199
-rw-r--r--moorefield_hdmi/ips/common/OverlayPlaneBase.h125
-rw-r--r--moorefield_hdmi/ips/common/PixelFormat.cpp56
-rw-r--r--moorefield_hdmi/ips/common/PixelFormat.h41
-rw-r--r--moorefield_hdmi/ips/common/RotationBufferProvider.cpp624
-rw-r--r--moorefield_hdmi/ips/common/RotationBufferProvider.h101
-rw-r--r--moorefield_hdmi/ips/common/SpritePlaneBase.cpp53
-rw-r--r--moorefield_hdmi/ips/common/SpritePlaneBase.h51
-rw-r--r--moorefield_hdmi/ips/common/TTMBufferMapper.cpp103
-rw-r--r--moorefield_hdmi/ips/common/TTMBufferMapper.h70
-rw-r--r--moorefield_hdmi/ips/common/VideoPayloadBuffer.h84
-rw-r--r--moorefield_hdmi/ips/common/VsyncControl.cpp84
-rw-r--r--moorefield_hdmi/ips/common/VsyncControl.h43
-rw-r--r--moorefield_hdmi/ips/common/Wsbm.cpp136
-rw-r--r--moorefield_hdmi/ips/common/Wsbm.h47
-rw-r--r--moorefield_hdmi/ips/common/WsbmWrapper.c401
-rw-r--r--moorefield_hdmi/ips/common/WsbmWrapper.h41
-rwxr-xr-xmoorefield_hdmi/ips/tangier/TngDisplayContext.cpp276
-rwxr-xr-xmoorefield_hdmi/ips/tangier/TngDisplayContext.h51
-rwxr-xr-xmoorefield_hdmi/ips/tangier/TngDisplayQuery.cpp88
-rw-r--r--moorefield_hdmi/ips/tangier/TngGrallocBuffer.cpp62
-rw-r--r--moorefield_hdmi/ips/tangier/TngGrallocBuffer.h44
-rw-r--r--moorefield_hdmi/ips/tangier/TngGrallocBufferMapper.cpp245
-rw-r--r--moorefield_hdmi/ips/tangier/TngGrallocBufferMapper.h50
46 files changed, 7717 insertions, 0 deletions
diff --git a/moorefield_hdmi/ips/anniedale/AnnCursorPlane.cpp b/moorefield_hdmi/ips/anniedale/AnnCursorPlane.cpp
new file mode 100644
index 0000000..e85a529
--- /dev/null
+++ b/moorefield_hdmi/ips/anniedale/AnnCursorPlane.cpp
@@ -0,0 +1,248 @@
+/*
+// Copyright (c) 2014 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <common/utils/HwcTrace.h>
+#include <Hwcomposer.h>
+#include <BufferManager.h>
+#include <ips/anniedale/AnnCursorPlane.h>
+#include <ips/tangier/TngGrallocBuffer.h>
+#include <hal_public.h>
+
+namespace android {
+namespace intel {
+
+AnnCursorPlane::AnnCursorPlane(int index, int disp)
+ : DisplayPlane(index, PLANE_CURSOR, disp)
+{
+ CTRACE();
+ memset(&mContext, 0, sizeof(mContext));
+ memset(&mCrop, 0, sizeof(mCrop));
+}
+
+AnnCursorPlane::~AnnCursorPlane()
+{
+ CTRACE();
+}
+
+bool AnnCursorPlane::enable()
+{
+ return enablePlane(true);
+}
+
+bool AnnCursorPlane::disable()
+{
+ return enablePlane(false);
+}
+
+bool AnnCursorPlane::reset()
+{
+ // clear mCrop once reset
+ memset(&mCrop, 0, sizeof(mCrop));
+ return true;
+}
+
+void* AnnCursorPlane::getContext() const
+{
+ CTRACE();
+ return (void *)&mContext;
+}
+
+void AnnCursorPlane::setZOrderConfig(ZOrderConfig& config, void *nativeConfig)
+{
+ (void) config;
+ (void) nativeConfig;
+
+ CTRACE();
+}
+
+bool AnnCursorPlane::setDataBuffer(uint32_t handle)
+{
+ bool ret;
+
+ if (!handle) {
+ ELOGTRACE("handle is NULL");
+ return false;
+ }
+
+ ret = DisplayPlane::setDataBuffer(handle);
+ if (ret == false) {
+ ELOGTRACE("failed to set data buffer");
+ return ret;
+ }
+
+ return true;
+}
+
+bool AnnCursorPlane::setDataBuffer(BufferMapper& mapper)
+{
+ int w = mapper.getWidth();
+ int h = mapper.getHeight();
+ int cursorSize = 0;
+
+ CTRACE();
+
+ // setup plane position
+ int dstX = mPosition.x;
+ int dstY = mPosition.y;
+ int dstW = mPosition.w;
+ int dstH = mPosition.h;
+
+ if (h < w) {
+ cursorSize = h;
+ } else {
+ cursorSize = w;
+ }
+
+ uint32_t cntr = 0;
+ if (64 <= cursorSize && cursorSize < 128) {
+ cursorSize = 64;
+ cntr = 0x7;
+ } else if (128 <= cursorSize && cursorSize < 256) {
+ cursorSize = 128;
+ cntr = 0x2;
+ } else {
+ cursorSize = 256;
+ cntr = 0x3;
+ }
+
+ if (mapper.getFormat() == HAL_PIXEL_FORMAT_RGBA_8888) {
+ cntr |= 1 << 5;
+ } else if (mapper.getFormat() == HAL_PIXEL_FORMAT_BGRA_8888) {
+ // swap color from BGRA to RGBA - alpha is MSB
+ uint8_t *p = (uint8_t *)(mapper.getCpuAddress(0));
+ uint8_t *srcPixel;
+ uint32_t stride = mapper.getStride().rgb.stride;
+ uint8_t temp;
+ if (!p) {
+ return false;
+ }
+
+ for (int i = 0; i < cursorSize; i++) {
+ for (int j = 0; j < cursorSize; j++) {
+ srcPixel = p + i*stride + j*4;
+ temp = srcPixel[0];
+ srcPixel[0] = srcPixel[2];
+ srcPixel[2] = temp;
+ }
+ }
+ cntr |= 1 << 5;
+ } else {
+ ELOGTRACE("invalid color format");
+ return false;
+ }
+
+ // TODO: clean spare mem to be 0 in gralloc instead
+ uint8_t *p = (uint8_t *)(mapper.getCpuAddress(0));
+ uint8_t *srcPixel;
+ uint32_t stride = mapper.getStride().rgb.stride;
+ uint8_t temp;
+ if (!p) {
+ return false;
+ }
+
+ if (mCrop.w == 0 && mCrop.h == 0) {
+ mCrop = mSrcCrop;
+ for (int i = 0; i < cursorSize; i++) {
+ for (int j = 0; j < cursorSize; j++) {
+ srcPixel = p + i*stride + j*4;
+ temp = srcPixel[0];
+ if (i >= mCrop.h || j >= mCrop.w) {
+ if (srcPixel[0] == 0 &&
+ srcPixel[3] == 0xff)
+ srcPixel[3] = 0;
+ }
+ }
+ }
+ }
+
+ // update context
+ mContext.type = DC_CURSOR_PLANE;
+ mContext.ctx.cs_ctx.index = mIndex;
+ mContext.ctx.cs_ctx.pipe = mDevice;
+ mContext.ctx.cs_ctx.cntr = cntr;
+ mContext.ctx.cs_ctx.surf = mapper.getGttOffsetInPage(0) << 12;
+
+ mContext.ctx.cs_ctx.pos = 0;
+ if (dstX < 0) {
+ mContext.ctx.cs_ctx.pos |= 1 << 15;
+ dstX = -dstX;
+ }
+ if (dstY < 0) {
+ mContext.ctx.cs_ctx.pos |= 1 << 31;
+ dstY = -dstY;
+ }
+ mContext.ctx.cs_ctx.pos |= (dstY & 0xfff) << 16 | (dstX & 0xfff);
+ return true;
+}
+
+bool AnnCursorPlane::enablePlane(bool enabled)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ struct drm_psb_register_rw_arg arg;
+ memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
+ if (enabled) {
+ arg.plane_enable_mask = 1;
+ } else {
+ arg.plane_disable_mask = 1;
+ }
+
+ arg.plane.type = DC_CURSOR_PLANE;
+ arg.plane.index = mIndex;
+ arg.plane.ctx = 0;
+
+ // issue ioctl
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
+ if (ret == false) {
+ WLOGTRACE("plane enabling (%d) failed with error code %d", enabled, ret);
+ return false;
+ }
+
+ return true;
+}
+
+bool AnnCursorPlane::isDisabled()
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ struct drm_psb_register_rw_arg arg;
+ memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
+
+ arg.plane.type = DC_CURSOR_PLANE;
+ arg.get_plane_state_mask = 1;
+ arg.plane.index = mIndex;
+ arg.plane.ctx = 0;
+
+ // issue ioctl
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
+ if (ret == false) {
+ WLOGTRACE("plane state query failed with error code %d", ret);
+ return false;
+ }
+
+ return arg.plane.ctx == PSB_DC_PLANE_DISABLED;
+}
+
+void AnnCursorPlane::postFlip()
+{
+ // prevent mUpdateMasks from being reset
+ // skipping flip may cause flicking
+}
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/anniedale/AnnCursorPlane.h b/moorefield_hdmi/ips/anniedale/AnnCursorPlane.h
new file mode 100644
index 0000000..7f2d099
--- /dev/null
+++ b/moorefield_hdmi/ips/anniedale/AnnCursorPlane.h
@@ -0,0 +1,59 @@
+/*
+// Copyright (c) 2014 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#ifndef ANN_CUR_PLANE_H
+#define ANN_CUR_PLANE_H
+
+#include <utils/KeyedVector.h>
+#include <hal_public.h>
+#include <Hwcomposer.h>
+#include <common/buffers/BufferCache.h>
+#include <DisplayPlane.h>
+
+#include <linux/psb_drm.h>
+
+namespace android {
+namespace intel {
+
+class AnnCursorPlane : public DisplayPlane {
+public:
+ AnnCursorPlane(int index, int disp);
+ virtual ~AnnCursorPlane();
+public:
+ // hardware operations
+ bool enable();
+ bool disable();
+ bool reset();
+ bool isDisabled();
+ void postFlip();
+
+ void* getContext() const;
+ void setZOrderConfig(ZOrderConfig& config, void *nativeConfig);
+
+ bool setDataBuffer(uint32_t handle);
+protected:
+ bool setDataBuffer(BufferMapper& mapper);
+ bool enablePlane(bool enabled);
+
+protected:
+ struct intel_dc_plane_ctx mContext;
+ crop_t mCrop;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* ANN_RGB_PLANE_H */
diff --git a/moorefield_hdmi/ips/anniedale/AnnOverlayPlane.cpp b/moorefield_hdmi/ips/anniedale/AnnOverlayPlane.cpp
new file mode 100755
index 0000000..8b63101
--- /dev/null
+++ b/moorefield_hdmi/ips/anniedale/AnnOverlayPlane.cpp
@@ -0,0 +1,916 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <math.h>
+#include <common/utils/HwcTrace.h>
+#include <common/base/Drm.h>
+#include <Hwcomposer.h>
+#include <ips/anniedale/AnnOverlayPlane.h>
+#include <ips/tangier/TngGrallocBuffer.h>
+#include <khronos/openmax/OMX_IntelVideoExt.h>
+#include <DisplayQuery.h>
+
+namespace android {
+namespace intel {
+
+AnnOverlayPlane::AnnOverlayPlane(int index, int disp)
+ : OverlayPlaneBase(index, disp),
+ mRotationBufProvider(NULL),
+ mRotationConfig(0),
+ mZOrderConfig(0),
+ mUseOverlayRotation(true)
+{
+ CTRACE();
+
+ memset(&mContext, 0, sizeof(mContext));
+}
+
+AnnOverlayPlane::~AnnOverlayPlane()
+{
+ CTRACE();
+}
+
+bool AnnOverlayPlane::setDataBuffer(uint32_t handle)
+{
+ if (handle == 0) {
+ ELOGTRACE("handle == 0");
+ return true;
+ }
+
+ if (mForceScaling) {
+ BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
+ ssize_t index = mScalingBufferMap.indexOfKey(handle);
+ if (index < 0) {
+ mScalingTarget = bm->allocGrallocBuffer(
+ mSrcCrop.w,
+ mSrcCrop.h,
+ DisplayQuery::queryNV12Format(),
+ GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_VIDEO_ENCODER);
+ if (!mScalingTarget) {
+ ELOGTRACE("Failed to allocate gralloc buffer.");
+ return false;
+ }
+
+ if (mScalingBufferMap.size() >= MAX_SCALING_BUF_COUNT) {
+ while (!mScalingBufferMap.isEmpty()) {
+ uint32_t handle = mScalingBufferMap.valueAt(0);
+ bm->freeGrallocBuffer(handle);
+ mScalingBufferMap.removeItemsAt(0);
+ }
+ }
+
+ mScalingBufferMap.add(handle, mScalingTarget);
+ } else {
+ mScalingTarget = mScalingBufferMap.valueAt(index);
+ }
+
+ mScalingSource = handle;
+ handle = mScalingTarget;
+ }
+
+ return DisplayPlane::setDataBuffer(handle);
+}
+
+void AnnOverlayPlane::setZOrderConfig(ZOrderConfig& /* zorderConfig */,
+ void *nativeConfig)
+{
+ int slot = (int)nativeConfig;
+
+ CTRACE();
+
+ switch (slot) {
+ case 0:
+ mZOrderConfig = 0;
+ break;
+ case 1:
+ mZOrderConfig = (1 << 8);
+ break;
+ case 2:
+ mZOrderConfig = (2 << 8);
+ break;
+ case 3:
+ mZOrderConfig = (3 << 8);
+ break;
+ default:
+ ELOGTRACE("Invalid overlay plane zorder %d", slot);
+ return;
+ }
+}
+
+bool AnnOverlayPlane::reset()
+{
+ while (!mScalingBufferMap.isEmpty()) {
+ uint32_t handle = mScalingBufferMap.valueAt(0);
+ Hwcomposer::getInstance().getBufferManager()->freeGrallocBuffer(handle);
+ mScalingBufferMap.removeItemsAt(0);
+ }
+
+ OverlayPlaneBase::reset();
+ if (mRotationBufProvider) {
+ mRotationBufProvider->reset();
+ }
+ return true;
+}
+
+bool AnnOverlayPlane::enable()
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ // by default always use overlay rotation
+ mUseOverlayRotation = true;
+
+ if (mContext.ctx.ov_ctx.ovadd & (0x1 << 15))
+ return true;
+
+ mContext.ctx.ov_ctx.ovadd |= (0x1 << 15);
+
+ // flush
+ flush(PLANE_ENABLE);
+
+ return true;
+}
+
+bool AnnOverlayPlane::disable()
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ if (!(mContext.ctx.ov_ctx.ovadd & (0x1 << 15)))
+ return true;
+
+ mContext.ctx.ov_ctx.ovadd &= ~(0x1 << 15);
+
+ mContext.ctx.ov_ctx.ovadd &= ~(0x300);
+
+ mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
+
+ // flush
+ flush(PLANE_DISABLE);
+
+ return true;
+}
+
+void AnnOverlayPlane::postFlip()
+{
+ // when using AnnOverlayPlane through AnnDisplayPlane as proxy, postFlip is never
+ // called so mUpdateMasks is never reset.
+ // When using AnnOverlayPlane directly, postFlip is invoked and mUpdateMasks is reset
+ // post-flip.
+
+ // need to check why mUpdateMasks = 0 causes video freeze.
+
+ //DisplayPlane::postFlip();
+}
+
+
+void AnnOverlayPlane::resetBackBuffer(int buf)
+{
+ CTRACE();
+
+ if (!mBackBuffer[buf] || !mBackBuffer[buf]->buf)
+ return;
+
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[buf]->buf;
+
+ memset(backBuffer, 0, sizeof(OverlayBackBufferBlk));
+
+ // reset overlay
+ backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) |
+ (OVERLAY_INIT_BRIGHTNESS & 0xff);
+ backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION;
+ backBuffer->DCLRKV = OVERLAY_INIT_COLORKEY;
+ backBuffer->DCLRKM = OVERLAY_INIT_COLORKEYMASK;
+ backBuffer->OCONFIG = 0;
+ backBuffer->OCONFIG |= (0x1 << 27);
+ // use 3 line buffers
+ backBuffer->OCONFIG |= 0x1;
+ backBuffer->SCHRKEN &= ~(0x7 << 24);
+ backBuffer->SCHRKEN |= 0xff;
+}
+
+bool AnnOverlayPlane::bufferOffsetSetup(BufferMapper& mapper)
+{
+ CTRACE();
+
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
+ if (!backBuffer) {
+ ELOGTRACE("invalid back buffer");
+ return false;
+ }
+
+ uint32_t format = mapper.getFormat();
+ uint32_t gttOffsetInBytes = (mapper.getGttOffsetInPage(0) << 12);
+
+ if (format == HAL_PIXEL_FORMAT_BGRX_8888 ||
+ format == HAL_PIXEL_FORMAT_BGRA_8888) {
+ backBuffer->OCMD = 1 << 10;
+ // by pass YUV->RGB conversion, 8-bit output
+ backBuffer->OCONFIG |= (0x1 << 4) | (0x1 << 3);
+ backBuffer->OSTART_0Y = gttOffsetInBytes;
+ backBuffer->OSTART_1Y = gttOffsetInBytes;
+ backBuffer->OBUF_0Y = 0;
+ backBuffer->OBUF_1Y = 0;
+ return true;
+ }
+
+ uint32_t yStride = mapper.getStride().yuv.yStride;
+ uint32_t uvStride = mapper.getStride().yuv.uvStride;
+ uint32_t w = mapper.getWidth();
+ uint32_t h = mapper.getHeight();
+ uint32_t srcX= mapper.getCrop().x;
+ uint32_t srcY= mapper.getCrop().y;
+ uint32_t ySurface, uSurface, vSurface;
+ uint32_t yTileOffsetX, yTileOffsetY;
+ uint32_t uTileOffsetX, uTileOffsetY;
+ uint32_t vTileOffsetX, vTileOffsetY;
+
+ // clear original format setting
+ backBuffer->OCMD &= ~(0xf << 10);
+ backBuffer->OCMD &= ~OVERLAY_MEMORY_LAYOUT_TILED;
+
+ backBuffer->OBUF_0Y = 0;
+ backBuffer->OBUF_0V = 0;
+ backBuffer->OBUF_0U = 0;
+ // Y/U/V plane must be 4k bytes aligned.
+ ySurface = gttOffsetInBytes;
+ if (mIsProtectedBuffer) {
+ // temporary workaround until vsync event logic is corrected.
+ // it seems that overlay buffer update and renderring can be overlapped,
+ // as such encryption bit may be cleared during HW rendering
+ ySurface |= 0x01;
+ }
+
+ switch(format) {
+ case HAL_PIXEL_FORMAT_YV12: // YV12
+ vSurface = ySurface + yStride * h;
+ uSurface = vSurface + uvStride * (h / 2);
+ yTileOffsetX = srcX;
+ yTileOffsetY = srcY;
+ uTileOffsetX = srcX / 2;
+ uTileOffsetY = srcY / 2;
+ vTileOffsetX = uTileOffsetX;
+ vTileOffsetY = uTileOffsetY;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
+ break;
+ case HAL_PIXEL_FORMAT_I420: // I420
+ uSurface = ySurface + yStride * h;
+ vSurface = uSurface + uvStride * (h / 2);
+ yTileOffsetX = srcX;
+ yTileOffsetY = srcY;
+ uTileOffsetX = srcX / 2;
+ uTileOffsetY = srcY / 2;
+ vTileOffsetX = uTileOffsetX;
+ vTileOffsetY = uTileOffsetY;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
+ break;
+ case HAL_PIXEL_FORMAT_NV12: // NV12
+ uSurface = ySurface;
+ vSurface = ySurface;
+ backBuffer->OBUF_0U = yStride * h;
+ yTileOffsetX = srcX;
+ yTileOffsetY = srcY;
+ uTileOffsetX = srcX / 2;
+ uTileOffsetY = srcY / 2 + h;
+ vTileOffsetX = uTileOffsetX;
+ vTileOffsetY = uTileOffsetY;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
+ break;
+ // NOTE: this is the decoded video format, align the height to 32B
+ //as it's defined by video driver
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: // NV12
+ uSurface = ySurface + yStride * align_to(h, 32);
+ vSurface = ySurface + yStride * align_to(h, 32);
+ yTileOffsetX = srcX;
+ yTileOffsetY = srcY;
+ uTileOffsetX = srcX;
+ uTileOffsetY = srcY / 2;
+ vTileOffsetX = uTileOffsetX;
+ vTileOffsetY = uTileOffsetY;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
+ break;
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: //NV12_tiled
+ uSurface = ySurface + yStride * align_to(h, 32);
+ vSurface = ySurface + yStride * align_to(h, 32);
+ yTileOffsetX = srcX;
+ yTileOffsetY = srcY;
+ uTileOffsetX = srcX;
+ uTileOffsetY = srcY / 2;
+ vTileOffsetX = uTileOffsetX;
+ vTileOffsetY = uTileOffsetY;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
+ backBuffer->OCMD |= OVERLAY_MEMORY_LAYOUT_TILED;
+ break;
+ case HAL_PIXEL_FORMAT_YUY2: // YUY2
+ uSurface = ySurface;
+ vSurface = ySurface;
+ yTileOffsetX = srcX;
+ yTileOffsetY = srcY;
+ uTileOffsetX = yTileOffsetX;
+ uTileOffsetY = yTileOffsetY;
+ vTileOffsetX = yTileOffsetX;
+ vTileOffsetY = yTileOffsetY;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
+ backBuffer->OCMD |= OVERLAY_PACKED_ORDER_YUY2;
+ break;
+ case HAL_PIXEL_FORMAT_UYVY: // UYVY
+ uSurface = ySurface;
+ vSurface = ySurface;
+ yTileOffsetX = srcX;
+ yTileOffsetY = srcY;
+ uTileOffsetX = yTileOffsetX;
+ uTileOffsetY = yTileOffsetY;
+ vTileOffsetX = yTileOffsetX;
+ vTileOffsetY = yTileOffsetY;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
+ backBuffer->OCMD |= OVERLAY_PACKED_ORDER_UYVY;
+ break;
+ default:
+ ELOGTRACE("unsupported format %d", format);
+ return false;
+ }
+
+ backBuffer->OSTART_0Y = ySurface;
+ backBuffer->OSTART_0U = uSurface;
+ backBuffer->OSTART_0V = vSurface;
+ backBuffer->OBUF_0Y += srcY * yStride + srcX;
+ backBuffer->OBUF_0V += (srcY / 2) * uvStride + srcX;
+ backBuffer->OBUF_0U += (srcY / 2) * uvStride + srcX;
+ backBuffer->OTILEOFF_0Y = yTileOffsetY << 16 | yTileOffsetX;
+ backBuffer->OTILEOFF_0U = uTileOffsetY << 16 | uTileOffsetX;
+ backBuffer->OTILEOFF_0V = vTileOffsetY << 16 | vTileOffsetX;
+
+ VLOGTRACE("done. offset (%d, %d, %d)",
+ backBuffer->OBUF_0Y,
+ backBuffer->OBUF_0U,
+ backBuffer->OBUF_0V);
+
+ return true;
+}
+
+bool AnnOverlayPlane::coordinateSetup(BufferMapper& mapper)
+{
+ CTRACE();
+
+ uint32_t format = mapper.getFormat();
+ if (format != HAL_PIXEL_FORMAT_BGRX_8888 &&
+ format != HAL_PIXEL_FORMAT_BGRA_8888) {
+ return OverlayPlaneBase::coordinateSetup(mapper);
+ }
+
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
+ if (!backBuffer) {
+ ELOGTRACE("invalid back buffer");
+ return false;
+ }
+
+ backBuffer->SWIDTH = mapper.getCrop().w;
+ backBuffer->SHEIGHT = mapper.getCrop().h;
+ backBuffer->SWIDTHSW = calculateSWidthSW(0, mapper.getCrop().w) << 2;
+ backBuffer->OSTRIDE = mapper.getStride().rgb.stride & (~0x3f);
+ return true;
+};
+
+bool AnnOverlayPlane::scalingSetup(BufferMapper& mapper)
+{
+ int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
+ int xscaleIntUV, xscaleFractUV;
+ int yscaleIntUV, yscaleFractUV;
+ // UV is half the size of Y -- YUV420
+ int uvratio = 2;
+ uint32_t newval;
+ coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
+ coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
+ coeffRec ycoeffY[N_VERT_Y_TAPS * N_PHASES];
+ coeffRec ycoeffUV[N_VERT_UV_TAPS * N_PHASES];
+ int i, j, pos;
+ bool scaleChanged = false;
+ int x, y, w, h;
+ int deinterlace_factor = 1;
+ drmModeModeInfoPtr mode = &mModeInfo;
+
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
+ if (!backBuffer) {
+ ELOGTRACE("invalid back buffer");
+ return false;
+ }
+
+ if (mPanelOrientation == PANEL_ORIENTATION_180) {
+ if (mode->hdisplay)
+ x = mode->hdisplay - mPosition.x - mPosition.w;
+ else
+ x = mPosition.x;
+ if (mode->vdisplay)
+ y = mode->vdisplay - mPosition.y - mPosition.h;
+ else
+ y = mPosition.y;
+ } else {
+ x = mPosition.x;
+ y = mPosition.y;
+ }
+
+ w = mPosition.w;
+ h = mPosition.h;
+
+ // check position
+ checkPosition(x, y, w, h);
+ VLOGTRACE("final position (%d, %d, %d, %d)", x, y, w, h);
+
+ if ((w <= 0) || (h <= 0)) {
+ ELOGTRACE("invalid dst width/height");
+ return false;
+ }
+
+ // setup dst position
+ backBuffer->DWINPOS = (y << 16) | x;
+ backBuffer->DWINSZ = (h << 16) | w;
+
+ uint32_t srcWidth = mapper.getCrop().w;
+ uint32_t srcHeight = mapper.getCrop().h;
+ uint32_t dstWidth = w;
+ uint32_t dstHeight = h;
+ uint32_t format = mapper.getFormat();
+
+ if (format == HAL_PIXEL_FORMAT_BGRX_8888 ||
+ format == HAL_PIXEL_FORMAT_BGRA_8888) {
+ backBuffer->YRGBSCALE = 1 << 15 | 0 << 3 || 0 << 20;
+ backBuffer->UVSCALEV = (1 << 16);
+ return true;
+ }
+
+ if (mBobDeinterlace && !mTransform)
+ deinterlace_factor = 2;
+
+ VLOGTRACE("src (%dx%d), dst (%dx%d), transform %d",
+ srcWidth, srcHeight,
+ dstWidth, dstHeight,
+ mTransform);
+
+ // switch destination width/height for scale factor calculation
+ // for 90/270 transformation
+ if (mUseOverlayRotation && ((mTransform == HWC_TRANSFORM_ROT_90) ||
+ (mTransform == HWC_TRANSFORM_ROT_270))) {
+ uint32_t tmp = srcHeight;
+ srcHeight = srcWidth;
+ srcWidth = tmp;
+ }
+
+ // Y down-scale factor as a multiple of 4096
+ if (srcWidth == dstWidth && srcHeight == dstHeight) {
+ xscaleFract = (1 << 12);
+ yscaleFract = (1 << 12) / deinterlace_factor;
+ } else {
+ xscaleFract = ((srcWidth - 1) << 12) / dstWidth;
+ yscaleFract = ((srcHeight - 1) << 12) / (dstHeight * deinterlace_factor);
+ }
+
+ // Calculate the UV scaling factor
+ xscaleFractUV = xscaleFract / uvratio;
+ yscaleFractUV = yscaleFract / uvratio;
+
+
+ // To keep the relative Y and UV ratios exact, round the Y scales
+ // to a multiple of the Y/UV ratio.
+ xscaleFract = xscaleFractUV * uvratio;
+ yscaleFract = yscaleFractUV * uvratio;
+
+ // Integer (un-multiplied) values
+ xscaleInt = xscaleFract >> 12;
+ yscaleInt = yscaleFract >> 12;
+
+ xscaleIntUV = xscaleFractUV >> 12;
+ yscaleIntUV = yscaleFractUV >> 12;
+
+ // Check scaling ratio
+ if (xscaleInt > INTEL_OVERLAY_MAX_SCALING_RATIO) {
+ ELOGTRACE("xscaleInt > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
+ return false;
+ }
+
+ // shouldn't get here
+ if (xscaleIntUV > INTEL_OVERLAY_MAX_SCALING_RATIO) {
+ ELOGTRACE("xscaleIntUV > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
+ return false;
+ }
+
+ newval = (xscaleInt << 15) |
+ ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
+ if (newval != backBuffer->YRGBSCALE) {
+ scaleChanged = true;
+ backBuffer->YRGBSCALE = newval;
+ }
+
+ newval = (xscaleIntUV << 15) | ((xscaleFractUV & 0xFFF) << 3) |
+ ((yscaleFractUV & 0xFFF) << 20);
+ if (newval != backBuffer->UVSCALE) {
+ scaleChanged = true;
+ backBuffer->UVSCALE = newval;
+ }
+
+ newval = yscaleInt << 16 | yscaleIntUV;
+ if (newval != backBuffer->UVSCALEV) {
+ scaleChanged = true;
+ backBuffer->UVSCALEV = newval;
+ }
+
+ // Recalculate coefficients if the scaling changed
+ // Only Horizontal coefficients so far.
+ if (scaleChanged) {
+ double fHCutoffY;
+ double fHCutoffUV;
+ double fVCutoffY;
+ double fVCutoffUV;
+
+ fHCutoffY = xscaleFract / 4096.0;
+ fHCutoffUV = xscaleFractUV / 4096.0;
+ fVCutoffY = yscaleFract / 4096.0;
+ fVCutoffUV = yscaleFractUV / 4096.0;
+
+ // Limit to between 1.0 and 3.0
+ if (fHCutoffY < MIN_CUTOFF_FREQ)
+ fHCutoffY = MIN_CUTOFF_FREQ;
+ if (fHCutoffY > MAX_CUTOFF_FREQ)
+ fHCutoffY = MAX_CUTOFF_FREQ;
+ if (fHCutoffUV < MIN_CUTOFF_FREQ)
+ fHCutoffUV = MIN_CUTOFF_FREQ;
+ if (fHCutoffUV > MAX_CUTOFF_FREQ)
+ fHCutoffUV = MAX_CUTOFF_FREQ;
+
+ if (fVCutoffY < MIN_CUTOFF_FREQ)
+ fVCutoffY = MIN_CUTOFF_FREQ;
+ if (fVCutoffY > MAX_CUTOFF_FREQ)
+ fVCutoffY = MAX_CUTOFF_FREQ;
+ if (fVCutoffUV < MIN_CUTOFF_FREQ)
+ fVCutoffUV = MIN_CUTOFF_FREQ;
+ if (fVCutoffUV > MAX_CUTOFF_FREQ)
+ fVCutoffUV = MAX_CUTOFF_FREQ;
+
+ updateCoeff(N_HORIZ_Y_TAPS, fHCutoffY, true, true, xcoeffY);
+ updateCoeff(N_HORIZ_UV_TAPS, fHCutoffUV, true, false, xcoeffUV);
+ updateCoeff(N_VERT_Y_TAPS, fVCutoffY, false, true, ycoeffY);
+ updateCoeff(N_VERT_UV_TAPS, fVCutoffUV, false, false, ycoeffUV);
+
+ for (i = 0; i < N_PHASES; i++) {
+ for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
+ pos = i * N_HORIZ_Y_TAPS + j;
+ backBuffer->Y_HCOEFS[pos] =
+ (xcoeffY[pos].sign << 15 |
+ xcoeffY[pos].exponent << 12 |
+ xcoeffY[pos].mantissa);
+ }
+ }
+ for (i = 0; i < N_PHASES; i++) {
+ for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
+ pos = i * N_HORIZ_UV_TAPS + j;
+ backBuffer->UV_HCOEFS[pos] =
+ (xcoeffUV[pos].sign << 15 |
+ xcoeffUV[pos].exponent << 12 |
+ xcoeffUV[pos].mantissa);
+ }
+ }
+
+ for (i = 0; i < N_PHASES; i++) {
+ for (j = 0; j < N_VERT_Y_TAPS; j++) {
+ pos = i * N_VERT_Y_TAPS + j;
+ backBuffer->Y_VCOEFS[pos] =
+ (ycoeffY[pos].sign << 15 |
+ ycoeffY[pos].exponent << 12 |
+ ycoeffY[pos].mantissa);
+ }
+ }
+ for (i = 0; i < N_PHASES; i++) {
+ for (j = 0; j < N_VERT_UV_TAPS; j++) {
+ pos = i * N_VERT_UV_TAPS + j;
+ backBuffer->UV_VCOEFS[pos] =
+ (ycoeffUV[pos].sign << 15 |
+ ycoeffUV[pos].exponent << 12 |
+ ycoeffUV[pos].mantissa);
+ }
+ }
+ }
+
+ XLOGTRACE();
+ return true;
+}
+
+void AnnOverlayPlane::setTransform(int transform)
+{
+ RETURN_VOID_IF_NOT_INIT();
+
+ if (mPanelOrientation == PANEL_ORIENTATION_180)
+ transform ^= HWC_TRANSFORM_ROT_180;
+
+ DisplayPlane::setTransform(transform);
+
+ // setup transform config
+ switch (mTransform) {
+ case HWC_TRANSFORM_ROT_90:
+ mRotationConfig = (0x1 << 10);
+ break;
+ case HWC_TRANSFORM_ROT_180:
+ mRotationConfig = (0x2 << 10);
+ break;
+ case HWC_TRANSFORM_ROT_270:
+ mRotationConfig = (0x3 << 10);
+ break;
+ case 0:
+ mRotationConfig = 0;
+ break;
+ default:
+ ELOGTRACE("Invalid transform %d", mTransform);
+ mRotationConfig = 0;
+ break;
+ }
+}
+
+bool AnnOverlayPlane::flip(void *ctx)
+{
+ uint32_t ovadd = 0;
+
+ RETURN_FALSE_IF_NOT_INIT();
+
+ if (mForceScaling) {
+ BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
+ if (!bm->blitGrallocBuffer(mScalingSource, mScalingTarget, mSrcCrop, 0)) {
+ ELOGTRACE("Failed to blit RGB buffer to NV12.");
+ return false;
+ }
+ }
+
+ if (!DisplayPlane::flip(ctx)) {
+ ELOGTRACE("failed to flip display plane.");
+ return false;
+ }
+
+ // update back buffer address
+ ovadd = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
+
+ // enable rotation mode and setup rotation config
+ if (mIndex == 0 && mRotationConfig != 0) {
+ ovadd |= (1 << 12);
+ ovadd |= mRotationConfig;
+ }
+
+ // setup z-order config
+ ovadd |= mZOrderConfig;
+
+ // load coefficients
+ ovadd |= 0x1;
+
+ // enable overlay
+ ovadd |= (1 << 15);
+
+ mContext.type = DC_OVERLAY_PLANE;
+ mContext.ctx.ov_ctx.ovadd = ovadd;
+ mContext.ctx.ov_ctx.index = mIndex;
+ mContext.ctx.ov_ctx.pipe = mDevice;
+ mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
+
+ // move to next back buffer
+ mCurrent = (mCurrent + 1) % OVERLAY_BACK_BUFFER_COUNT;
+
+ VLOGTRACE("ovadd = %#x, index = %d, device = %d",
+ mContext.ctx.ov_ctx.ovadd,
+ mIndex,
+ mDevice);
+
+ return true;
+}
+
+void* AnnOverlayPlane::getContext() const
+{
+ CTRACE();
+ return (void *)&mContext;
+}
+
+bool AnnOverlayPlane::setDataBuffer(BufferMapper& mapper)
+{
+ if (mIsProtectedBuffer) {
+ // workaround overlay scaling limitation
+ float scaleX = (float)mSrcCrop.w/mPosition.w;
+ float scaleY = (float)mSrcCrop.h/mPosition.h;
+ if (scaleX > 4.0) {
+ int crop = (mSrcCrop.w - 4 * mPosition.w)/2 + 1;
+ mSrcCrop.x += crop;
+ mSrcCrop.w -= 2 * crop;
+ }
+
+ if (scaleY > 4.0) {
+ int crop = (mSrcCrop.h - 4 * mPosition.h)/2 + 1;
+ mSrcCrop.y += crop;
+ mSrcCrop.h -= 2 * crop;
+ }
+
+ if (scaleX > 4.0 || scaleY > 4.0) {
+ mUpdateMasks |= PLANE_SOURCE_CROP_CHANGED;
+ mapper.setCrop(mSrcCrop.x, mSrcCrop.y, mSrcCrop.w, mSrcCrop.h);
+ }
+ }
+
+
+ if (OverlayPlaneBase::setDataBuffer(mapper) == false) {
+ return false;
+ }
+
+ signalVideoRotation(mapper);
+
+ if (mIsProtectedBuffer) {
+ // Bit 0: Decryption request, only allowed to change on a synchronous flip
+ // This request will be qualified with the separate decryption enable bit for OV
+ mBackBuffer[mCurrent]->buf->OSTART_0Y |= 0x1;
+ mBackBuffer[mCurrent]->buf->OSTART_1Y |= 0x1;
+ }
+ return true;
+}
+
+bool AnnOverlayPlane::initialize(uint32_t bufferCount)
+{
+ if (!OverlayPlaneBase::initialize(bufferCount)) {
+ ELOGTRACE("failed to initialize OverlayPlaneBase");
+ return false;
+ }
+
+ // setup rotation buffer
+ mRotationBufProvider = new RotationBufferProvider(mWsbm);
+ if (!mRotationBufProvider || !mRotationBufProvider->initialize()) {
+ DEINIT_AND_RETURN_FALSE("failed to initialize RotationBufferProvider");
+ }
+ return true;
+}
+
+void AnnOverlayPlane::deinitialize()
+{
+ DEINIT_AND_DELETE_OBJ(mRotationBufProvider);
+ OverlayPlaneBase::deinitialize();
+}
+
+bool AnnOverlayPlane::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper)
+{
+ struct VideoPayloadBuffer *payload;
+ uint32_t format;
+ // only NV12_VED has rotated buffer
+ format = mapper.getFormat();
+ if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
+ format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
+ ELOGTRACE("invalid video format %#x", format);
+ return false;
+ }
+
+ payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
+ // check payload
+ if (!payload) {
+ ELOGTRACE("no payload found");
+ return false;
+ }
+
+ if (payload->force_output_method == FORCE_OUTPUT_GPU) {
+ ELOGTRACE("Output method is not supported!");
+ return false;
+ }
+
+ if (payload->client_transform != mTransform ||
+ mBobDeinterlace) {
+ if (!mRotationBufProvider->setupRotationBuffer(payload, mTransform)) {
+ DLOGTRACE("failed to setup rotation buffer");
+ return false;
+ }
+ }
+
+ rotatedMapper = getTTMMapper(mapper, payload);
+ return true;
+}
+
+void AnnOverlayPlane::signalVideoRotation(BufferMapper& mapper)
+{
+ struct VideoPayloadBuffer *payload;
+ uint32_t format;
+
+ // check if it's video layer
+ format = mapper.getFormat();
+ if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
+ format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
+ return;
+ }
+
+ payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
+ if (!payload) {
+ ELOGTRACE("no payload found");
+ return;
+ }
+
+ /* if use overlay rotation, signal decoder to stop rotation */
+ if (mUseOverlayRotation) {
+ if (payload->client_transform) {
+ WLOGTRACE("signal decoder to stop generate rotation buffer");
+ payload->hwc_timestamp = systemTime();
+ payload->layer_transform = 0;
+ }
+ } else {
+ /* if overlay rotation cannot be used, signal decoder to start rotation */
+ if (payload->client_transform != mTransform) {
+ WLOGTRACE("signal decoder to generate rotation buffer with transform %d", mTransform);
+ payload->hwc_timestamp = systemTime();
+ payload->layer_transform = mTransform;
+ }
+ }
+}
+
+bool AnnOverlayPlane::useOverlayRotation(BufferMapper& /* mapper */)
+{
+ if (mTransform == 0)
+ return true;
+
+ // workaround limitation of overlay rotation by falling back to use VA rotated buffer
+ bool fallback = false;
+ float scaleX = (float)mSrcCrop.w / mPosition.w;
+ float scaleY = (float)mSrcCrop.h / mPosition.h;
+ if (mTransform == HAL_TRANSFORM_ROT_270 || mTransform == HAL_TRANSFORM_ROT_90) {
+ scaleX = (float)mSrcCrop.w / mPosition.h;
+ scaleY = (float)mSrcCrop.h / mPosition.w;
+ }
+ if (scaleX >= 3 || scaleY >= 3 || scaleX < 1.0/3 || scaleY < 1.0/3) {
+ if (mUseOverlayRotation) {
+ DLOGTRACE("overlay rotation with scaling >= 3, use VA rotated buffer");
+ }
+ fallback = true;
+ } else if ((int)mSrcCrop.x & 63) {
+ if (mUseOverlayRotation) {
+ DLOGTRACE("offset is not 64 bytes aligned, use VA rotated buffer");
+ }
+ fallback = true;
+ }
+#if 0
+ else if (mTransform != HAL_TRANSFORM_ROT_180 && scaleX != scaleY) {
+ if (mUseOverlayRotation) {
+ DLOGTRACE("overlay rotation with uneven scaling, use VA rotated buffer");
+ }
+ fallback = true;
+ }
+#endif
+
+ // per DC spec, if video is 1080(H)x1920(V), the buffer
+ // need 1920 of 64-pixel strip if using hw rotation.
+ // fallback to video ration buffer in such case.
+ if (mSrcCrop.w == 1080 && mSrcCrop.h == 1920 && mTransform != 0) {
+ DLOGTRACE("1080(H)x1920(V) cannot use hw rotation, use VA rotated buffer");
+ fallback = true;
+ }
+
+ if (fallback || mBobDeinterlace) {
+ mUseOverlayRotation = false;
+ mRotationConfig = 0;
+ } else {
+ mUseOverlayRotation = true;
+ }
+ return mUseOverlayRotation;
+}
+
+bool AnnOverlayPlane::flush(uint32_t flags)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+ ALOGTRACE("flags = %#x, type = %d, index = %d", flags, mType, mIndex);
+
+ if (!(flags & PLANE_ENABLE) && !(flags & PLANE_DISABLE)) {
+ ELOGTRACE("invalid flush flags.");
+ return false;
+ }
+
+ struct drm_psb_register_rw_arg arg;
+ memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
+
+ if (flags & PLANE_DISABLE)
+ arg.plane_disable_mask = 1;
+ else if (flags & PLANE_ENABLE)
+ arg.plane_enable_mask = 1;
+
+ arg.plane.type = DC_OVERLAY_PLANE;
+ arg.plane.index = mIndex;
+ arg.plane.ctx = mContext.ctx.ov_ctx.ovadd;
+ if (flags & PLANE_DISABLE) {
+ DLOGTRACE("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));
+ if (ret == false) {
+ WLOGTRACE("overlay update failed with error code %d", ret);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/anniedale/AnnOverlayPlane.h b/moorefield_hdmi/ips/anniedale/AnnOverlayPlane.h
new file mode 100755
index 0000000..1578b57
--- /dev/null
+++ b/moorefield_hdmi/ips/anniedale/AnnOverlayPlane.h
@@ -0,0 +1,85 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef ANN_OVERLAY_PLANE_H
+#define ANN_OVERLAY_PLANE_H
+
+#include <utils/KeyedVector.h>
+#include <hal_public.h>
+#include <DisplayPlane.h>
+#include <BufferMapper.h>
+#include <ips/common/Wsbm.h>
+#include <ips/common/OverlayPlaneBase.h>
+#include <ips/common/RotationBufferProvider.h>
+
+namespace android {
+namespace intel {
+
+class AnnOverlayPlane : public OverlayPlaneBase {
+public:
+ AnnOverlayPlane(int index, int disp);
+ virtual ~AnnOverlayPlane();
+
+ bool setDataBuffer(uint32_t handle);
+
+ virtual void setTransform(int transform);
+ virtual void setZOrderConfig(ZOrderConfig& config, void *nativeConfig);
+
+ // plane operations
+ virtual bool flip(void *ctx);
+ virtual bool reset();
+ virtual bool enable();
+ virtual bool disable();
+ virtual void postFlip();
+ virtual void* getContext() const;
+ virtual bool initialize(uint32_t bufferCount);
+ virtual void deinitialize();
+ virtual bool rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper);
+ virtual bool useOverlayRotation(BufferMapper& mapper);
+
+private:
+ void signalVideoRotation(BufferMapper& mapper);
+protected:
+ virtual bool setDataBuffer(BufferMapper& mapper);
+ virtual bool flush(uint32_t flags);
+ virtual bool bufferOffsetSetup(BufferMapper& mapper);
+ virtual bool coordinateSetup(BufferMapper& mapper);
+ virtual bool scalingSetup(BufferMapper& mapper);
+
+ virtual void resetBackBuffer(int buf);
+
+ RotationBufferProvider *mRotationBufProvider;
+
+ // rotation config
+ uint32_t mRotationConfig;
+ // z order config
+ uint32_t mZOrderConfig;
+ bool mUseOverlayRotation;
+ // hardware context
+ struct intel_dc_plane_ctx mContext;
+
+private:
+ // scaling buffer vector max size
+ enum {
+ MAX_SCALING_BUF_COUNT = 3,
+ };
+ KeyedVector<uint32_t, uint32_t> mScalingBufferMap;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* ANN_OVERLAY_PLANE_H */
+
diff --git a/moorefield_hdmi/ips/anniedale/AnnPlaneManager.cpp b/moorefield_hdmi/ips/anniedale/AnnPlaneManager.cpp
new file mode 100755
index 0000000..f921199
--- /dev/null
+++ b/moorefield_hdmi/ips/anniedale/AnnPlaneManager.cpp
@@ -0,0 +1,424 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <utils/String8.h>
+#include <ips/anniedale/AnnPlaneManager.h>
+#include <ips/anniedale/AnnRGBPlane.h>
+#include <ips/anniedale/AnnOverlayPlane.h>
+#include <ips/anniedale/AnnCursorPlane.h>
+#include <PlaneCapabilities.h>
+
+namespace android {
+namespace intel {
+
+
+struct PlaneDescription {
+ char nickname;
+ int type;
+ int index;
+};
+
+
+static PlaneDescription PLANE_DESC[] =
+{
+ // nickname must be continous and start with 'A',
+ // it is used to fast locate plane index and type
+ {'A', DisplayPlane::PLANE_PRIMARY, 0},
+ {'B', DisplayPlane::PLANE_PRIMARY, 1},
+ {'C', DisplayPlane::PLANE_PRIMARY, 2},
+ {'D', DisplayPlane::PLANE_SPRITE, 0},
+ {'E', DisplayPlane::PLANE_SPRITE, 1},
+ {'F', DisplayPlane::PLANE_SPRITE, 2},
+ {'G', DisplayPlane::PLANE_OVERLAY, 0}, // nickname for Overlay A
+ {'H', DisplayPlane::PLANE_OVERLAY, 1}, // nickname for Overlay C
+ {'I', DisplayPlane::PLANE_CURSOR, 0}, // nickname for cursor A
+ {'J', DisplayPlane::PLANE_CURSOR, 1}, // nickname for cursor B
+ {'K', DisplayPlane::PLANE_CURSOR, 2} // nickname for cursor C
+};
+
+
+struct ZOrderDescription {
+ int index; // based on overlay position
+ const char *zorder;
+};
+
+// If overlay is in the bottom of Z order, two legitimate combinations are Oa, D, E, F
+// and Oc, D, E, F. However, plane A has to be part of the blending chain as it can't
+// be disabled [HW bug]. The only legitimate combinations including overlay and plane A is:
+// A, Oa, E, F
+// A, Oc, E, F
+#define OVERLAY_HW_WORKAROUND
+
+
+// Cursor plane can be placed on top of any plane below and is intentionally ignored
+// in the zorder table.
+
+static ZOrderDescription PIPE_A_ZORDER_DESC[] =
+{
+ {0, "ADEF"}, // no overlay
+#ifndef OVERLAY_HW_WORKAROUND
+ {1, "GDEF"}, // overlay A at bottom (1 << 0)
+ {1, "HDEF"}, // overlay C at bottom (1 << 0)
+#else
+ {1, "GEF"}, // overlay A at bottom (1 << 0)
+ {1, "HEF"}, // overlay C at bottom (1 << 0)
+#endif
+ {2, "AGEF"}, // overlay A at next to bottom (1 << 1)
+ {2, "AHEF"}, // overlay C at next to bottom (1 << 1)
+#ifndef OVERLAY_HW_WORKAROUND
+ {3, "GHEF"}, // overlay A, C at bottom
+#else
+ {3, "GHF"}, // overlay A, C at bottom
+#endif
+ {4, "ADGF"}, // overlay A at next to top (1 << 2)
+ {4, "ADHF"}, // overlay C at next to top (1 << 2)
+ {6, "AGHF"}, // overlay A, C in between
+ {8, "ADEG"}, // overlay A at top (1 << 3)
+ {8, "ADEH"}, // overlay C at top (1 <<3)
+ {12, "ADGH"} // overlay A, C at top
+};
+
+// use overlay C over overlay A if possible on pipe B
+// workaround: use only overlay C on pipe B
+static ZOrderDescription PIPE_B_ZORDER_DESC[] =
+{
+ {0, "BD"}, // no overlay
+ {1, "GBD"}, // overlay A at bottom (1 << 0)
+ {1, "HBD"}, // overlay C at bottom (1 << 0)
+ {2, "BGD"}, // overlay A at middle (1 << 1)
+ {2, "BHD"}, // overlay C at middle (1 << 1)
+ {3, "GHBD"}, // overlay A and C at bottom ( 1 << 0 + 1 << 1)
+ {4, "BDG"}, // overlay A at top (1 << 2)
+ {4, "BDH"}, // overlay C at top (1 << 2)
+ {6, "BGHD"}, // overlay A/C at middle 1 << 1 + 1 << 2)
+ {12, "BDGH"} // overlay A/C at top (1 << 2 + 1 << 3)
+};
+
+static const int PIPE_A_ZORDER_COMBINATIONS =
+ sizeof(PIPE_A_ZORDER_DESC)/sizeof(ZOrderDescription);
+static const int PIPE_B_ZORDER_COMBINATIONS =
+ sizeof(PIPE_B_ZORDER_DESC)/sizeof(ZOrderDescription);
+
+AnnPlaneManager::AnnPlaneManager()
+ : DisplayPlaneManager()
+{
+}
+
+AnnPlaneManager::~AnnPlaneManager()
+{
+}
+
+bool AnnPlaneManager::initialize()
+{
+ mSpritePlaneCount = 3; // Sprite D, E, F
+ mOverlayPlaneCount = 2; // Overlay A, C
+ mPrimaryPlaneCount = 3; // Primary A, B, C
+ mCursorPlaneCount = 3;
+
+ return DisplayPlaneManager::initialize();
+}
+
+void AnnPlaneManager::deinitialize()
+{
+ DisplayPlaneManager::deinitialize();
+}
+
+DisplayPlane* AnnPlaneManager::allocPlane(int index, int type)
+{
+ DisplayPlane *plane = NULL;
+
+ switch (type) {
+ case DisplayPlane::PLANE_PRIMARY:
+ plane = new AnnRGBPlane(index, DisplayPlane::PLANE_PRIMARY, index/*disp*/);
+ break;
+ case DisplayPlane::PLANE_SPRITE:
+ plane = new AnnRGBPlane(index, DisplayPlane::PLANE_SPRITE, 0/*disp*/);
+ break;
+ case DisplayPlane::PLANE_OVERLAY:
+ plane = new AnnOverlayPlane(index, 0/*disp*/);
+ break;
+ case DisplayPlane::PLANE_CURSOR:
+ plane = new AnnCursorPlane(index, index /*disp */);
+ break;
+ default:
+ ELOGTRACE("unsupported type %d", type);
+ break;
+ }
+
+ if (plane && !plane->initialize(DisplayPlane::MIN_DATA_BUFFER_COUNT)) {
+ ELOGTRACE("failed to initialize plane.");
+ DEINIT_AND_DELETE_OBJ(plane);
+ }
+
+ return plane;
+}
+
+bool AnnPlaneManager::isValidZOrder(int dsp, ZOrderConfig& config)
+{
+ int size = (int)config.size();
+
+ if (size == 0 || size > 5) {
+ VLOGTRACE("invalid z order config size %d", size);
+ return false;
+ }
+
+ if (dsp == IDisplayDevice::DEVICE_PRIMARY) {
+ int firstOverlay = -1;
+ for (int i = 0; i < size; i++) {
+ if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
+ firstOverlay = i;
+ break;
+ }
+ }
+
+ int sprites = 0;
+ for (int i = 0; i < size; i++) {
+ if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY &&
+ config[i]->planeType != DisplayPlane::PLANE_CURSOR) {
+ sprites++;
+ }
+ }
+
+ if (firstOverlay < 0 && sprites > 4) {
+ VLOGTRACE("not capable to support more than 4 sprite layers");
+ return false;
+ }
+
+#ifdef OVERLAY_HW_WORKAROUND
+ if (firstOverlay == 0 && sprites > 2) {
+ VLOGTRACE("not capable to support 3 sprite layers on top of overlay");
+ return false;
+ }
+#endif
+ } else if (dsp == IDisplayDevice::DEVICE_EXTERNAL) {
+ int sprites = 0;
+ for (int i = 0; i < size; i++) {
+ if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY &&
+ config[i]->planeType != DisplayPlane::PLANE_CURSOR) {
+ sprites++;
+ }
+ }
+ if (sprites > 2) {
+ ELOGTRACE("number of sprite: %d, maximum 1 sprite and 1 primary supported on pipe 1", sprites);
+ return false;
+ }
+ } else {
+ ELOGTRACE("invalid display device %d", dsp);
+ return false;
+ }
+ return true;
+}
+
+bool AnnPlaneManager::assignPlanes(int dsp, ZOrderConfig& config)
+{
+ if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
+ ELOGTRACE("invalid display device %d", dsp);
+ return false;
+ }
+
+ int size = (int)config.size();
+
+ // calculate index based on overlay Z order position
+ int index = 0;
+ for (int i = 0; i < size; i++) {
+ if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
+ index += (1 << i);
+ }
+ }
+
+ int combinations = 0;
+ if (dsp == IDisplayDevice::DEVICE_PRIMARY)
+ combinations = PIPE_A_ZORDER_COMBINATIONS;
+ else
+ combinations = PIPE_B_ZORDER_COMBINATIONS;
+
+ ZOrderDescription *zorderDesc = NULL;
+ for (int i = 0; i < combinations; i++) {
+ if (dsp == IDisplayDevice::DEVICE_PRIMARY)
+ zorderDesc = &PIPE_A_ZORDER_DESC[i];
+ else
+ zorderDesc = &PIPE_B_ZORDER_DESC[i];
+
+ if (zorderDesc->index != index)
+ continue;
+
+ if (assignPlanes(dsp, config, zorderDesc->zorder)) {
+ VLOGTRACE("zorder assigned %s", zorderDesc->zorder);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool AnnPlaneManager::assignPlanes(int dsp, ZOrderConfig& config, const char *zorder)
+{
+ // zorder string does not include cursor plane, therefore cursor layer needs to be handled
+ // in a special way. Cursor layer must be on top of zorder and no more than one cursor layer.
+
+ int size = (int)config.size();
+
+ if (zorder == NULL || size == 0) {
+ //DLOGTRACE("invalid zorder or ZOrder config.");
+ return false;
+ }
+
+ int zorderLen = (int)strlen(zorder);
+
+ // test if plane is available
+ for (int i = 0; i < size; i++) {
+ if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
+ if (i != size - 1) {
+ ELOGTRACE("invalid zorder of cursor layer");
+ return false;
+ }
+ PlaneDescription& desc = PLANE_DESC['I' - 'A' + dsp];
+ if (!isFreePlane(desc.type, desc.index)) {
+ ELOGTRACE("cursor plane is not available");
+ return false;
+ }
+ continue;
+ }
+ if (i >= zorderLen) {
+ DLOGTRACE("index of ZOrderConfig is out of bound");
+ return false;
+ }
+ char id = *(zorder + i);
+ PlaneDescription& desc = PLANE_DESC[id - 'A'];
+ if (!isFreePlane(desc.type, desc.index)) {
+ DLOGTRACE("plane type %d index %d is not available", desc.type, desc.index);
+ return false;
+ }
+
+#if 0
+ // plane type check
+ if (config[i]->planeType == DisplayPlane::PLANE_OVERLAY &&
+ desc.type != DisplayPlane::PLANE_OVERLAY) {
+ ELOGTRACE("invalid plane type %d, expected %d", desc.type, config[i]->planeType);
+ return false;
+ }
+
+ if (config[i]->planeType != DisplayPlane::PLANE_OVERLAY) {
+ if (config[i]->planeType != DisplayPlane::PLANE_PRIMARY &&
+ config[i]->planeType != DisplayPlane::PLANE_SPRITE) {
+ ELOGTRACE("invalid plane type %d,", config[i]->planeType);
+ return false;
+ }
+ if (desc.type != DisplayPlane::PLANE_PRIMARY &&
+ desc.type != DisplayPlane::PLANE_SPRITE) {
+ ELOGTRACE("invalid plane type %d, expected %d", desc.type, config[i]->planeType);
+ return false;
+ }
+ }
+#endif
+
+ if (desc.type == DisplayPlane::PLANE_OVERLAY && desc.index == 1 &&
+ config[i]->hwcLayer->getTransform() != 0) {
+ DLOGTRACE("overlay C does not support transform");
+ return false;
+ }
+ }
+
+ bool primaryPlaneActive = false;
+ // allocate planes
+ for (int i = 0; i < size; i++) {
+ if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
+ PlaneDescription& desc = PLANE_DESC['I' - 'A' + dsp];
+ ZOrderLayer *zLayer = config.itemAt(i);
+ zLayer->plane = getPlane(desc.type, desc.index);
+ if (zLayer->plane == NULL) {
+ ELOGTRACE("failed to get cursor plane, should never happen!");
+ }
+ continue;
+ }
+ char id = *(zorder + i);
+ PlaneDescription& desc = PLANE_DESC[id - 'A'];
+ ZOrderLayer *zLayer = config.itemAt(i);
+ zLayer->plane = getPlane(desc.type, desc.index);
+ if (zLayer->plane == NULL) {
+ ELOGTRACE("failed to get plane, should never happen!");
+ }
+ // override type
+ zLayer->planeType = desc.type;
+ if (desc.type == DisplayPlane::PLANE_PRIMARY) {
+ primaryPlaneActive = true;
+ }
+ }
+
+ // setup Z order
+ int slot = 0;
+ for (int i = 0; i < size; i++) {
+ slot = i;
+
+#ifdef OVERLAY_HW_WORKAROUND
+ if (!primaryPlaneActive && config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
+ slot += 1;
+ }
+#endif
+
+ config[i]->plane->setZOrderConfig(config, (void *)slot);
+ config[i]->plane->enable();
+ }
+
+#if 0
+ DLOGTRACE("config size %d, zorder %s", size, zorder);
+ for (int i = 0; i < size; i++) {
+ const ZOrderLayer *l = config.itemAt(i);
+ ILOGTRACE("%d: plane type %d, index %d, zorder %d",
+ i, l->planeType, l->plane->getIndex(), l->zorder);
+ }
+#endif
+
+ return true;
+}
+
+void* AnnPlaneManager::getZOrderConfig() const
+{
+ return NULL;
+}
+
+int AnnPlaneManager::getFreePlanes(int dsp, int type)
+{
+ RETURN_NULL_IF_NOT_INIT();
+
+ if (type != DisplayPlane::PLANE_SPRITE) {
+ return DisplayPlaneManager::getFreePlanes(dsp, type);
+ }
+
+ if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
+ ELOGTRACE("invalid display device %d", dsp);
+ return 0;
+ }
+
+ uint32_t freePlanes = mFreePlanes[type] | mReclaimedPlanes[type];
+ int start = 0;
+ int stop = mSpritePlaneCount;
+ if (dsp == IDisplayDevice::DEVICE_EXTERNAL) {
+ // only Sprite D (index 0) can be assigned to pipe 1
+ // Sprites E/F (index 1, 2) are fixed on pipe 0
+ stop = 1;
+ }
+ int count = 0;
+ for (int i = start; i < stop; i++) {
+ if ((1 << i) & freePlanes) {
+ count++;
+ }
+ }
+ return count;
+}
+
+} // namespace intel
+} // namespace android
+
diff --git a/moorefield_hdmi/ips/anniedale/AnnPlaneManager.h b/moorefield_hdmi/ips/anniedale/AnnPlaneManager.h
new file mode 100644
index 0000000..5a7971e
--- /dev/null
+++ b/moorefield_hdmi/ips/anniedale/AnnPlaneManager.h
@@ -0,0 +1,48 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef ANN_PLANE_MANAGER_H
+#define ANN_PLANE_MANAGER_H
+
+#include <DisplayPlaneManager.h>
+#include <linux/psb_drm.h>
+
+namespace android {
+namespace intel {
+
+class AnnPlaneManager : public DisplayPlaneManager {
+public:
+ AnnPlaneManager();
+ virtual ~AnnPlaneManager();
+
+public:
+ virtual bool initialize();
+ virtual void deinitialize();
+ virtual bool isValidZOrder(int dsp, ZOrderConfig& config);
+ virtual bool assignPlanes(int dsp, ZOrderConfig& config);
+ virtual int getFreePlanes(int dsp, int type);
+ // TODO: remove this API
+ virtual void* getZOrderConfig() const;
+
+protected:
+ DisplayPlane* allocPlane(int index, int type);
+ bool assignPlanes(int dsp, ZOrderConfig& config, const char *zorder);
+};
+
+} // namespace intel
+} // namespace android
+
+
+#endif /* ANN_PLANE_MANAGER_H */
diff --git a/moorefield_hdmi/ips/anniedale/AnnRGBPlane.cpp b/moorefield_hdmi/ips/anniedale/AnnRGBPlane.cpp
new file mode 100755
index 0000000..afc4480
--- /dev/null
+++ b/moorefield_hdmi/ips/anniedale/AnnRGBPlane.cpp
@@ -0,0 +1,384 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <Hwcomposer.h>
+#include <BufferManager.h>
+#include <ips/anniedale/AnnRGBPlane.h>
+#include <ips/tangier/TngGrallocBuffer.h>
+#include <ips/common/PixelFormat.h>
+
+namespace android {
+namespace intel {
+
+AnnRGBPlane::AnnRGBPlane(int index, int type, int disp)
+ : DisplayPlane(index, type, disp)
+{
+ CTRACE();
+ memset(&mContext, 0, sizeof(mContext));
+}
+
+AnnRGBPlane::~AnnRGBPlane()
+{
+ CTRACE();
+}
+
+bool AnnRGBPlane::enable()
+{
+ return enablePlane(true);
+}
+
+bool AnnRGBPlane::disable()
+{
+ return enablePlane(false);
+}
+
+bool AnnRGBPlane::reset()
+{
+ while (!mScalingBufferMap.isEmpty()) {
+ uint32_t handle = mScalingBufferMap.valueAt(0);
+ Hwcomposer::getInstance().getBufferManager()->freeGrallocBuffer(handle);
+ mScalingBufferMap.removeItemsAt(0);
+ }
+
+ return DisplayPlane::reset();
+}
+
+bool AnnRGBPlane::flip(void*)
+{
+ if (mForceScaling) {
+ BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
+ if (!bm->blitGrallocBuffer(mScalingSource, mScalingTarget, mDisplayCrop, 0)) {
+ ELOGTRACE("Failed to blit RGB buffer.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void* AnnRGBPlane::getContext() const
+{
+ CTRACE();
+ return (void *)&mContext;
+}
+
+void AnnRGBPlane::setZOrderConfig(ZOrderConfig& /* config */, void * /* nativeConfig */)
+{
+ CTRACE();
+}
+
+bool AnnRGBPlane::setDataBuffer(uint32_t handle)
+{
+ if (!handle) {
+ if (!mForceScaling) {
+ setFramebufferTarget(handle);
+ return true;
+ } else {
+ ELOGTRACE("Invalid handle while scaling is required.");
+ return false;
+ }
+ }
+
+ if (mForceScaling) {
+ BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
+ ssize_t index = mScalingBufferMap.indexOfKey(handle);
+ if (index < 0) {
+ mScalingTarget = bm->allocGrallocBuffer(
+ mDisplayWidth,
+ mDisplayHeight,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE);
+ if (!mScalingTarget) {
+ ELOGTRACE("Failed to allocate gralloc buffer.");
+ return false;
+ }
+ mScalingBufferMap.add(handle, mScalingTarget);
+ } else {
+ mScalingTarget = mScalingBufferMap.valueAt(index);
+ }
+ mScalingSource = handle;
+ handle = mScalingTarget;
+ }
+
+ TngGrallocBuffer tmpBuf(handle);
+ uint32_t usage;
+ bool ret;
+
+ ALOGTRACE("handle = %#x", handle);
+
+ usage = tmpBuf.getUsage();
+ if (GRALLOC_USAGE_HW_FB & usage) {
+ setFramebufferTarget(handle);
+ return true;
+ }
+
+ // use primary as a sprite
+ ret = DisplayPlane::setDataBuffer(handle);
+ if (ret == false) {
+ ELOGTRACE("failed to set data buffer");
+ return ret;
+ }
+
+ return true;
+}
+
+bool AnnRGBPlane::setDataBuffer(BufferMapper& mapper)
+{
+ int bpp;
+ int srcX, srcY, srcW, srcH;
+ int dstX, dstY, dstW, dstH;
+ uint32_t spriteFormat;
+ uint32_t stride;
+ uint32_t linoff;
+ uint32_t planeAlpha;
+ drmModeModeInfoPtr mode = &mModeInfo;
+
+ CTRACE();
+
+ // setup plane position
+ dstX = mPosition.x;
+ dstY = mPosition.y;
+ dstW = mPosition.w;
+ dstH = mPosition.h;
+
+ checkPosition(dstX, dstY, dstW, dstH);
+
+ // setup plane format
+ if (!PixelFormat::convertFormat(mapper.getFormat(), spriteFormat, bpp)) {
+ ELOGTRACE("unsupported format %#x", mapper.getFormat());
+ return false;
+ }
+
+ // setup stride and source buffer crop
+ srcX = mapper.getCrop().x;
+ srcY = mapper.getCrop().y;
+ srcW = mapper.getWidth();
+ srcH = mapper.getHeight();
+ stride = mapper.getStride().rgb.stride;
+
+ if (mPanelOrientation == PANEL_ORIENTATION_180)
+ linoff = srcY * stride + srcX * bpp + (mapper.getCrop().h - 1) * stride + (mapper.getCrop().w - 1) * bpp;
+ else
+ linoff = srcY * stride + srcX * bpp;
+
+ // unlikely happen, but still we need make sure linoff is valid
+ if (linoff > (stride * mapper.getHeight())) {
+ ELOGTRACE("invalid source crop");
+ return false;
+ }
+
+ // update context
+ if (mType == PLANE_SPRITE)
+ mContext.type = DC_SPRITE_PLANE;
+ else
+ mContext.type = DC_PRIMARY_PLANE;
+
+ // setup plane alpha
+ if (0 < mPlaneAlpha && mPlaneAlpha < 0xff) {
+ planeAlpha = mPlaneAlpha | 0x80000000;
+ } else {
+ // disable plane alpha to offload HW
+ planeAlpha = 0xff;
+ }
+
+ mContext.ctx.sp_ctx.index = mIndex;
+ mContext.ctx.sp_ctx.pipe = mDevice;
+ mContext.ctx.sp_ctx.cntr = spriteFormat | 0x80000000;
+ mContext.ctx.sp_ctx.linoff = linoff;
+ mContext.ctx.sp_ctx.stride = stride;
+
+ // turn off premultipled alpha blending for HWC_BLENDING_COVERAGE
+ if (mBlending == HWC_BLENDING_COVERAGE) {
+ mContext.ctx.sp_ctx.cntr |= (0x1 << 23);
+ }
+
+ if (mPanelOrientation == PANEL_ORIENTATION_180)
+ mContext.ctx.sp_ctx.cntr |= (0x1 << 15);
+
+ if (mapper.isCompression()) {
+ mContext.ctx.sp_ctx.stride = align_to(srcW, 32) * 4;
+ mContext.ctx.sp_ctx.linoff = (align_to(srcW, 32) * srcH / 64) - 1;
+ mContext.ctx.sp_ctx.tileoff = (srcY & 0xfff) << 16 | (srcX & 0xfff);
+ mContext.ctx.sp_ctx.cntr |= (0x1 << 11);
+ }
+
+ mContext.ctx.sp_ctx.surf = mapper.getGttOffsetInPage(0) << 12;
+
+ if (mPanelOrientation == PANEL_ORIENTATION_180) {
+ if (mode->vdisplay && mode->hdisplay)
+ mContext.ctx.sp_ctx.pos = ((mode->vdisplay - dstY - dstH) & 0xfff) << 16 | ((mode->hdisplay - dstX - dstW) & 0xfff);
+ else
+ mContext.ctx.sp_ctx.pos = (dstY & 0xfff) << 16 | (dstX & 0xfff);
+ } else {
+ mContext.ctx.sp_ctx.pos = (dstY & 0xfff) << 16 | (dstX & 0xfff);
+ }
+
+ mContext.ctx.sp_ctx.size =
+ ((dstH - 1) & 0xfff) << 16 | ((dstW - 1) & 0xfff);
+ mContext.ctx.sp_ctx.contalpa = planeAlpha;
+ mContext.ctx.sp_ctx.update_mask = SPRITE_UPDATE_ALL;
+
+ VLOGTRACE("type = %d, index = %d, cntr = %#x, linoff = %#x, stride = %#x,"
+ "surf = %#x, pos = %#x, size = %#x, contalpa = %#x", mType, mIndex,
+ mContext.ctx.sp_ctx.cntr,
+ mContext.ctx.sp_ctx.linoff,
+ mContext.ctx.sp_ctx.stride,
+ mContext.ctx.sp_ctx.surf,
+ mContext.ctx.sp_ctx.pos,
+ mContext.ctx.sp_ctx.size,
+ mContext.ctx.sp_ctx.contalpa);
+ return true;
+}
+
+bool AnnRGBPlane::enablePlane(bool enabled)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ struct drm_psb_register_rw_arg arg;
+ memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
+ if (enabled) {
+ arg.plane_enable_mask = 1;
+ } else {
+ arg.plane_disable_mask = 1;
+ }
+
+ if (mType == PLANE_SPRITE)
+ arg.plane.type = DC_SPRITE_PLANE;
+ else
+ arg.plane.type = DC_PRIMARY_PLANE;
+
+ arg.plane.index = mIndex;
+ arg.plane.ctx = 0;
+
+ // issue ioctl
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
+ if (ret == false) {
+ WLOGTRACE("plane enabling (%d) failed with error code %d", enabled, ret);
+ return false;
+ }
+
+ return true;
+}
+
+bool AnnRGBPlane::isDisabled()
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ struct drm_psb_register_rw_arg arg;
+ memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
+
+ if (mType == PLANE_SPRITE)
+ arg.plane.type = DC_SPRITE_PLANE;
+ else
+ arg.plane.type = DC_PRIMARY_PLANE;
+
+ arg.get_plane_state_mask = 1;
+ arg.plane.index = mIndex;
+ arg.plane.ctx = 0;
+
+ // issue ioctl
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
+ if (ret == false) {
+ WLOGTRACE("plane state query failed with error code %d", ret);
+ return false;
+ }
+
+ return arg.plane.ctx == PSB_DC_PLANE_DISABLED;
+}
+
+void AnnRGBPlane::postFlip()
+{
+ // prevent mUpdateMasks from being reset
+ // skipping flip may cause flicking
+}
+
+void AnnRGBPlane::setFramebufferTarget(uint32_t handle)
+{
+ uint32_t stride;
+ uint32_t planeAlpha;
+
+ CTRACE();
+
+ // do not need to update the buffer handle
+ if (mCurrentDataBuffer != handle)
+ mUpdateMasks |= PLANE_BUFFER_CHANGED;
+ else
+ mUpdateMasks &= ~PLANE_BUFFER_CHANGED;
+
+ // if no update then do Not need set data buffer
+ if (!mUpdateMasks)
+ return;
+
+ // don't need to map data buffer for primary plane
+ if (mType == PLANE_SPRITE)
+ mContext.type = DC_SPRITE_PLANE;
+ else
+ mContext.type = DC_PRIMARY_PLANE;
+
+ stride = align_to((4 * align_to(mPosition.w, 32)), 64);
+
+ if (0 < mPlaneAlpha && mPlaneAlpha < 0xff) {
+ planeAlpha = mPlaneAlpha | 0x80000000;
+ } else {
+ // disable plane alpha to offload HW
+ planeAlpha = 0xff;
+ }
+
+ // FIXME: use sprite context for sprite plane
+ mContext.ctx.prim_ctx.update_mask = SPRITE_UPDATE_ALL;
+ mContext.ctx.prim_ctx.index = mIndex;
+ mContext.ctx.prim_ctx.pipe = mDevice;
+
+ if (mPanelOrientation == PANEL_ORIENTATION_180)
+ mContext.ctx.prim_ctx.linoff = (mPosition.h - 1) * stride + (mPosition.w - 1) * 4;
+ else
+ mContext.ctx.prim_ctx.linoff = 0;
+
+ mContext.ctx.prim_ctx.stride = stride;
+ mContext.ctx.prim_ctx.tileoff = 0;
+ mContext.ctx.prim_ctx.pos = 0;
+ mContext.ctx.prim_ctx.size =
+ ((mPosition.h - 1) & 0xfff) << 16 | ((mPosition.w - 1) & 0xfff);
+ mContext.ctx.prim_ctx.surf = 0;
+ mContext.ctx.prim_ctx.contalpa = planeAlpha;
+ mContext.ctx.prim_ctx.cntr = PixelFormat::PLANE_PIXEL_FORMAT_BGRA8888;
+ mContext.ctx.prim_ctx.cntr |= 0x80000000;
+
+ // turn off premultipled alpha blending for HWC_BLENDING_COVERAGE
+ if (mBlending == HWC_BLENDING_COVERAGE) {
+ mContext.ctx.prim_ctx.cntr |= (0x1 << 23);
+ }
+
+ if (mPanelOrientation == PANEL_ORIENTATION_180)
+ mContext.ctx.prim_ctx.cntr |= (0x1 << 15);
+
+ VLOGTRACE("type = %d, index = %d, cntr = %#x, linoff = %#x, stride = %#x,"
+ "surf = %#x, pos = %#x, size = %#x, contalpa = %#x", mType, mIndex,
+ mContext.ctx.prim_ctx.cntr,
+ mContext.ctx.prim_ctx.linoff,
+ mContext.ctx.prim_ctx.stride,
+ mContext.ctx.prim_ctx.surf,
+ mContext.ctx.prim_ctx.pos,
+ mContext.ctx.prim_ctx.size,
+ mContext.ctx.sp_ctx.contalpa);
+
+ mCurrentDataBuffer = handle;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/anniedale/AnnRGBPlane.h b/moorefield_hdmi/ips/anniedale/AnnRGBPlane.h
new file mode 100755
index 0000000..76ef53a
--- /dev/null
+++ b/moorefield_hdmi/ips/anniedale/AnnRGBPlane.h
@@ -0,0 +1,61 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef ANN_RGB_PLANE_H
+#define ANN_RGB_PLANE_H
+
+#include <utils/KeyedVector.h>
+#include <Hwcomposer.h>
+#include <common/buffers/BufferCache.h>
+#include <DisplayPlane.h>
+
+#include <linux/psb_drm.h>
+
+namespace android {
+namespace intel {
+
+class AnnRGBPlane : public DisplayPlane {
+public:
+ AnnRGBPlane(int index, int type, int disp);
+ virtual ~AnnRGBPlane();
+public:
+ // hardware operations
+ bool enable();
+ bool disable();
+ bool reset();
+ bool isDisabled();
+ bool flip(void *ctx);
+ void postFlip();
+
+ void* getContext() const;
+ void setZOrderConfig(ZOrderConfig& config, void *nativeConfig);
+
+ bool setDataBuffer(uint32_t handle);
+protected:
+ bool setDataBuffer(BufferMapper& mapper);
+ bool enablePlane(bool enabled);
+private:
+ void setFramebufferTarget(uint32_t handle);
+protected:
+ struct intel_dc_plane_ctx mContext;
+
+private:
+ KeyedVector<uint32_t, uint32_t> mScalingBufferMap;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* ANN_RGB_PLANE_H */
diff --git a/moorefield_hdmi/ips/anniedale/PlaneCapabilities.cpp b/moorefield_hdmi/ips/anniedale/PlaneCapabilities.cpp
new file mode 100755
index 0000000..736fff1
--- /dev/null
+++ b/moorefield_hdmi/ips/anniedale/PlaneCapabilities.cpp
@@ -0,0 +1,244 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <common/utils/HwcTrace.h>
+#include <DisplayPlane.h>
+#include <PlaneCapabilities.h>
+#include <ips/common/OverlayHardware.h>
+#include <common/base/HwcLayer.h>
+#include <khronos/openmax/OMX_IntelVideoExt.h>
+#include <hal_public.h>
+
+#define SPRITE_PLANE_MAX_STRIDE_TILED 16384
+#define SPRITE_PLANE_MAX_STRIDE_LINEAR 16384
+
+#define OVERLAY_PLANE_MAX_STRIDE_PACKED 4096
+#define OVERLAY_PLANE_MAX_STRIDE_LINEAR 8192
+
+namespace android {
+namespace intel {
+
+bool PlaneCapabilities::isFormatSupported(int planeType, HwcLayer *hwcLayer)
+{
+ uint32_t format = hwcLayer->getFormat();
+ uint32_t trans = hwcLayer->getLayer()->transform;
+
+ if (planeType == DisplayPlane::PLANE_SPRITE || planeType == DisplayPlane::PLANE_PRIMARY) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return trans ? false : true;
+ default:
+ VLOGTRACE("unsupported format %#x", format);
+ return false;
+ }
+ } else if (planeType == DisplayPlane::PLANE_OVERLAY) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_I420:
+ case HAL_PIXEL_FORMAT_YUY2:
+ case HAL_PIXEL_FORMAT_UYVY:
+ // TODO: overlay supports 180 degree rotation
+ if (trans == HAL_TRANSFORM_ROT_180) {
+ WLOGTRACE("180 degree rotation is not supported yet");
+ }
+ return trans ? false : true;
+ case HAL_PIXEL_FORMAT_YV12:
+ return trans ? false: true;
+ case HAL_PIXEL_FORMAT_NV12:
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar:
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled:
+ return true;
+ default:
+ VLOGTRACE("unsupported format %#x", format);
+ return false;
+ }
+ } else {
+ ELOGTRACE("invalid plane type %d", planeType);
+ return false;
+ }
+}
+
+bool PlaneCapabilities::isSizeSupported(int planeType, HwcLayer *hwcLayer)
+{
+ uint32_t format = hwcLayer->getFormat();
+ uint32_t w = hwcLayer->getBufferWidth();
+ uint32_t h = hwcLayer->getBufferHeight();
+ const stride_t& stride = hwcLayer->getBufferStride();
+
+ bool isYUVPacked;
+ uint32_t maxStride;
+
+ if (planeType == DisplayPlane::PLANE_SPRITE || planeType == DisplayPlane::PLANE_PRIMARY) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ VLOGTRACE("stride %d", stride.rgb.stride);
+ if (stride.rgb.stride > SPRITE_PLANE_MAX_STRIDE_LINEAR) {
+ VLOGTRACE("too large stride %d", stride.rgb.stride);
+ return false;
+ }
+ return true;
+ default:
+ VLOGTRACE("unsupported format %#x", format);
+ return false;
+ }
+ } else if (planeType == DisplayPlane::PLANE_OVERLAY) {
+ switch (format) {
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_I420:
+ case HAL_PIXEL_FORMAT_NV12:
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar:
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled:
+ isYUVPacked = false;
+ break;
+ case HAL_PIXEL_FORMAT_YUY2:
+ case HAL_PIXEL_FORMAT_UYVY:
+ isYUVPacked = true;
+ break;
+ default:
+ VLOGTRACE("unsupported format %#x", format);
+ return false;
+ }
+ // don't use overlay plane if stride is too big
+ maxStride = OVERLAY_PLANE_MAX_STRIDE_LINEAR;
+ if (isYUVPacked) {
+ maxStride = OVERLAY_PLANE_MAX_STRIDE_PACKED;
+ }
+
+ if (stride.yuv.yStride > maxStride) {
+ VLOGTRACE("stride %d is too large", stride.yuv.yStride);
+ return false;
+ }
+ return true;
+ } else {
+ ELOGTRACE("invalid plane type %d", planeType);
+ return false;
+ }
+}
+
+bool PlaneCapabilities::isBlendingSupported(int planeType, HwcLayer *hwcLayer)
+{
+ uint32_t blending = (uint32_t)hwcLayer->getLayer()->blending;
+ uint8_t planeAlpha = hwcLayer->getLayer()->planeAlpha;
+
+ if (planeType == DisplayPlane::PLANE_SPRITE || planeType == DisplayPlane::PLANE_PRIMARY) {
+ // support premultipled & none blanding
+ switch (blending) {
+ case HWC_BLENDING_NONE:
+ case HWC_BLENDING_PREMULT:
+ // add coverage alpha support for ann
+ case HWC_BLENDING_COVERAGE:
+ return true;
+ default:
+ VLOGTRACE("unsupported blending %#x", blending);
+ return false;
+ }
+ } else if (planeType == DisplayPlane::PLANE_OVERLAY) {
+ // overlay doesn't support blending
+ return (blending == HWC_BLENDING_NONE) ? true : false;
+ } else {
+ ELOGTRACE("invalid plane type %d", planeType);
+ return false;
+ }
+}
+
+bool PlaneCapabilities::isScalingSupported(int planeType, HwcLayer *hwcLayer)
+{
+ hwc_frect_t& src = hwcLayer->getLayer()->sourceCropf;
+ hwc_rect_t& dest = hwcLayer->getLayer()->displayFrame;
+ uint32_t trans = hwcLayer->getLayer()->transform;
+
+ int srcW, srcH;
+ int dstW, dstH;
+
+ srcW = (int)src.right - (int)src.left;
+ srcH = (int)src.bottom - (int)src.top;
+ dstW = dest.right - dest.left;
+ dstH = dest.bottom - dest.top;
+
+ if (planeType == DisplayPlane::PLANE_SPRITE || planeType == DisplayPlane::PLANE_PRIMARY) {
+ // no scaling is supported
+ return ((srcW == dstW) && (srcH == dstH)) ? true : false;
+
+ } else if (planeType == DisplayPlane::PLANE_OVERLAY) {
+ // overlay cannot support resolution that bigger than 2047x2047.
+ if ((srcW > INTEL_OVERLAY_MAX_WIDTH - 1) || (srcH > INTEL_OVERLAY_MAX_HEIGHT - 1)) {
+ return false;
+ }
+
+ if (dstW <= 1 || dstH <= 1 || srcW <= 1 || srcH <= 1) {
+ // Workaround: Overlay flip when height is 1 causes MIPI stall on TNG
+ DLOGTRACE("invalid destination size: %dx%d, fall back to GLES", dstW, dstH);
+ return false;
+ }
+
+ if (trans == HAL_TRANSFORM_ROT_90 || trans == HAL_TRANSFORM_ROT_270) {
+ int tmp = srcW;
+ srcW = srcH;
+ srcH = tmp;
+ }
+
+ if (!hwcLayer->isProtected()) {
+ if ((int)src.left & 63) {
+ DLOGTRACE("offset %d is not 64 bytes aligned, fall back to GLES", (int)src.left);
+ return false;
+ }
+
+ float scaleX = (float)srcW / dstW;
+ float scaleY = (float)srcH / dstH;
+ if (scaleX > 4.0 || scaleY > 4.0 || scaleX < 0.25 || scaleY < 0.25) {
+ WLOGTRACE("overlay scaling > 4, fall back to GLES");
+ return false;
+ }
+ }
+
+ return true;
+ } else {
+ ELOGTRACE("invalid plane type %d", planeType);
+ return false;
+ }
+}
+
+bool PlaneCapabilities::isTransformSupported(int planeType, HwcLayer *hwcLayer)
+{
+ uint32_t trans = hwcLayer->getLayer()->transform;
+
+ if (planeType == DisplayPlane::PLANE_OVERLAY) {
+ // overlay does not support FLIP_H/FLIP_V
+ switch (trans) {
+ case 0:
+ case HAL_TRANSFORM_ROT_90:
+ case HAL_TRANSFORM_ROT_180:
+ case HAL_TRANSFORM_ROT_270:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // don't transform any tranform
+ return trans ? false : true;
+}
+
+} // namespace intel
+} // namespace android
+
diff --git a/moorefield_hdmi/ips/common/BlankControl.cpp b/moorefield_hdmi/ips/common/BlankControl.cpp
new file mode 100644
index 0000000..53e2bc7
--- /dev/null
+++ b/moorefield_hdmi/ips/common/BlankControl.cpp
@@ -0,0 +1,43 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <common/utils/HwcTrace.h>
+#include <common/base/Drm.h>
+#include <ips/common/BlankControl.h>
+#include <Hwcomposer.h>
+
+namespace android {
+namespace intel {
+
+BlankControl::BlankControl()
+ : IBlankControl()
+{
+}
+
+BlankControl::~BlankControl()
+{
+}
+
+bool BlankControl::blank(int disp, bool blank)
+{
+ // current do nothing but return true
+ // use PM to trigger screen blank/unblank
+ VLOGTRACE("blank is not supported yet, disp %d, blank %d", disp, blank);
+ return true;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/common/BlankControl.h b/moorefield_hdmi/ips/common/BlankControl.h
new file mode 100644
index 0000000..1c0de05
--- /dev/null
+++ b/moorefield_hdmi/ips/common/BlankControl.h
@@ -0,0 +1,36 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef BLANK_CONTROL_H
+#define BLANK_CONTROL_H
+
+#include <IBlankControl.h>
+
+namespace android {
+namespace intel {
+
+class BlankControl : public IBlankControl {
+public:
+ BlankControl();
+ virtual ~BlankControl();
+
+public:
+ bool blank(int disp, bool blank);
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* BLANK_CONTROL_H */
diff --git a/moorefield_hdmi/ips/common/DrmConfig.cpp b/moorefield_hdmi/ips/common/DrmConfig.cpp
new file mode 100644
index 0000000..8575edb
--- /dev/null
+++ b/moorefield_hdmi/ips/common/DrmConfig.cpp
@@ -0,0 +1,79 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <IDisplayDevice.h>
+#include <common/base/Drm.h>
+#include <DrmConfig.h>
+
+
+namespace android {
+namespace intel {
+
+const char* DrmConfig::getDrmPath()
+{
+ return "/dev/card0";
+}
+
+uint32_t DrmConfig::getDrmConnector(int device)
+{
+ if (device == IDisplayDevice::DEVICE_PRIMARY)
+ return DRM_MODE_CONNECTOR_MIPI;
+ else if (device == IDisplayDevice::DEVICE_EXTERNAL)
+ return DRM_MODE_CONNECTOR_DVID;
+ return DRM_MODE_CONNECTOR_Unknown;
+}
+
+uint32_t DrmConfig::getDrmEncoder(int device)
+{
+ if (device == IDisplayDevice::DEVICE_PRIMARY)
+ return DRM_MODE_ENCODER_MIPI;
+ else if (device == IDisplayDevice::DEVICE_EXTERNAL)
+ return DRM_MODE_ENCODER_TMDS;
+ return DRM_MODE_ENCODER_NONE;
+}
+
+uint32_t DrmConfig::getFrameBufferFormat()
+{
+ return HAL_PIXEL_FORMAT_RGBX_8888;
+}
+
+uint32_t DrmConfig::getFrameBufferDepth()
+{
+ return 24;
+}
+
+uint32_t DrmConfig::getFrameBufferBpp()
+{
+ return 32;
+}
+
+const char* DrmConfig::getUeventEnvelope()
+{
+ return "change@/devices/pci0000:00/0000:00:02.0/drm/card0";
+}
+
+const char* DrmConfig::getHotplugString()
+{
+ return "HOTPLUG=1";
+}
+
+const char* DrmConfig::getRepeatedFrameString()
+{
+ return "REPEATED_FRAME";
+}
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/common/DrmControl.cpp b/moorefield_hdmi/ips/common/DrmControl.cpp
new file mode 100644
index 0000000..6969ef3
--- /dev/null
+++ b/moorefield_hdmi/ips/common/DrmControl.cpp
@@ -0,0 +1,58 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <common/utils/HwcTrace.h>
+#include <linux/psb_drm.h>
+#include <Hwcomposer.h>
+#include <ips/common/DrmControl.h>
+
+namespace android {
+namespace intel {
+
+DrmControl::DrmControl()
+ : mVideoExtCommand(0)
+{
+}
+
+DrmControl::~DrmControl()
+{
+}
+
+int DrmControl::getVideoExtCommand()
+{
+ if (mVideoExtCommand) {
+ return mVideoExtCommand;
+ }
+
+ int fd = Hwcomposer::getInstance().getDrm()->getDrmFd();
+
+ union drm_psb_extension_arg video_getparam_arg;
+ strncpy(video_getparam_arg.extension,
+ "lnc_video_getparam", sizeof(video_getparam_arg.extension));
+ int ret = drmCommandWriteRead(fd, DRM_PSB_EXTENSION,
+ &video_getparam_arg, sizeof(video_getparam_arg));
+ if (ret != 0) {
+ VLOGTRACE("failed to get video extension command");
+ return 0;
+ }
+
+ mVideoExtCommand = video_getparam_arg.rep.driver_ioctl_offset;
+
+ return mVideoExtCommand;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/common/DrmControl.h b/moorefield_hdmi/ips/common/DrmControl.h
new file mode 100644
index 0000000..fbd0284
--- /dev/null
+++ b/moorefield_hdmi/ips/common/DrmControl.h
@@ -0,0 +1,38 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef DRM_CONTROL_H
+#define DRM_CONTROL_H
+
+
+namespace android {
+namespace intel {
+
+class DrmControl {
+public:
+ DrmControl();
+ virtual ~DrmControl();
+
+public:
+ int getVideoExtCommand();
+
+private:
+ int mVideoExtCommand;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* DRM_CONTROL_H */
diff --git a/moorefield_hdmi/ips/common/GrallocBufferBase.cpp b/moorefield_hdmi/ips/common/GrallocBufferBase.cpp
new file mode 100644
index 0000000..ed2452a
--- /dev/null
+++ b/moorefield_hdmi/ips/common/GrallocBufferBase.cpp
@@ -0,0 +1,92 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <ips/common/GrallocBufferBase.h>
+#include <DisplayQuery.h>
+#include <khronos/openmax/OMX_IntelVideoExt.h>
+#include <hal_public.h>
+
+namespace android {
+namespace intel {
+
+GrallocBufferBase::GrallocBufferBase(uint32_t handle)
+ : GraphicBuffer(handle)
+{
+ ALOGTRACE("handle = %#x", handle);
+ initBuffer(handle);
+}
+
+void GrallocBufferBase::resetBuffer(uint32_t handle)
+{
+ GraphicBuffer::resetBuffer(handle);
+ initBuffer(handle);
+}
+
+void GrallocBufferBase::initBuffer(uint32_t /* handle */)
+{
+ // nothing to initialize
+}
+
+void GrallocBufferBase::initStride()
+{
+ int yStride, uvStride;
+
+ // setup stride
+ switch (mFormat) {
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_I420:
+ uint32_t yStride_align;
+ yStride_align = DisplayQuery::getOverlayLumaStrideAlignment(mFormat);
+ if (yStride_align > 0)
+ {
+ yStride = align_to(align_to(mWidth, 32), yStride_align);
+ }
+ else
+ {
+ yStride = align_to(align_to(mWidth, 32), 64);
+ }
+ uvStride = align_to(yStride >> 1, 64);
+ mStride.yuv.yStride = yStride;
+ mStride.yuv.uvStride = uvStride;
+ break;
+ case HAL_PIXEL_FORMAT_NV12:
+ yStride = align_to(align_to(mWidth, 32), 64);
+ uvStride = yStride;
+ mStride.yuv.yStride = yStride;
+ mStride.yuv.uvStride = uvStride;
+ break;
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar:
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled:
+ yStride = align_to(align_to(mWidth, 32), 64);
+ uvStride = yStride;
+ mStride.yuv.yStride = yStride;
+ mStride.yuv.uvStride = uvStride;
+ break;
+ case HAL_PIXEL_FORMAT_YUY2:
+ case HAL_PIXEL_FORMAT_UYVY:
+ yStride = align_to((align_to(mWidth, 32) << 1), 64);
+ uvStride = 0;
+ mStride.yuv.yStride = yStride;
+ mStride.yuv.uvStride = uvStride;
+ break;
+ default:
+ mStride.rgb.stride = align_to(((mBpp >> 3) * align_to(mWidth, 32)), 64);
+ break;
+ }
+}
+
+}
+}
diff --git a/moorefield_hdmi/ips/common/GrallocBufferBase.h b/moorefield_hdmi/ips/common/GrallocBufferBase.h
new file mode 100644
index 0000000..d7f4ef9
--- /dev/null
+++ b/moorefield_hdmi/ips/common/GrallocBufferBase.h
@@ -0,0 +1,41 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef GRALLOC_BUFFER_BASE_H
+#define GRALLOC_BUFFER_BASE_H
+
+#include <GraphicBuffer.h>
+
+namespace android {
+namespace intel {
+
+class GrallocBufferBase : public GraphicBuffer {
+public:
+ GrallocBufferBase(uint32_t handle);
+ virtual ~GrallocBufferBase() {}
+ virtual void resetBuffer(uint32_t handle);
+
+protected:
+ // helper function to be invoked by the derived class
+ void initStride();
+
+private:
+ void initBuffer(uint32_t handle);
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* GRALLOC_BUFFER_BASE_H */
diff --git a/moorefield_hdmi/ips/common/GrallocBufferMapperBase.cpp b/moorefield_hdmi/ips/common/GrallocBufferMapperBase.cpp
new file mode 100644
index 0000000..95fc755
--- /dev/null
+++ b/moorefield_hdmi/ips/common/GrallocBufferMapperBase.cpp
@@ -0,0 +1,72 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <common/base/Drm.h>
+#include <Hwcomposer.h>
+#include <ips/common/GrallocBufferMapperBase.h>
+
+namespace android {
+namespace intel {
+
+GrallocBufferMapperBase::GrallocBufferMapperBase(DataBuffer& buffer)
+ : BufferMapper(buffer)
+{
+ CTRACE();
+
+ for (int i = 0; i < SUB_BUFFER_MAX; i++) {
+ mGttOffsetInPage[i] = 0;
+ mCpuAddress[i] = 0;
+ mSize[i] = 0;
+ mKHandle[i] = 0;
+ }
+}
+
+GrallocBufferMapperBase::~GrallocBufferMapperBase()
+{
+ CTRACE();
+}
+
+uint32_t GrallocBufferMapperBase::getGttOffsetInPage(int subIndex) const
+{
+ if (subIndex >= 0 && subIndex < SUB_BUFFER_MAX)
+ return mGttOffsetInPage[subIndex];
+ return 0;
+}
+
+void* GrallocBufferMapperBase::getCpuAddress(int subIndex) const
+{
+ if (subIndex >=0 && subIndex < SUB_BUFFER_MAX)
+ return mCpuAddress[subIndex];
+ return 0;
+}
+
+uint32_t GrallocBufferMapperBase::getSize(int subIndex) const
+{
+ if (subIndex >= 0 && subIndex < SUB_BUFFER_MAX)
+ return mSize[subIndex];
+ return 0;
+}
+
+uint32_t GrallocBufferMapperBase::getKHandle(int subIndex)
+{
+ if (subIndex >= 0 && subIndex < SUB_BUFFER_MAX)
+ return mKHandle[subIndex];
+ return 0;
+}
+
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/common/GrallocBufferMapperBase.h b/moorefield_hdmi/ips/common/GrallocBufferMapperBase.h
new file mode 100644
index 0000000..e193974
--- /dev/null
+++ b/moorefield_hdmi/ips/common/GrallocBufferMapperBase.h
@@ -0,0 +1,52 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef GRALLOC_BUFFER_MAPPER_BASE_H
+#define GRALLOC_BUFFER_MAPPER_BASE_H
+
+#include <BufferMapper.h>
+#include <ips/common/GrallocSubBuffer.h>
+#include <ips/common/GrallocBufferBase.h>
+
+namespace android {
+namespace intel {
+
+class GrallocBufferMapperBase : public BufferMapper {
+public:
+ GrallocBufferMapperBase(DataBuffer& buffer);
+ virtual ~GrallocBufferMapperBase();
+public:
+ virtual bool map() = 0;
+ virtual bool unmap() = 0;
+
+ uint32_t getGttOffsetInPage(int subIndex) const;
+ void* getCpuAddress(int subIndex) const;
+ uint32_t getSize(int subIndex) const;
+ virtual uint32_t getKHandle(int subIndex);
+ virtual uint32_t getFbHandle(int subIndex) = 0;
+ virtual void putFbHandle() = 0;
+
+protected:
+ // mapped info
+ uint32_t mGttOffsetInPage[SUB_BUFFER_MAX];
+ void* mCpuAddress[SUB_BUFFER_MAX];
+ uint32_t mSize[SUB_BUFFER_MAX];
+ uint32_t mKHandle[SUB_BUFFER_MAX];
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* TNG_GRALLOC_BUFFER_MAPPER_H */
diff --git a/moorefield_hdmi/ips/common/GrallocSubBuffer.h b/moorefield_hdmi/ips/common/GrallocSubBuffer.h
new file mode 100644
index 0000000..15170f2
--- /dev/null
+++ b/moorefield_hdmi/ips/common/GrallocSubBuffer.h
@@ -0,0 +1,35 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef GRALLOC_SUB_BUFFER_H
+#define GRALLOC_SUB_BUFFER_H
+
+
+namespace android {
+namespace intel {
+
+enum {
+ SUB_BUFFER0 = 0,
+ SUB_BUFFER1,
+ SUB_BUFFER2,
+ SUB_BUFFER_MAX,
+};
+
+} // namespace intel
+} // namespace android
+
+
+#endif /* GRALLOC_SUB_BUFFER_H */
+
diff --git a/moorefield_hdmi/ips/common/HdcpControl.cpp b/moorefield_hdmi/ips/common/HdcpControl.cpp
new file mode 100644
index 0000000..b250ece
--- /dev/null
+++ b/moorefield_hdmi/ips/common/HdcpControl.cpp
@@ -0,0 +1,380 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <DrmConfig.h>
+#include <Hwcomposer.h>
+#include <DisplayQuery.h>
+#include <ips/common/DrmControl.h>
+#include <ips/common/HdcpControl.h>
+#include <cutils/properties.h>
+
+
+namespace android {
+namespace intel {
+
+HdcpControl::HdcpControl()
+ : mCallback(NULL),
+ mUserData(NULL),
+ mCallbackState(CALLBACK_PENDING),
+ mMutex(),
+ mStoppedCondition(),
+ mCompletedCondition(),
+ mWaitForCompletion(false),
+ mStopped(true),
+ mAuthenticated(false),
+ mActionDelay(0),
+ mAuthRetryCount(0)
+{
+}
+
+HdcpControl::~HdcpControl()
+{
+}
+
+bool HdcpControl::startHdcp()
+{
+ // this is a blocking and synchronous call
+ Mutex::Autolock lock(mMutex);
+
+ char prop[PROPERTY_VALUE_MAX];
+ if (property_get("debug.hwc.hdcp.enable", prop, "1") > 0) {
+ if (atoi(prop) == 0) {
+ WLOGTRACE("HDCP is disabled");
+ return false;
+ }
+ }
+
+ if (!mStopped) {
+ WLOGTRACE("HDCP has been started");
+ return true;
+ }
+
+ mStopped = false;
+ mAuthenticated = false;
+ mWaitForCompletion = false;
+
+ mThread = new HdcpControlThread(this);
+ if (!mThread.get()) {
+ ELOGTRACE("failed to create hdcp control thread");
+ return false;
+ }
+
+ if (!runHdcp()) {
+ ELOGTRACE("failed to run HDCP");
+ mStopped = true;
+ mThread = NULL;
+ return false;
+ }
+
+ mAuthRetryCount = 0;
+ mWaitForCompletion = !mAuthenticated;
+ if (mAuthenticated) {
+ mActionDelay = HDCP_VERIFICATION_DELAY_MS;
+ } else {
+ mActionDelay = HDCP_AUTHENTICATION_SHORT_DELAY_MS;
+ }
+
+ mThread->run("HdcpControl", PRIORITY_NORMAL);
+
+ if (!mWaitForCompletion) {
+ // HDCP is authenticated.
+ return true;
+ }
+ status_t err = mCompletedCondition.waitRelative(mMutex, milliseconds(HDCP_AUTHENTICATION_TIMEOUT_MS));
+ if (err == -ETIMEDOUT) {
+ WLOGTRACE("timeout waiting for completion");
+ }
+ mWaitForCompletion = false;
+ return mAuthenticated;
+}
+
+bool HdcpControl::startHdcpAsync(HdcpStatusCallback cb, void *userData)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ if (property_get("debug.hwc.hdcp.enable", prop, "1") > 0) {
+ if (atoi(prop) == 0) {
+ WLOGTRACE("HDCP is disabled");
+ return false;
+ }
+ }
+
+ if (cb == NULL || userData == NULL) {
+ ELOGTRACE("invalid callback or user data");
+ return false;
+ }
+
+ Mutex::Autolock lock(mMutex);
+
+ if (!mStopped) {
+ WLOGTRACE("HDCP has been started");
+ return true;
+ }
+
+ mThread = new HdcpControlThread(this);
+ if (!mThread.get()) {
+ ELOGTRACE("failed to create hdcp control thread");
+ return false;
+ }
+
+ mAuthRetryCount = 0;
+ mCallback = cb;
+ mUserData = userData;
+ mCallbackState = CALLBACK_PENDING;
+ mWaitForCompletion = false;
+ mAuthenticated = false;
+ mStopped = false;
+ mActionDelay = HDCP_ASYNC_START_DELAY_MS;
+ mThread->run("HdcpControl", PRIORITY_NORMAL);
+
+ return true;
+}
+
+bool HdcpControl::stopHdcp()
+{
+ do {
+ Mutex::Autolock lock(mMutex);
+ if (mStopped) {
+ return true;
+ }
+
+ mStopped = true;
+ mStoppedCondition.signal();
+
+ mAuthenticated = false;
+ mWaitForCompletion = false;
+ mCallback = NULL;
+ mUserData = NULL;
+ disableAuthentication();
+ } while (0);
+
+ if (mThread.get()) {
+ mThread->requestExitAndWait();
+ mThread = NULL;
+ }
+
+ return true;
+}
+
+bool HdcpControl::enableAuthentication()
+{
+ int fd = Hwcomposer::getInstance().getDrm()->getDrmFd();
+ int ret = drmCommandNone(fd, DRM_PSB_ENABLE_HDCP);
+ if (ret != 0) {
+ ELOGTRACE("failed to enable HDCP authentication");
+ return false;
+ }
+ return true;
+}
+
+bool HdcpControl::disableAuthentication()
+{
+ int fd = Hwcomposer::getInstance().getDrm()->getDrmFd();
+ int ret = drmCommandNone(fd, DRM_PSB_DISABLE_HDCP);
+ if (ret != 0) {
+ ELOGTRACE("failed to stop disable authentication");
+ return false;
+ }
+ return true;
+}
+
+bool HdcpControl::enableOverlay()
+{
+ return true;
+}
+
+bool HdcpControl::disableOverlay()
+{
+ return true;
+}
+
+bool HdcpControl::enableDisplayIED()
+{
+ int fd = Hwcomposer::getInstance().getDrm()->getDrmFd();
+ int ret = drmCommandNone(fd, DRM_PSB_HDCP_DISPLAY_IED_ON);
+ if (ret != 0) {
+ ELOGTRACE("failed to enable overlay IED");
+ return false;
+ }
+ return true;
+}
+
+bool HdcpControl::disableDisplayIED()
+{
+ int fd = Hwcomposer::getInstance().getDrm()->getDrmFd();
+ int ret = drmCommandNone(fd, DRM_PSB_HDCP_DISPLAY_IED_OFF);
+ if (ret != 0) {
+ ELOGTRACE("failed to disable overlay IED");
+ return false;
+ }
+ return true;
+}
+
+bool HdcpControl::isHdcpSupported()
+{
+ int fd = Hwcomposer::getInstance().getDrm()->getDrmFd();
+ unsigned int caps = 0;
+ int ret = drmCommandRead(fd, DRM_PSB_QUERY_HDCP, &caps, sizeof(caps));
+ if (ret != 0) {
+ ELOGTRACE("failed to query HDCP capability");
+ return false;
+ }
+ if (caps == 0) {
+ WLOGTRACE("HDCP is not supported");
+ return false;
+ } else {
+ ILOGTRACE("HDCP is supported");
+ return true;
+ }
+}
+
+bool HdcpControl::checkAuthenticated()
+{
+ int fd = Hwcomposer::getInstance().getDrm()->getDrmFd();
+ unsigned int match = 0;
+ int ret = drmCommandRead(fd, DRM_PSB_GET_HDCP_LINK_STATUS, &match, sizeof(match));
+ if (ret != 0) {
+ ELOGTRACE("failed to get hdcp link status");
+ return false;
+ }
+ if (match) {
+ VLOGTRACE("HDCP is authenticated");
+ mAuthenticated = true;
+ } else {
+ ELOGTRACE("HDCP is not authenticated");
+ mAuthenticated = false;
+ }
+ return mAuthenticated;
+}
+
+bool HdcpControl::runHdcp()
+{
+ // Default return value is true so HDCP can be re-authenticated in the working thread
+ bool ret = true;
+
+ preRunHdcp();
+
+ for (int i = 0; i < HDCP_INLOOP_RETRY_NUMBER; i++) {
+ VLOGTRACE("enable and verify HDCP, iteration# %d", i);
+ if (mStopped) {
+ WLOGTRACE("HDCP authentication has been stopped");
+ ret = false;
+ break;
+ }
+
+ if (!enableAuthentication()) {
+ ELOGTRACE("HDCP authentication failed. Retry");
+ mAuthenticated = false;
+ ret = true;
+ } else {
+ ILOGTRACE("HDCP is authenticated");
+ mAuthenticated = true;
+ ret = true;
+ break;
+ }
+
+ if (mStopped) {
+ WLOGTRACE("HDCP authentication has been stopped");
+ ret = false;
+ break;
+ }
+
+ if (i < HDCP_INLOOP_RETRY_NUMBER - 1) {
+ // Adding delay to make sure panel receives video signal so it can start HDCP authentication.
+ // (HDCP spec 1.3, section 2.3)
+ usleep(HDCP_INLOOP_RETRY_DELAY_US);
+ }
+ }
+
+ postRunHdcp();
+
+ return ret;
+}
+
+bool HdcpControl::preRunHdcp()
+{
+ // TODO: for CTP platform, IED needs to be disabled during HDCP authentication.
+ return true;
+}
+
+bool HdcpControl::postRunHdcp()
+{
+ // TODO: for CTP platform, IED needs to be disabled during HDCP authentication.
+ return true;
+}
+
+
+void HdcpControl::signalCompletion()
+{
+ if (mWaitForCompletion) {
+ ILOGTRACE("signal HDCP authentication completed, status = %d", mAuthenticated);
+ mCompletedCondition.signal();
+ mWaitForCompletion = false;
+ }
+}
+
+bool HdcpControl::threadLoop()
+{
+ Mutex::Autolock lock(mMutex);
+ status_t err = mStoppedCondition.waitRelative(mMutex, milliseconds(mActionDelay));
+ if (err != -ETIMEDOUT) {
+ ILOGTRACE("Hdcp is stopped.");
+ signalCompletion();
+ return false;
+ }
+
+ // default is to keep thread active
+ bool ret = true;
+ if (!mAuthenticated) {
+ ret = runHdcp();
+ mAuthRetryCount++;
+ } else {
+ mAuthRetryCount = 0;
+ checkAuthenticated();
+ }
+
+ // set next action delay
+ if (mAuthenticated) {
+ mActionDelay = HDCP_VERIFICATION_DELAY_MS;
+ } else {
+ // If HDCP can not authenticate after "HDCP_RETRY_LIMIT" attempts
+ // reduce HDCP retry frequency to 2 sec
+ if (mAuthRetryCount >= HDCP_RETRY_LIMIT) {
+ mActionDelay = HDCP_AUTHENTICATION_LONG_DELAY_MS;
+ } else {
+ mActionDelay = HDCP_AUTHENTICATION_SHORT_DELAY_MS;
+ }
+ }
+
+ // TODO: move out of lock?
+ if (!ret || mAuthenticated) {
+ signalCompletion();
+ }
+
+ if (mCallback) {
+ if ((mAuthenticated && mCallbackState == CALLBACK_AUTHENTICATED) ||
+ (!mAuthenticated && mCallbackState == CALLBACK_NOT_AUTHENTICATED)) {
+ // ignore callback as state is not changed
+ } else {
+ mCallbackState =
+ mAuthenticated ? CALLBACK_AUTHENTICATED : CALLBACK_NOT_AUTHENTICATED;
+ (*mCallback)(mAuthenticated, mUserData);
+ }
+ }
+ return ret;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/common/HdcpControl.h b/moorefield_hdmi/ips/common/HdcpControl.h
new file mode 100644
index 0000000..301ee96
--- /dev/null
+++ b/moorefield_hdmi/ips/common/HdcpControl.h
@@ -0,0 +1,87 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef HDCP_CONTROL_H
+#define HDCP_CONTROL_H
+
+#include <IHdcpControl.h>
+#include <common/base/SimpleThread.h>
+
+namespace android {
+namespace intel {
+
+class HdcpControl : public IHdcpControl {
+public:
+ HdcpControl();
+ virtual ~HdcpControl();
+
+public:
+ virtual bool startHdcp();
+ virtual bool startHdcpAsync(HdcpStatusCallback cb, void *userData);
+ virtual bool stopHdcp();
+
+protected:
+ bool enableAuthentication();
+ bool disableAuthentication();
+ bool enableOverlay();
+ bool disableOverlay();
+ bool enableDisplayIED();
+ bool disableDisplayIED();
+ bool isHdcpSupported();
+ bool checkAuthenticated();
+ virtual bool preRunHdcp();
+ virtual bool postRunHdcp();
+ bool runHdcp();
+ inline void signalCompletion();
+
+private:
+ enum {
+ HDCP_INLOOP_RETRY_NUMBER = 1,
+ HDCP_INLOOP_RETRY_DELAY_US = 50000,
+ HDCP_VERIFICATION_DELAY_MS = 2000,
+ HDCP_ASYNC_START_DELAY_MS = 100,
+ HDCP_AUTHENTICATION_SHORT_DELAY_MS = 200,
+ HDCP_AUTHENTICATION_LONG_DELAY_MS = 2000,
+ HDCP_AUTHENTICATION_TIMEOUT_MS = 5000,
+ HDCP_RETRY_LIMIT = 10,
+ };
+
+ enum {
+ CALLBACK_PENDING,
+ CALLBACK_AUTHENTICATED,
+ CALLBACK_NOT_AUTHENTICATED,
+ };
+
+protected:
+ HdcpStatusCallback mCallback;
+ void *mUserData;
+ int mCallbackState;
+ Mutex mMutex;
+ Condition mStoppedCondition;
+ Condition mCompletedCondition;
+ bool mWaitForCompletion;
+ bool mStopped;
+ bool mAuthenticated;
+ int mActionDelay; // in milliseconds
+ uint32_t mAuthRetryCount;
+
+private:
+ DECLARE_THREAD(HdcpControlThread, HdcpControl);
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* HDCP_CONTROL_H */
diff --git a/moorefield_hdmi/ips/common/OverlayHardware.h b/moorefield_hdmi/ips/common/OverlayHardware.h
new file mode 100644
index 0000000..a06f304
--- /dev/null
+++ b/moorefield_hdmi/ips/common/OverlayHardware.h
@@ -0,0 +1,160 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef OVERLAY_HARDWARE_H
+#define OVERLAY_HARDWARE_H
+
+namespace android {
+namespace intel {
+
+// only one overlay data buffer for testing
+#define INTEL_OVERLAY_BUFFER_NUM 1
+#define INTEL_OVERLAY_MAX_WIDTH 2048
+#define INTEL_OVERLAY_MAX_HEIGHT 2048
+#define INTEL_OVERLAY_MIN_STRIDE 512
+#define INTEL_OVERLAY_MAX_STRIDE_PACKED (8 * 1024)
+#define INTEL_OVERLAY_MAX_STRIDE_LINEAR (4 * 1024)
+#define INTEL_OVERLAY_MAX_SCALING_RATIO 7
+
+// Polyphase filter coefficients
+#define N_HORIZ_Y_TAPS 5
+#define N_VERT_Y_TAPS 3
+#define N_HORIZ_UV_TAPS 3
+#define N_VERT_UV_TAPS 3
+#define N_PHASES 17
+#define MAX_TAPS 5
+
+// Filter cutoff frequency limits.
+#define MIN_CUTOFF_FREQ 1.0
+#define MAX_CUTOFF_FREQ 3.0
+
+// Overlay init micros
+#define OVERLAY_INIT_CONTRAST 0x4b
+#define OVERLAY_INIT_BRIGHTNESS -19
+#define OVERLAY_INIT_SATURATION 0x92
+#define OVERLAY_INIT_GAMMA0 0x080808
+#define OVERLAY_INIT_GAMMA1 0x101010
+#define OVERLAY_INIT_GAMMA2 0x202020
+#define OVERLAY_INIT_GAMMA3 0x404040
+#define OVERLAY_INIT_GAMMA4 0x808080
+#define OVERLAY_INIT_GAMMA5 0xc0c0c0
+#define OVERLAY_INIT_COLORKEY 0
+#define OVERLAY_INIT_COLORKEYMASK ((0x0 << 31) | (0X0 << 30))
+#define OVERLAY_INIT_CONFIG ((0x1 << 18) | (0x1 << 3))
+
+// overlay register values
+#define OVERLAY_FORMAT_MASK (0xf << 10)
+#define OVERLAY_FORMAT_PACKED_YUV422 (0x8 << 10)
+#define OVERLAY_FORMAT_PLANAR_NV12_1 (0x7 << 10)
+#define OVERLAY_FORMAT_PLANAR_NV12_2 (0xb << 10)
+#define OVERLAY_FORMAT_PLANAR_YUV420 (0xc << 10)
+#define OVERLAY_FORMAT_PLANAR_YUV422 (0xd << 10)
+#define OVERLAY_FORMAT_PLANAR_YUV41X (0xe << 10)
+
+#define OVERLAY_PACKED_ORDER_YUY2 (0x0 << 14)
+#define OVERLAY_PACKED_ORDER_YVYU (0x1 << 14)
+#define OVERLAY_PACKED_ORDER_UYVY (0x2 << 14)
+#define OVERLAY_PACKED_ORDER_VYUY (0x3 << 14)
+#define OVERLAY_PACKED_ORDER_MASK (0x3 << 14)
+
+#define OVERLAY_MEMORY_LAYOUT_TILED (0x1 << 19)
+#define OVERLAY_MEMORY_LAYOUT_LINEAR (0x0 << 19)
+
+#define OVERLAY_MIRRORING_NORMAL (0x0 << 17)
+#define OVERLAY_MIRRORING_HORIZONTAL (0x1 << 17)
+#define OVERLAY_MIRRORING_VERTIACAL (0x2 << 17)
+#define OVERLAY_MIRRORING_BOTH (0x3 << 17)
+
+#define BUF_TYPE (0x1<<5)
+#define BUF_TYPE_FRAME (0x0<<5)
+#define BUF_TYPE_FIELD (0x1<<5)
+#define TEST_MODE (0x1<<4)
+#define BUFFER_SELECT (0x3<<2)
+#define BUFFER0 (0x0<<2)
+#define BUFFER1 (0x1<<2)
+#define FIELD_SELECT (0x1<<1)
+#define FIELD0 (0x0<<1)
+#define FIELD1 (0x1<<1)
+#define OVERLAY_ENABLE 0x1
+
+
+// Overlay contorl registers
+typedef struct {
+ uint32_t OBUF_0Y;
+ uint32_t OBUF_1Y;
+ uint32_t OBUF_0U;
+ uint32_t OBUF_0V;
+ uint32_t OBUF_1U;
+ uint32_t OBUF_1V;
+ uint32_t OSTRIDE;
+ uint32_t YRGB_VPH;
+ uint32_t UV_VPH;
+ uint32_t HORZ_PH;
+ uint32_t INIT_PHS;
+ uint32_t DWINPOS;
+ uint32_t DWINSZ;
+ uint32_t SWIDTH;
+ uint32_t SWIDTHSW;
+ uint32_t SHEIGHT;
+ uint32_t YRGBSCALE;
+ uint32_t UVSCALE;
+ uint32_t OCLRC0;
+ uint32_t OCLRC1;
+ uint32_t DCLRKV;
+ uint32_t DCLRKM;
+ uint32_t SCHRKVH;
+ uint32_t SCHRKVL;
+ uint32_t SCHRKEN;
+ uint32_t OCONFIG;
+ uint32_t OCMD;
+ uint32_t RESERVED1;
+ uint32_t OSTART_0Y;
+ uint32_t OSTART_1Y;
+ uint32_t OSTART_0U;
+ uint32_t OSTART_0V;
+ uint32_t OSTART_1U;
+ uint32_t OSTART_1V;
+ uint32_t OTILEOFF_0Y;
+ uint32_t OTILEOFF_1Y;
+ uint32_t OTILEOFF_0U;
+ uint32_t OTILEOFF_0V;
+ uint32_t OTILEOFF_1U;
+ uint32_t OTILEOFF_1V;
+ uint32_t FASTHSCALE;
+ uint32_t UVSCALEV;
+
+ uint32_t RESERVEDC[(0x200 - 0xA8) / 4];
+ uint16_t Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES];
+ uint16_t RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
+ uint16_t Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES];
+ uint16_t RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
+ uint16_t UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES];
+ uint16_t RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
+ uint16_t UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES];
+ uint16_t RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
+} OverlayBackBufferBlk;
+
+typedef struct {
+ uint8_t sign;
+ uint16_t mantissa;
+ uint8_t exponent;
+} coeffRec, *coeffPtr;
+
+
+} // namespace intel
+} // nam
+
+
+#endif
diff --git a/moorefield_hdmi/ips/common/OverlayPlaneBase.cpp b/moorefield_hdmi/ips/common/OverlayPlaneBase.cpp
new file mode 100755
index 0000000..2a41177
--- /dev/null
+++ b/moorefield_hdmi/ips/common/OverlayPlaneBase.cpp
@@ -0,0 +1,1199 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <math.h>
+#include <common/utils/HwcTrace.h>
+#include <common/base/Drm.h>
+#include <Hwcomposer.h>
+#include <PhysicalDevice.h>
+#include <ips/common/OverlayPlaneBase.h>
+#include <ips/common/TTMBufferMapper.h>
+#include <ips/common/GrallocSubBuffer.h>
+#include <DisplayQuery.h>
+#include <khronos/openmax/OMX_IntelVideoExt.h>
+#include <hal_public.h>
+
+namespace android {
+namespace intel {
+
+OverlayPlaneBase::OverlayPlaneBase(int index, int disp)
+ : DisplayPlane(index, PLANE_OVERLAY, disp),
+ mTTMBuffers(),
+ mActiveTTMBuffers(),
+ mCurrent(0),
+ mWsbm(0),
+ mPipeConfig(0),
+ mBobDeinterlace(0)
+{
+ CTRACE();
+ for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
+ mBackBuffer[i] = 0;
+ }
+}
+
+OverlayPlaneBase::~OverlayPlaneBase()
+{
+ CTRACE();
+}
+
+bool OverlayPlaneBase::initialize(uint32_t bufferCount)
+{
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ CTRACE();
+
+ // NOTE: use overlay's data buffer count for the overlay plane
+ if (bufferCount < OVERLAY_DATA_BUFFER_COUNT) {
+ ILOGTRACE("override overlay buffer count from %d to %d",
+ bufferCount, OVERLAY_DATA_BUFFER_COUNT);
+ bufferCount = OVERLAY_DATA_BUFFER_COUNT;
+ }
+ if (!DisplayPlane::initialize(bufferCount)) {
+ DEINIT_AND_RETURN_FALSE("failed to initialize display plane");
+ }
+
+ mTTMBuffers.setCapacity(bufferCount);
+ mActiveTTMBuffers.setCapacity(MIN_DATA_BUFFER_COUNT);
+
+ // init wsbm
+ mWsbm = new Wsbm(drm->getDrmFd());
+ if (!mWsbm || !mWsbm->initialize()) {
+ DEINIT_AND_RETURN_FALSE("failed to create wsbm");
+ }
+
+ // create overlay back buffer
+ for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
+ mBackBuffer[i] = createBackBuffer();
+ if (!mBackBuffer[i]) {
+ DEINIT_AND_RETURN_FALSE("failed to create overlay back buffer");
+ }
+ // reset back buffer
+ resetBackBuffer(i);
+ }
+
+ // disable overlay when created
+ flush(PLANE_DISABLE);
+
+ return true;
+}
+
+bool OverlayPlaneBase::isDisabled()
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ struct drm_psb_register_rw_arg arg;
+ memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
+
+ arg.get_plane_state_mask = 1;
+ arg.plane.type = DC_OVERLAY_PLANE;
+ arg.plane.index = mIndex;
+ // pass the pipe index to check its enabled status
+ // now we can pass the device id directly since
+ // their values are just equal
+ arg.plane.ctx = mDevice; // not used in kernel
+
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
+ if (ret == false) {
+ WLOGTRACE("overlay plane query failed with error code %d", ret);
+ return false;
+ }
+
+ DLOGTRACE("overlay %d status %s on device %d, current device %d",
+ mIndex, arg.plane.ctx ? "DISABLED" : "ENABLED", mDevice, mDevice);
+
+ return arg.plane.ctx == PSB_DC_PLANE_DISABLED;
+}
+
+void OverlayPlaneBase::deinitialize()
+{
+ if (mTTMBuffers.size()) {
+ invalidateBufferCache();
+ }
+
+ if (mActiveTTMBuffers.size() > 0) {
+ invalidateActiveTTMBuffers();
+ }
+
+ // delete back buffer
+ for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
+ if (mBackBuffer[i]) {
+ deleteBackBuffer(i);
+ mBackBuffer[i] = NULL;
+ }
+ }
+ DEINIT_AND_DELETE_OBJ(mWsbm);
+
+ DisplayPlane::deinitialize();
+}
+
+void OverlayPlaneBase::invalidateBufferCache()
+{
+ // clear plane buffer cache
+ DisplayPlane::invalidateBufferCache();
+ invalidateTTMBuffers();
+}
+
+bool OverlayPlaneBase::assignToDevice(int disp)
+{
+ uint32_t pipeConfig = 0;
+
+ RETURN_FALSE_IF_NOT_INIT();
+ VLOGTRACE("overlay %d assigned to disp %d", mIndex, disp);
+
+ switch (disp) {
+ case IDisplayDevice::DEVICE_EXTERNAL:
+ pipeConfig = (0x2 << 6);
+ break;
+ case IDisplayDevice::DEVICE_PRIMARY:
+ default:
+ pipeConfig = 0;
+ break;
+ }
+
+ // if pipe switching happened, then disable overlay first
+ if (mPipeConfig != pipeConfig) {
+ DLOGTRACE("overlay %d switched from %d to %d", mIndex, mDevice, disp);
+ disable();
+ }
+
+ mPipeConfig = pipeConfig;
+ DisplayPlane::assignToDevice(disp);
+
+ enable();
+
+ return true;
+}
+
+void OverlayPlaneBase::setZOrderConfig(ZOrderConfig& zorderConfig,
+ void * /*nativeConfig*/)
+{
+ CTRACE();
+
+ // setup overlay z order
+ int ovaZOrder = -1;
+ int ovcZOrder = -1;
+ for (size_t i = 0; i < zorderConfig.size(); i++) {
+ DisplayPlane *plane = zorderConfig[i]->plane;
+ if (plane->getType() == DisplayPlane::PLANE_OVERLAY) {
+ if (plane->getIndex() == 0) {
+ ovaZOrder = i;
+ } else if (plane->getIndex() == 1) {
+ ovcZOrder = i;
+ }
+ }
+ }
+
+ for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[i]->buf;
+ if (!backBuffer)
+ return;
+
+ // force overlay c above overlay a
+ if ((ovaZOrder >= 0) && (ovaZOrder < ovcZOrder)) {
+ backBuffer->OCONFIG |= (1 << 15);
+ } else {
+ backBuffer->OCONFIG &= ~(1 << 15);
+ }
+ }
+}
+
+bool OverlayPlaneBase::reset()
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ DisplayPlane::reset();
+
+ // invalidate active TTM buffers
+ if (mActiveTTMBuffers.size() > 0) {
+ invalidateActiveTTMBuffers();
+ }
+
+ // reset back buffers
+ for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
+ resetBackBuffer(i);
+ }
+ return true;
+}
+
+bool OverlayPlaneBase::enable()
+{
+ RETURN_FALSE_IF_NOT_INIT();
+ for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[i]->buf;
+ if (!backBuffer)
+ return false;
+
+ if (backBuffer->OCMD & 0x1)
+ return true;
+
+ backBuffer->OCMD |= 0x1;
+ }
+
+ // flush
+ flush(PLANE_ENABLE);
+ return true;
+}
+
+bool OverlayPlaneBase::disable()
+{
+ RETURN_FALSE_IF_NOT_INIT();
+ for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[i]->buf;
+ if (!backBuffer)
+ return false;
+
+ if (!(backBuffer->OCMD & 0x1))
+ return true;
+
+ backBuffer->OCMD &= ~0x1;
+ }
+
+ // flush
+ flush(PLANE_DISABLE);
+ return true;
+}
+
+OverlayBackBuffer* OverlayPlaneBase::createBackBuffer()
+{
+ CTRACE();
+
+ // create back buffer
+ OverlayBackBuffer *backBuffer = (OverlayBackBuffer *)malloc(sizeof(OverlayBackBuffer));
+ if (!backBuffer) {
+ ELOGTRACE("failed to allocate back buffer");
+ return 0;
+ }
+
+
+ int size = sizeof(OverlayBackBufferBlk);
+ int alignment = 64 * 1024;
+ void *wsbmBufferObject = 0;
+ bool ret = mWsbm->allocateTTMBuffer(size, alignment, &wsbmBufferObject);
+ if (ret == false) {
+ ELOGTRACE("failed to allocate TTM buffer");
+ return 0;
+ }
+
+ void *virtAddr = mWsbm->getCPUAddress(wsbmBufferObject);
+ uint32_t gttOffsetInPage = mWsbm->getGttOffset(wsbmBufferObject);
+
+ backBuffer->buf = (OverlayBackBufferBlk *)virtAddr;
+ backBuffer->gttOffsetInPage = gttOffsetInPage;
+ backBuffer->bufObject = (uint32_t)wsbmBufferObject;
+
+ VLOGTRACE("cpu %p, gtt %d", virtAddr, gttOffsetInPage);
+
+ return backBuffer;
+}
+
+void OverlayPlaneBase::deleteBackBuffer(int buf)
+{
+ if (!mBackBuffer[buf])
+ return;
+
+ void *wsbmBufferObject = (void *)mBackBuffer[buf]->bufObject;
+ bool ret = mWsbm->destroyTTMBuffer(wsbmBufferObject);
+ if (ret == false) {
+ WLOGTRACE("failed to destroy TTM buffer");
+ }
+ // free back buffer
+ free(mBackBuffer[buf]);
+ mBackBuffer[buf] = 0;
+}
+
+void OverlayPlaneBase::resetBackBuffer(int buf)
+{
+ CTRACE();
+
+ if (!mBackBuffer[buf] || !mBackBuffer[buf]->buf)
+ return;
+
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[buf]->buf;
+
+ memset(backBuffer, 0, sizeof(OverlayBackBufferBlk));
+
+ // reset overlay
+ backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) |
+ (OVERLAY_INIT_BRIGHTNESS & 0xff);
+ backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION;
+ backBuffer->DCLRKV = OVERLAY_INIT_COLORKEY;
+ backBuffer->DCLRKM = OVERLAY_INIT_COLORKEYMASK;
+ backBuffer->OCONFIG = 0;
+ backBuffer->OCONFIG |= (0x1 << 3);
+ backBuffer->OCONFIG |= (0x1 << 27);
+ backBuffer->SCHRKEN &= ~(0x7 << 24);
+ backBuffer->SCHRKEN |= 0xff;
+}
+
+BufferMapper* OverlayPlaneBase::getTTMMapper(BufferMapper& grallocMapper, struct VideoPayloadBuffer *payload)
+{
+ uint32_t khandle;
+ uint32_t w, h;
+ uint32_t yStride, uvStride;
+ stride_t stride;
+ int srcX, srcY, srcW, srcH;
+ int tmp;
+
+ DataBuffer *buf;
+ ssize_t index;
+ TTMBufferMapper *mapper;
+ bool ret;
+
+ if (!payload) {
+ ELOGTRACE("invalid payload buffer");
+ return 0;
+ }
+
+ srcX = grallocMapper.getCrop().x;
+ srcY = grallocMapper.getCrop().y;
+ srcW = grallocMapper.getCrop().w;
+ srcH = grallocMapper.getCrop().h;
+
+ // init ttm buffer
+ khandle = payload->rotated_buffer_handle;
+ index = mTTMBuffers.indexOfKey(khandle);
+ if (index < 0) {
+ VLOGTRACE("unmapped TTM buffer, will map it");
+
+ w = payload->rotated_width;
+ h = payload->rotated_height;
+ checkCrop(srcX, srcY, srcW, srcH, payload->coded_width, payload->coded_height);
+
+ uint32_t format = grallocMapper.getFormat();
+ // this is for sw decode with tiled buffer in landscape mode
+ if (payload->tiling)
+ format = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled;
+
+ // calculate stride
+ switch (format) {
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_I420:
+ uint32_t yStride_align;
+ yStride_align = DisplayQuery::getOverlayLumaStrideAlignment(grallocMapper.getFormat());
+ if (yStride_align > 0)
+ {
+ yStride = align_to(align_to(w, 32), yStride_align);
+ }
+ else
+ {
+ yStride = align_to(align_to(w, 32), 64);
+ }
+ uvStride = align_to(yStride >> 1, 64);
+ stride.yuv.yStride = yStride;
+ stride.yuv.uvStride = uvStride;
+ break;
+ case HAL_PIXEL_FORMAT_NV12:
+ yStride = align_to(align_to(w, 32), 64);
+ uvStride = yStride;
+ stride.yuv.yStride = yStride;
+ stride.yuv.uvStride = uvStride;
+ break;
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar:
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled:
+ yStride = align_to(align_to(w, 32), 64);
+ uvStride = yStride;
+ stride.yuv.yStride = yStride;
+ stride.yuv.uvStride = uvStride;
+ break;
+ case HAL_PIXEL_FORMAT_YUY2:
+ case HAL_PIXEL_FORMAT_UYVY:
+ yStride = align_to((align_to(w, 32) << 1), 64);
+ uvStride = 0;
+ stride.yuv.yStride = yStride;
+ stride.yuv.uvStride = uvStride;
+ break;
+ }
+
+ DataBuffer buf(khandle);
+ // update buffer
+ buf.setStride(stride);
+ buf.setWidth(w);
+ buf.setHeight(h);
+ buf.setCrop(srcX, srcY, srcW, srcH);
+ buf.setFormat(format);
+
+ // create buffer mapper
+ bool res = false;
+ do {
+ mapper = new TTMBufferMapper(*mWsbm, buf);
+ if (!mapper) {
+ ELOGTRACE("failed to allocate mapper");
+ break;
+ }
+ // map ttm buffer
+ ret = mapper->map();
+ if (!ret) {
+ ELOGTRACE("failed to map");
+ invalidateTTMBuffers();
+ ret = mapper->map();
+ if (!ret) {
+ ELOGTRACE("failed to remap");
+ break;
+ }
+ }
+
+ if (mTTMBuffers.size() >= OVERLAY_DATA_BUFFER_COUNT) {
+ invalidateTTMBuffers();
+ }
+
+ // add mapper
+ index = mTTMBuffers.add(khandle, mapper);
+ if (index < 0) {
+ ELOGTRACE("failed to add TTMMapper");
+ break;
+ }
+
+ // increase mapper refCount since it is added to mTTMBuffers
+ mapper->incRef();
+ res = true;
+ } while (0);
+
+ if (!res) {
+ // error handling
+ if (mapper) {
+ mapper->unmap();
+ delete mapper;
+ mapper = NULL;
+ }
+ return 0;
+ }
+ } else {
+ VLOGTRACE("got mapper in saved ttm buffers");
+ mapper = reinterpret_cast<TTMBufferMapper *>(mTTMBuffers.valueAt(index));
+ if (mapper->getCrop().x != srcX || mapper->getCrop().y != srcY ||
+ mapper->getCrop().w != srcW || mapper->getCrop().h != srcH) {
+ checkCrop(srcX, srcY, srcW, srcH, payload->coded_width, payload->coded_height);
+ mapper->setCrop(srcX, srcY, srcW, srcH);
+ }
+ }
+
+ XLOGTRACE();
+ return mapper;
+}
+
+void OverlayPlaneBase::putTTMMapper(BufferMapper* mapper)
+{
+ if (!mapper)
+ return;
+
+ if (!mapper->decRef()) {
+ // unmap it
+ mapper->unmap();
+
+ // destroy this mapper
+ delete mapper;
+ }
+}
+
+bool OverlayPlaneBase::isActiveTTMBuffer(BufferMapper *mapper)
+{
+ for (size_t i = 0; i < mActiveTTMBuffers.size(); i++) {
+ BufferMapper *activeMapper = mActiveTTMBuffers.itemAt(i);
+ if (!activeMapper)
+ continue;
+ if (activeMapper->getKey() == mapper->getKey())
+ return true;
+ }
+
+ return false;
+}
+
+void OverlayPlaneBase::updateActiveTTMBuffers(BufferMapper *mapper)
+{
+ // unmap the first entry (oldest buffer)
+ if (mActiveTTMBuffers.size() >= MAX_ACTIVE_TTM_BUFFERS) {
+ BufferMapper *oldest = mActiveTTMBuffers.itemAt(0);
+ putTTMMapper(oldest);
+ mActiveTTMBuffers.removeAt(0);
+ }
+
+ // queue it to cached buffers
+ if (!isActiveTTMBuffer(mapper)) {
+ mapper->incRef();
+ mActiveTTMBuffers.push_back(mapper);
+ }
+}
+
+void OverlayPlaneBase::invalidateActiveTTMBuffers()
+{
+ BufferMapper* mapper;
+
+ RETURN_VOID_IF_NOT_INIT();
+
+ for (size_t i = 0; i < mActiveTTMBuffers.size(); i++) {
+ mapper = mActiveTTMBuffers.itemAt(i);
+ // unmap it
+ putTTMMapper(mapper);
+ }
+
+ // clear recorded data buffers
+ mActiveTTMBuffers.clear();
+}
+
+void OverlayPlaneBase::invalidateTTMBuffers()
+{
+ BufferMapper* mapper;
+ for (size_t i = 0; i < mTTMBuffers.size(); i++) {
+ mapper = mTTMBuffers.valueAt(i);
+ // putTTMMapper removes mapper from cache
+ putTTMMapper(mapper);
+ }
+ mTTMBuffers.clear();
+}
+
+
+bool OverlayPlaneBase::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper)
+{
+ struct VideoPayloadBuffer *payload;
+ uint32_t format;
+
+ // only NV12_VED has rotated buffer
+ format = mapper.getFormat();
+ if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
+ format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled)
+ return false;
+
+ payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
+ // check payload
+ if (!payload) {
+ ELOGTRACE("no payload found");
+ return false;
+ }
+
+ if (payload->force_output_method == FORCE_OUTPUT_GPU)
+ return false;
+
+ if (payload->client_transform != mTransform) {
+ if (payload->surface_protected) {
+ payload->hwc_timestamp = systemTime();
+ payload->layer_transform = mTransform;
+ }
+ WLOGTRACE("client is not ready");
+ return false;
+ }
+
+ rotatedMapper = getTTMMapper(mapper, payload);
+ return true;
+}
+
+
+bool OverlayPlaneBase::useOverlayRotation(BufferMapper& /* mapper */)
+{
+ // by default overlay plane does not support rotation.
+ return false;
+}
+
+void OverlayPlaneBase::checkPosition(int& x, int& y, int& w, int& h)
+{
+ drmModeModeInfoPtr mode = &mModeInfo;
+
+ if (mode->hdisplay == 0 || mode->vdisplay == 0)
+ return;
+
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ if ((x + w) > mode->hdisplay)
+ w = mode->hdisplay - x;
+ if ((y + h) > mode->vdisplay)
+ h = mode->vdisplay - y;
+}
+
+void OverlayPlaneBase::checkCrop(int& srcX, int& srcY, int& srcW, int& srcH,
+ int coded_width, int coded_height)
+{
+ int tmp;
+
+ if (mTransform)
+ srcH >>= mBobDeinterlace;
+
+ if (mTransform == HWC_TRANSFORM_ROT_90 || mTransform == HWC_TRANSFORM_ROT_270) {
+ tmp = srcH;
+ srcH = srcW;
+ srcW = tmp;
+
+ tmp = srcX;
+ srcX = srcY;
+ srcY = tmp;
+
+ tmp = coded_width;
+ coded_width = coded_height;
+ coded_height = tmp;
+ }
+
+ // skip pading bytes in rotate buffer
+ switch(mTransform) {
+ case HWC_TRANSFORM_ROT_90:
+ srcX = (coded_width >> mBobDeinterlace) - srcW - srcX;
+ break;
+ case HWC_TRANSFORM_ROT_180:
+ srcX = coded_width - srcW - srcX;
+ srcY = (coded_height >> mBobDeinterlace) - srcH - srcY;
+ break;
+ case HWC_TRANSFORM_ROT_270:
+ srcY = coded_height - srcH - srcY;
+ break;
+ default:
+ break;
+ }
+}
+
+
+bool OverlayPlaneBase::bufferOffsetSetup(BufferMapper& mapper)
+{
+ CTRACE();
+
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
+ if (!backBuffer) {
+ ELOGTRACE("invalid back buffer");
+ return false;
+ }
+
+ uint32_t format = mapper.getFormat();
+ uint32_t gttOffsetInBytes = (mapper.getGttOffsetInPage(0) << 12);
+ uint32_t yStride = mapper.getStride().yuv.yStride;
+ uint32_t uvStride = mapper.getStride().yuv.uvStride;
+ uint32_t w = mapper.getWidth();
+ uint32_t h = mapper.getHeight();
+ uint32_t srcX= mapper.getCrop().x;
+ uint32_t srcY= mapper.getCrop().y;
+
+ // clear original format setting
+ backBuffer->OCMD &= ~(0xf << 10);
+ backBuffer->OCMD &= ~OVERLAY_MEMORY_LAYOUT_TILED;
+
+ // Y/U/V plane must be 4k bytes aligned.
+ backBuffer->OSTART_0Y = gttOffsetInBytes;
+ if (mIsProtectedBuffer) {
+ // temporary workaround until vsync event logic is corrected.
+ // it seems that overlay buffer update and renderring can be overlapped,
+ // as such encryption bit may be cleared during HW rendering
+ backBuffer->OSTART_0Y |= 0x01;
+ }
+
+ backBuffer->OSTART_0U = gttOffsetInBytes;
+ backBuffer->OSTART_0V = gttOffsetInBytes;
+
+ backBuffer->OSTART_1Y = backBuffer->OSTART_0Y;
+ backBuffer->OSTART_1U = backBuffer->OSTART_0U;
+ backBuffer->OSTART_1V = backBuffer->OSTART_0V;
+
+ switch(format) {
+ case HAL_PIXEL_FORMAT_YV12: // YV12
+ backBuffer->OBUF_0Y = 0;
+ backBuffer->OBUF_0V = yStride * h;
+ backBuffer->OBUF_0U = backBuffer->OBUF_0V + (uvStride * (h / 2));
+ backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
+ break;
+ case HAL_PIXEL_FORMAT_I420: // I420
+ backBuffer->OBUF_0Y = 0;
+ backBuffer->OBUF_0U = yStride * h;
+ backBuffer->OBUF_0V = backBuffer->OBUF_0U + (uvStride * (h / 2));
+ backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
+ break;
+ case HAL_PIXEL_FORMAT_NV12: // NV12
+ backBuffer->OBUF_0Y = 0;
+ backBuffer->OBUF_0U = yStride * h;
+ backBuffer->OBUF_0V = 0;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
+ break;
+ // NOTE: this is the decoded video format, align the height to 32B
+ //as it's defined by video driver
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: // Intel codec NV12
+ backBuffer->OBUF_0Y = 0;
+ backBuffer->OBUF_0U = yStride * align_to(h, 32);
+ backBuffer->OBUF_0V = 0;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
+ break;
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: //NV12_tiled
+ backBuffer->OBUF_0Y = 0;
+ backBuffer->OBUF_0U = yStride * align_to(h, 32);
+ backBuffer->OBUF_0V = 0;
+ backBuffer->OSTART_0U += yStride * align_to(h, 32);
+ backBuffer->OSTART_0V += yStride * align_to(h, 32);
+ backBuffer->OSTART_1U = backBuffer->OSTART_0U;
+ backBuffer->OSTART_1V = backBuffer->OSTART_0V;
+ backBuffer->OTILEOFF_0Y = srcX + (srcY << 16);
+ backBuffer->OTILEOFF_1Y = backBuffer->OTILEOFF_0Y;
+ backBuffer->OTILEOFF_0U = srcX + ((srcY / 2) << 16);
+ backBuffer->OTILEOFF_1U = backBuffer->OTILEOFF_0U;
+ backBuffer->OTILEOFF_0V = backBuffer->OTILEOFF_0U;
+ backBuffer->OTILEOFF_1V = backBuffer->OTILEOFF_0U;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
+ backBuffer->OCMD |= OVERLAY_MEMORY_LAYOUT_TILED;
+ break;
+ case HAL_PIXEL_FORMAT_YUY2: // YUY2
+ backBuffer->OBUF_0Y = 0;
+ backBuffer->OBUF_0U = 0;
+ backBuffer->OBUF_0V = 0;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
+ backBuffer->OCMD |= OVERLAY_PACKED_ORDER_YUY2;
+ break;
+ case HAL_PIXEL_FORMAT_UYVY: // UYVY
+ backBuffer->OBUF_0Y = 0;
+ backBuffer->OBUF_0U = 0;
+ backBuffer->OBUF_0V = 0;
+ backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
+ backBuffer->OCMD |= OVERLAY_PACKED_ORDER_UYVY;
+ break;
+ default:
+ ELOGTRACE("unsupported format %d", format);
+ return false;
+ }
+
+ backBuffer->OBUF_0Y += srcY * yStride + srcX;
+ backBuffer->OBUF_0V += (srcY / 2) * uvStride + srcX;
+ backBuffer->OBUF_0U += (srcY / 2) * uvStride + srcX;
+ backBuffer->OBUF_1Y = backBuffer->OBUF_0Y;
+ backBuffer->OBUF_1U = backBuffer->OBUF_0U;
+ backBuffer->OBUF_1V = backBuffer->OBUF_0V;
+
+ VLOGTRACE("done. offset (%d, %d, %d)",
+ backBuffer->OBUF_0Y,
+ backBuffer->OBUF_0U,
+ backBuffer->OBUF_0V);
+ return true;
+}
+
+uint32_t OverlayPlaneBase::calculateSWidthSW(uint32_t offset, uint32_t width)
+{
+ ALOGTRACE("offset = %d, width = %d", offset, width);
+
+ uint32_t swidth = ((offset + width + 0x3F) >> 6) - (offset >> 6);
+
+ swidth <<= 1;
+ swidth -= 1;
+
+ return swidth;
+}
+
+bool OverlayPlaneBase::coordinateSetup(BufferMapper& mapper)
+{
+ CTRACE();
+
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
+ if (!backBuffer) {
+ ELOGTRACE("invalid back buffer");
+ return false;
+ }
+
+ uint32_t swidthy = 0;
+ uint32_t swidthuv = 0;
+ uint32_t format = mapper.getFormat();
+ uint32_t width = mapper.getCrop().w;
+ uint32_t height = mapper.getCrop().h;
+ uint32_t yStride = mapper.getStride().yuv.yStride;
+ uint32_t uvStride = mapper.getStride().yuv.uvStride;
+ uint32_t offsety = backBuffer->OBUF_0Y;
+ uint32_t offsetu = backBuffer->OBUF_0U;
+
+ switch (format) {
+ case HAL_PIXEL_FORMAT_YV12: // YV12
+ case HAL_PIXEL_FORMAT_I420: // I420
+ case HAL_PIXEL_FORMAT_NV12: // NV12
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: // NV12
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: // NV12_tiled
+ break;
+ case HAL_PIXEL_FORMAT_YUY2: // YUY2
+ case HAL_PIXEL_FORMAT_UYVY: // UYVY
+ width <<= 1;
+ break;
+ default:
+ ELOGTRACE("unsupported format %d", format);
+ return false;
+ }
+
+ if (width <= 0 || height <= 0) {
+ ELOGTRACE("invalid src dim");
+ return false;
+ }
+
+ if (yStride <=0 && uvStride <= 0) {
+ ELOGTRACE("invalid source stride");
+ return false;
+ }
+
+ backBuffer->SWIDTH = width | ((width / 2) << 16);
+ swidthy = calculateSWidthSW(offsety, width);
+ swidthuv = calculateSWidthSW(offsetu, width / 2);
+ backBuffer->SWIDTHSW = (swidthy << 2) | (swidthuv << 18);
+ backBuffer->SHEIGHT = height | ((height / 2) << 16);
+ backBuffer->OSTRIDE = (yStride & (~0x3f)) | ((uvStride & (~0x3f)) << 16);
+
+ XLOGTRACE();
+
+ return true;
+}
+
+bool OverlayPlaneBase::setCoeffRegs(double *coeff, int mantSize,
+ coeffPtr pCoeff, int pos)
+{
+ int maxVal, icoeff, res;
+ int sign;
+ double c;
+
+ sign = 0;
+ maxVal = 1 << mantSize;
+ c = *coeff;
+ if (c < 0.0) {
+ sign = 1;
+ c = -c;
+ }
+
+ res = 12 - mantSize;
+ if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) {
+ pCoeff[pos].exponent = 3;
+ pCoeff[pos].mantissa = icoeff << res;
+ *coeff = (double)icoeff / (double)(4 * maxVal);
+ } else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) {
+ pCoeff[pos].exponent = 2;
+ pCoeff[pos].mantissa = icoeff << res;
+ *coeff = (double)icoeff / (double)(2 * maxVal);
+ } else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) {
+ pCoeff[pos].exponent = 1;
+ pCoeff[pos].mantissa = icoeff << res;
+ *coeff = (double)icoeff / (double)(maxVal);
+ } else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) {
+ pCoeff[pos].exponent = 0;
+ pCoeff[pos].mantissa = icoeff << res;
+ *coeff = (double)icoeff / (double)(maxVal / 2);
+ } else {
+ // Coeff out of range
+ return false;
+ }
+
+ pCoeff[pos].sign = sign;
+ if (sign)
+ *coeff = -(*coeff);
+ return true;
+}
+
+void OverlayPlaneBase::updateCoeff(int taps, double fCutoff,
+ bool isHoriz, bool isY,
+ coeffPtr pCoeff)
+{
+ int i, j, j1, num, pos, mantSize;
+ double pi = 3.1415926535, val, sinc, window, sum;
+ double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS];
+ double diff;
+ int tapAdjust[MAX_TAPS], tap2Fix;
+ bool isVertAndUV;
+
+ if (isHoriz)
+ mantSize = 7;
+ else
+ mantSize = 6;
+
+ isVertAndUV = !isHoriz && !isY;
+ num = taps * 16;
+ for (i = 0; i < num * 2; i++) {
+ val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num);
+ if (val == 0.0)
+ sinc = 1.0;
+ else
+ sinc = sin(val) / val;
+
+ // Hamming window
+ window = (0.54 - 0.46 * cos(2 * i * pi / (2 * num - 1)));
+ rawCoeff[i] = sinc * window;
+ }
+
+ for (i = 0; i < N_PHASES; i++) {
+ // Normalise the coefficients
+ sum = 0.0;
+ for (j = 0; j < taps; j++) {
+ pos = i + j * 32;
+ sum += rawCoeff[pos];
+ }
+ for (j = 0; j < taps; j++) {
+ pos = i + j * 32;
+ coeffs[i][j] = rawCoeff[pos] / sum;
+ }
+
+ // Set the register values
+ for (j = 0; j < taps; j++) {
+ pos = j + i * taps;
+ if ((j == (taps - 1) / 2) && !isVertAndUV)
+ setCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos);
+ else
+ setCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos);
+ }
+
+ tapAdjust[0] = (taps - 1) / 2;
+ for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) {
+ tapAdjust[j1] = tapAdjust[0] - j;
+ tapAdjust[++j1] = tapAdjust[0] + j;
+ }
+
+ // Adjust the coefficients
+ sum = 0.0;
+ for (j = 0; j < taps; j++)
+ sum += coeffs[i][j];
+ if (sum != 1.0) {
+ for (j1 = 0; j1 < taps; j1++) {
+ tap2Fix = tapAdjust[j1];
+ diff = 1.0 - sum;
+ coeffs[i][tap2Fix] += diff;
+ pos = tap2Fix + i * taps;
+ if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV)
+ setCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos);
+ else
+ setCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos);
+
+ sum = 0.0;
+ for (j = 0; j < taps; j++)
+ sum += coeffs[i][j];
+ if (sum == 1.0)
+ break;
+ }
+ }
+ }
+}
+
+bool OverlayPlaneBase::scalingSetup(BufferMapper& mapper)
+{
+ int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
+ int xscaleIntUV, xscaleFractUV;
+ int yscaleIntUV, yscaleFractUV;
+ int deinterlace_factor = 1;
+ // UV is half the size of Y -- YUV420
+ int uvratio = 2;
+ uint32_t newval;
+ coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
+ coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
+ int i, j, pos;
+ bool scaleChanged = false;
+ int x, y, w, h;
+
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
+ if (!backBuffer) {
+ ELOGTRACE("invalid back buffer");
+ return false;
+ }
+
+ x = mPosition.x;
+ y = mPosition.y;
+ w = mPosition.w;
+ h = mPosition.h;
+
+ // check position
+ checkPosition(x, y, w, h);
+ VLOGTRACE("final position (%d, %d, %d, %d)", x, y, w, h);
+
+ if ((w <= 0) || (h <= 0)) {
+ ELOGTRACE("invalid dst width/height");
+ return false;
+ }
+
+ // setup dst position
+ backBuffer->DWINPOS = (y << 16) | x;
+ backBuffer->DWINSZ = (h << 16) | w;
+
+ uint32_t srcWidth = mapper.getCrop().w;
+ uint32_t srcHeight = mapper.getCrop().h;
+ uint32_t dstWidth = w;
+ uint32_t dstHeight = h;
+
+ VLOGTRACE("src (%dx%d), dst (%dx%d)",
+ srcWidth, srcHeight,
+ dstWidth, dstHeight);
+
+ // Y down-scale factor as a multiple of 4096
+ if (srcWidth == dstWidth && srcHeight == dstHeight) {
+ xscaleFract = (1 << 12);
+ yscaleFract = (1 << 12)/deinterlace_factor;
+ } else {
+ xscaleFract = ((srcWidth - 1) << 12) / dstWidth;
+ yscaleFract = ((srcHeight - 1) << 12) / (dstHeight * deinterlace_factor);
+ }
+
+ // Calculate the UV scaling factor
+ xscaleFractUV = xscaleFract / uvratio;
+ yscaleFractUV = yscaleFract / uvratio;
+
+ // To keep the relative Y and UV ratios exact, round the Y scales
+ // to a multiple of the Y/UV ratio.
+ xscaleFract = xscaleFractUV * uvratio;
+ yscaleFract = yscaleFractUV * uvratio;
+
+ // Integer (un-multiplied) values
+ xscaleInt = xscaleFract >> 12;
+ yscaleInt = yscaleFract >> 12;
+
+ xscaleIntUV = xscaleFractUV >> 12;
+ yscaleIntUV = yscaleFractUV >> 12;
+
+ // Check scaling ratio
+ if (xscaleInt > INTEL_OVERLAY_MAX_SCALING_RATIO) {
+ ELOGTRACE("xscaleInt > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
+ return false;
+ }
+
+ // shouldn't get here
+ if (xscaleIntUV > INTEL_OVERLAY_MAX_SCALING_RATIO) {
+ ELOGTRACE("xscaleIntUV > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
+ return false;
+ }
+
+ newval = (xscaleInt << 15) |
+ ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
+ if (newval != backBuffer->YRGBSCALE) {
+ scaleChanged = true;
+ backBuffer->YRGBSCALE = newval;
+ }
+
+ newval = (xscaleIntUV << 15) | ((xscaleFractUV & 0xFFF) << 3) |
+ ((yscaleFractUV & 0xFFF) << 20);
+ if (newval != backBuffer->UVSCALE) {
+ scaleChanged = true;
+ backBuffer->UVSCALE = newval;
+ }
+
+ newval = yscaleInt << 16 | yscaleIntUV;
+ if (newval != backBuffer->UVSCALEV) {
+ scaleChanged = true;
+ backBuffer->UVSCALEV = newval;
+ }
+
+ // Recalculate coefficients if the scaling changed
+ // Only Horizontal coefficients so far.
+ if (scaleChanged) {
+ double fCutoffY;
+ double fCutoffUV;
+
+ fCutoffY = xscaleFract / 4096.0;
+ fCutoffUV = xscaleFractUV / 4096.0;
+
+ // Limit to between 1.0 and 3.0
+ if (fCutoffY < MIN_CUTOFF_FREQ)
+ fCutoffY = MIN_CUTOFF_FREQ;
+ if (fCutoffY > MAX_CUTOFF_FREQ)
+ fCutoffY = MAX_CUTOFF_FREQ;
+ if (fCutoffUV < MIN_CUTOFF_FREQ)
+ fCutoffUV = MIN_CUTOFF_FREQ;
+ if (fCutoffUV > MAX_CUTOFF_FREQ)
+ fCutoffUV = MAX_CUTOFF_FREQ;
+
+ updateCoeff(N_HORIZ_Y_TAPS, fCutoffY, true, true, xcoeffY);
+ updateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, true, false, xcoeffUV);
+
+ for (i = 0; i < N_PHASES; i++) {
+ for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
+ pos = i * N_HORIZ_Y_TAPS + j;
+ backBuffer->Y_HCOEFS[pos] =
+ (xcoeffY[pos].sign << 15 |
+ xcoeffY[pos].exponent << 12 |
+ xcoeffY[pos].mantissa);
+ }
+ }
+ for (i = 0; i < N_PHASES; i++) {
+ for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
+ pos = i * N_HORIZ_UV_TAPS + j;
+ backBuffer->UV_HCOEFS[pos] =
+ (xcoeffUV[pos].sign << 15 |
+ xcoeffUV[pos].exponent << 12 |
+ xcoeffUV[pos].mantissa);
+ }
+ }
+ }
+
+ XLOGTRACE();
+ return true;
+}
+
+bool OverlayPlaneBase::setDataBuffer(BufferMapper& grallocMapper)
+{
+ BufferMapper *mapper;
+ BufferMapper *rotatedMapper = 0;
+ bool ret;
+ uint32_t format;
+
+ RETURN_FALSE_IF_NOT_INIT();
+
+ // get gralloc mapper
+ mapper = &grallocMapper;
+ format = grallocMapper.getFormat();
+ if (format == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar ||
+ format == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
+ struct VideoPayloadBuffer *payload;
+ payload = (struct VideoPayloadBuffer *)grallocMapper.getCpuAddress(SUB_BUFFER1);
+ if (!payload) {
+ ELOGTRACE("invalid payload buffer");
+ return 0;
+ }
+
+ mBobDeinterlace = payload->bob_deinterlace;
+ }
+
+ if (mTransform && !useOverlayRotation(grallocMapper)) {
+ if (!rotatedBufferReady(grallocMapper, rotatedMapper)) {
+ DLOGTRACE("rotated buffer is not ready");
+ return false;
+ }
+
+ if (!rotatedMapper) {
+ ELOGTRACE("failed to get rotated buffer");
+ return false;
+ }
+ mapper = rotatedMapper;
+ }
+
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
+ if (!backBuffer) {
+ ELOGTRACE("invalid back buffer");
+ return false;
+ }
+
+ ret = bufferOffsetSetup(*mapper);
+ if (ret == false) {
+ ELOGTRACE("failed to set up buffer offsets");
+ return false;
+ }
+
+ ret = coordinateSetup(*mapper);
+ if (ret == false) {
+ ELOGTRACE("failed to set up overlay coordinates");
+ return false;
+ }
+
+ ret = scalingSetup(*mapper);
+ if (ret == false) {
+ ELOGTRACE("failed to set up scaling parameters");
+ return false;
+ }
+
+ backBuffer->OCMD |= 0x1;
+
+ if (mBobDeinterlace && !mTransform) {
+ backBuffer->OCMD |= BUF_TYPE_FIELD;
+ backBuffer->OCMD &= ~FIELD_SELECT;
+ backBuffer->OCMD |= FIELD0;
+ backBuffer->OCMD &= ~(BUFFER_SELECT);
+ backBuffer->OCMD |= BUFFER0;
+ }
+
+ // add to active ttm buffers if it's a rotated buffer
+ if (rotatedMapper) {
+ updateActiveTTMBuffers(mapper);
+ }
+
+ return true;
+}
+
+} // namespace intel
+} // namespace android
+
diff --git a/moorefield_hdmi/ips/common/OverlayPlaneBase.h b/moorefield_hdmi/ips/common/OverlayPlaneBase.h
new file mode 100644
index 0000000..8f2572c
--- /dev/null
+++ b/moorefield_hdmi/ips/common/OverlayPlaneBase.h
@@ -0,0 +1,125 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef OVERLAY_PLANE_BASE_H
+#define OVERLAY_PLANE_BASE_H
+
+#include <utils/KeyedVector.h>
+#include <DisplayPlane.h>
+#include <BufferMapper.h>
+#include <ips/common/Wsbm.h>
+#include <ips/common/OverlayHardware.h>
+#include <ips/common/VideoPayloadBuffer.h>
+
+namespace android {
+namespace intel {
+
+typedef struct {
+ OverlayBackBufferBlk *buf;
+ uint32_t gttOffsetInPage;
+ uint32_t bufObject;
+} OverlayBackBuffer;
+
+class OverlayPlaneBase : public DisplayPlane {
+public:
+ OverlayPlaneBase(int index, int disp);
+ virtual ~OverlayPlaneBase();
+
+ virtual void invalidateBufferCache();
+
+ virtual bool assignToDevice(int disp);
+
+ virtual void setZOrderConfig(ZOrderConfig& config, void *nativeConfig);
+
+ // plane operations
+ virtual bool flip(void *ctx) = 0;
+ virtual bool reset();
+ virtual bool enable();
+ virtual bool disable();
+ virtual bool isDisabled();
+
+ virtual void* getContext() const = 0;
+ virtual bool initialize(uint32_t bufferCount);
+ virtual void deinitialize();
+
+protected:
+ // generic overlay register flush
+ virtual bool flush(uint32_t flags) = 0;
+ virtual bool setDataBuffer(BufferMapper& mapper);
+ virtual bool bufferOffsetSetup(BufferMapper& mapper);
+ virtual uint32_t calculateSWidthSW(uint32_t offset, uint32_t width);
+ virtual bool coordinateSetup(BufferMapper& mapper);
+ virtual bool setCoeffRegs(double *coeff, int mantSize,
+ coeffPtr pCoeff, int pos);
+ virtual void updateCoeff(int taps, double fCutoff,
+ bool isHoriz, bool isY,
+ coeffPtr pCoeff);
+ virtual bool scalingSetup(BufferMapper& mapper);
+ virtual void checkPosition(int& x, int& y, int& w, int& h);
+ virtual void checkCrop(int& x, int& y, int& w, int& h, int coded_width, int coded_height);
+
+
+protected:
+ // back buffer operations
+ virtual OverlayBackBuffer* createBackBuffer();
+ virtual void deleteBackBuffer(int buf);
+ virtual void resetBackBuffer(int buf);
+
+ virtual BufferMapper* getTTMMapper(BufferMapper& grallocMapper, struct VideoPayloadBuffer *payload);
+ virtual void putTTMMapper(BufferMapper* mapper);
+ virtual bool rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper);
+ virtual bool useOverlayRotation(BufferMapper& mapper);
+
+private:
+ inline bool isActiveTTMBuffer(BufferMapper *mapper);
+ void updateActiveTTMBuffers(BufferMapper *mapper);
+ void invalidateActiveTTMBuffers();
+ void invalidateTTMBuffers();
+
+protected:
+ // flush flags
+ enum {
+ PLANE_ENABLE = 0x00000001UL,
+ PLANE_DISABLE = 0x00000002UL,
+ UPDATE_COEF = 0x00000004UL,
+ };
+
+ enum {
+ OVERLAY_BACK_BUFFER_COUNT = 3,
+ MAX_ACTIVE_TTM_BUFFERS = 3,
+ OVERLAY_DATA_BUFFER_COUNT = 20,
+ };
+
+ // TTM data buffers
+ KeyedVector<uint64_t, BufferMapper*> mTTMBuffers;
+ // latest TTM buffers
+ Vector<BufferMapper*> mActiveTTMBuffers;
+
+ // overlay back buffer
+ OverlayBackBuffer *mBackBuffer[OVERLAY_BACK_BUFFER_COUNT];
+ int mCurrent;
+ // wsbm
+ Wsbm *mWsbm;
+ // pipe config
+ uint32_t mPipeConfig;
+
+ int mBobDeinterlace;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* OVERLAY_PLANE_BASE_H */
+
diff --git a/moorefield_hdmi/ips/common/PixelFormat.cpp b/moorefield_hdmi/ips/common/PixelFormat.cpp
new file mode 100644
index 0000000..67774dc
--- /dev/null
+++ b/moorefield_hdmi/ips/common/PixelFormat.cpp
@@ -0,0 +1,56 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <system/graphics.h>
+#include <common/utils/HwcTrace.h>
+#include <ips/common/PixelFormat.h>
+#include <hal_public.h>
+
+namespace android {
+namespace intel {
+
+bool PixelFormat::convertFormat(uint32_t grallocFormat, uint32_t& spriteFormat, int& bpp)
+{
+ switch (grallocFormat) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ spriteFormat = PLANE_PIXEL_FORMAT_RGBA8888;
+ bpp = 4;
+ break;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ spriteFormat = PLANE_PIXEL_FORMAT_RGBX8888;
+ bpp = 4;
+ break;
+ case HAL_PIXEL_FORMAT_BGRX_8888:
+ spriteFormat = PLANE_PIXEL_FORMAT_BGRX8888;
+ bpp = 4;
+ break;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ spriteFormat = PLANE_PIXEL_FORMAT_BGRA8888;
+ bpp = 4;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ spriteFormat = PLANE_PIXEL_FORMAT_BGRX565;
+ bpp = 2;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/common/PixelFormat.h b/moorefield_hdmi/ips/common/PixelFormat.h
new file mode 100644
index 0000000..cea69e0
--- /dev/null
+++ b/moorefield_hdmi/ips/common/PixelFormat.h
@@ -0,0 +1,41 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef PIXEL_FORMAT_H
+#define PIXEL_FORMAT_H
+
+namespace android {
+namespace intel {
+
+class PixelFormat
+{
+public:
+ enum {
+ PLANE_PIXEL_FORMAT_BGRX565 = 0x14000000UL,
+ PLANE_PIXEL_FORMAT_BGRX8888 = 0x18000000UL,
+ PLANE_PIXEL_FORMAT_BGRA8888 = 0x1c000000UL,
+ PLANE_PIXEL_FORMAT_RGBX8888 = 0x38000000UL,
+ PLANE_PIXEL_FORMAT_RGBA8888 = 0x3c000000UL,
+ };
+
+ // convert gralloc color format to IP specific sprite pixel format.
+ // See DSPACNTR (Display A Primary Sprite Control Register for more information)
+ static bool convertFormat(uint32_t grallocFormat, uint32_t& spriteFormat, int& bpp);
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /*PIXEL_FORMAT_H*/
diff --git a/moorefield_hdmi/ips/common/RotationBufferProvider.cpp b/moorefield_hdmi/ips/common/RotationBufferProvider.cpp
new file mode 100644
index 0000000..22fdf60
--- /dev/null
+++ b/moorefield_hdmi/ips/common/RotationBufferProvider.cpp
@@ -0,0 +1,624 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <common/utils/HwcTrace.h>
+#include <ips/common/RotationBufferProvider.h>
+
+namespace android {
+namespace intel {
+
+#define CHECK_VA_STATUS_RETURN(FUNC) \
+if (vaStatus != VA_STATUS_SUCCESS) {\
+ ELOGTRACE(FUNC" failed. vaStatus = %#x", vaStatus);\
+ return false;\
+}
+
+#define CHECK_VA_STATUS_BREAK(FUNC) \
+if (vaStatus != VA_STATUS_SUCCESS) {\
+ ELOGTRACE(FUNC" failed. vaStatus = %#x", vaStatus);\
+ break;\
+}
+
+// With this display value, VA will hook VED driver insead of VSP driver for buffer rotation
+#define DISPLAYVALUE 0x56454450
+
+RotationBufferProvider::RotationBufferProvider(Wsbm* wsbm)
+ : mWsbm(wsbm),
+ mVaInitialized(false),
+ mVaDpy(0),
+ mVaCfg(0),
+ mVaCtx(0),
+ mVaBufFilter(0),
+ mSourceSurface(0),
+ mDisplay(DISPLAYVALUE),
+ mWidth(0),
+ mHeight(0),
+ mTransform(0),
+ mRotatedWidth(0),
+ mRotatedHeight(0),
+ mRotatedStride(0),
+ mTargetIndex(0),
+ mTTMWrappers(),
+ mBobDeinterlace(0)
+{
+ for (int i = 0; i < MAX_SURFACE_NUM; i++) {
+ mKhandles[i] = 0;
+ mRotatedSurfaces[i] = 0;
+ mDrmBuf[i] = NULL;
+ }
+}
+
+RotationBufferProvider::~RotationBufferProvider()
+{
+}
+
+uint32_t RotationBufferProvider::getMilliseconds()
+{
+ struct timeval ptimeval;
+ gettimeofday(&ptimeval, NULL);
+ return (uint32_t)((ptimeval.tv_sec * 1000) + (ptimeval.tv_usec / 1000));
+}
+
+bool RotationBufferProvider::initialize()
+{
+ if (NULL == mWsbm)
+ return false;
+ mTTMWrappers.setCapacity(TTM_WRAPPER_COUNT);
+ return true;
+}
+
+void RotationBufferProvider::deinitialize()
+{
+ stopVA();
+ reset();
+}
+
+void RotationBufferProvider::reset()
+{
+ if (mTTMWrappers.size()) {
+ invalidateCaches();
+ }
+}
+
+void RotationBufferProvider::invalidateCaches()
+{
+ void *buf;
+
+ for (size_t i = 0; i < mTTMWrappers.size(); i++) {
+ buf = mTTMWrappers.valueAt(i);
+ if (!mWsbm->destroyTTMBuffer(buf))
+ WLOGTRACE("failed to free TTMBuffer");
+ }
+ mTTMWrappers.clear();
+}
+
+int RotationBufferProvider::transFromHalToVa(int transform)
+{
+ if (transform == HAL_TRANSFORM_ROT_90)
+ return VA_ROTATION_90;
+ if (transform == HAL_TRANSFORM_ROT_180)
+ return VA_ROTATION_180;
+ if (transform == HAL_TRANSFORM_ROT_270)
+ return VA_ROTATION_270;
+ return 0;
+}
+
+int RotationBufferProvider::getStride(bool isTarget, int width)
+{
+ int stride = 0;
+ if (width <= 512)
+ stride = 512;
+ else if (width <= 1024)
+ stride = 1024;
+ else if (width <= 1280) {
+ stride = 1280;
+ if (isTarget)
+ stride = 2048;
+ } else if (width <= 2048)
+ stride = 2048;
+ else if (width <= 4096)
+ stride = 4096;
+ else
+ stride = (width + 0x3f) & ~0x3f;
+ return stride;
+}
+
+uint32_t RotationBufferProvider::createWsbmBuffer(int width, int height, void **buf)
+{
+ int size = width * height * 3 / 2; // YUV420 NV12 format
+ int allignment = 16 * 2048; // tiling row stride aligned
+ bool ret = mWsbm->allocateTTMBuffer(size, allignment, buf);
+
+ if (ret == false) {
+ ELOGTRACE("failed to allocate TTM buffer");
+ return 0;
+ }
+
+ return mWsbm->getKBufHandle(*buf);
+}
+
+bool RotationBufferProvider::createVaSurface(VideoPayloadBuffer *payload, int transform, bool isTarget)
+{
+ VAStatus vaStatus;
+ VASurfaceAttributeTPI attribTpi;
+ VASurfaceAttributeTPI *vaSurfaceAttrib = &attribTpi;
+ int stride;
+ unsigned long buffers;
+ VASurfaceID *surface;
+ int width = 0, height = 0, bufferHeight = 0;
+
+ if (isTarget) {
+ if (transFromHalToVa(transform) == VA_ROTATION_180) {
+ width = payload->width;
+ height = payload->height;
+ } else {
+ width = payload->height;
+ height = payload->width;
+ }
+ mRotatedWidth = width;
+ mRotatedHeight = height;
+ bufferHeight = (height + 0x1f) & ~0x1f;
+ stride = getStride(isTarget, width);
+ } else {
+ width = payload->width;
+ height = payload->height;
+ bufferHeight = payload->height;
+ stride = payload->luma_stride; /* NV12 srouce buffer */
+ }
+
+ if (!stride) {
+ ELOGTRACE("invalid stride value");
+ return false;
+ }
+
+ // adjust source target for Bob deinterlace
+ if (!isTarget && mBobDeinterlace) {
+ height >>= 1;
+ bufferHeight >>= 1;
+ stride <<= 1;
+ }
+
+ vaSurfaceAttrib->count = 1;
+ vaSurfaceAttrib->width = width;
+ vaSurfaceAttrib->height = height;
+ vaSurfaceAttrib->pixel_format = payload->format;
+ vaSurfaceAttrib->type = VAExternalMemoryKernelDRMBufffer;
+ vaSurfaceAttrib->tiling = payload->tiling;
+ vaSurfaceAttrib->size = (stride * bufferHeight * 3) / 2;
+ vaSurfaceAttrib->luma_offset = 0;
+ vaSurfaceAttrib->chroma_v_offset = stride * bufferHeight;
+ vaSurfaceAttrib->luma_stride = vaSurfaceAttrib->chroma_u_stride
+ = vaSurfaceAttrib->chroma_v_stride
+ = stride;
+ vaSurfaceAttrib->chroma_u_offset = vaSurfaceAttrib->chroma_v_offset;
+ vaSurfaceAttrib->buffers = &buffers;
+
+ if (isTarget) {
+ int khandle = createWsbmBuffer(stride, bufferHeight, &mDrmBuf[mTargetIndex]);
+ if (khandle == 0) {
+ ELOGTRACE("failed to create buffer by wsbm");
+ return false;
+ }
+
+ mKhandles[mTargetIndex] = khandle;
+ vaSurfaceAttrib->buffers[0] = khandle;
+ mRotatedStride = stride;
+ surface = &mRotatedSurfaces[mTargetIndex];
+ } else {
+ vaSurfaceAttrib->buffers[0] = payload->khandle;
+ surface = &mSourceSurface;
+ /* set src surface width/height to video crop size */
+ if (payload->crop_width && payload->crop_height) {
+ width = payload->crop_width;
+ height = (payload->crop_height >> mBobDeinterlace);
+ } else {
+ VLOGTRACE("Invalid cropping width or height");
+ payload->crop_width = width;
+ payload->crop_height = height;
+ }
+ }
+
+ vaStatus = vaCreateSurfacesWithAttribute(mVaDpy,
+ width,
+ height,
+ VA_RT_FORMAT_YUV420,
+ 1,
+ surface,
+ vaSurfaceAttrib);
+ if (vaStatus != VA_STATUS_SUCCESS) {
+ ELOGTRACE("vaCreateSurfacesWithAttribute returns %d", vaStatus);
+ ELOGTRACE("Attributes: target: %d, width: %d, height %d, bufferHeight %d, tiling %d",
+ isTarget, width, height, bufferHeight, payload->tiling);
+ *surface = 0;
+ return false;
+ }
+
+ return true;
+}
+
+bool RotationBufferProvider::startVA(VideoPayloadBuffer *payload, int transform)
+{
+ bool ret = true;
+ VAStatus vaStatus;
+ VAEntrypoint *entryPoint;
+ VAConfigAttrib attribDummy;
+ int numEntryPoints;
+ bool supportVideoProcessing = false;
+ int majorVer = 0, minorVer = 0;
+
+ // VA will hold a copy of the param pointer, so local varialbe doesn't work
+ mVaDpy = vaGetDisplay(&mDisplay);
+ if (NULL == mVaDpy) {
+ ELOGTRACE("failed to get VADisplay");
+ return false;
+ }
+
+ vaStatus = vaInitialize(mVaDpy, &majorVer, &minorVer);
+ CHECK_VA_STATUS_RETURN("vaInitialize");
+
+ numEntryPoints = vaMaxNumEntrypoints(mVaDpy);
+
+ if (numEntryPoints <= 0) {
+ ELOGTRACE("numEntryPoints value is invalid");
+ return false;
+ }
+
+ entryPoint = (VAEntrypoint*)malloc(sizeof(VAEntrypoint) * numEntryPoints);
+ if (NULL == entryPoint) {
+ ELOGTRACE("failed to malloc memory for entryPoint");
+ return false;
+ }
+
+ vaStatus = vaQueryConfigEntrypoints(mVaDpy,
+ VAProfileNone,
+ entryPoint,
+ &numEntryPoints);
+ CHECK_VA_STATUS_RETURN("vaQueryConfigEntrypoints");
+
+ for (int i = 0; i < numEntryPoints; i++)
+ if (entryPoint[i] == VAEntrypointVideoProc)
+ supportVideoProcessing = true;
+
+ free(entryPoint);
+ entryPoint = NULL;
+
+ if (!supportVideoProcessing) {
+ ELOGTRACE("VAEntrypointVideoProc is not supported");
+ return false;
+ }
+
+ vaStatus = vaCreateConfig(mVaDpy,
+ VAProfileNone,
+ VAEntrypointVideoProc,
+ &attribDummy,
+ 0,
+ &mVaCfg);
+ CHECK_VA_STATUS_RETURN("vaCreateConfig");
+
+ // create first target surface
+ ret = createVaSurface(payload, transform, true);
+ if (ret == false) {
+ ELOGTRACE("failed to create target surface with attribute");
+ return false;
+ }
+
+ vaStatus = vaCreateContext(mVaDpy,
+ mVaCfg,
+ payload->width,
+ payload->height,
+ 0,
+ &mRotatedSurfaces[0],
+ 1,
+ &mVaCtx);
+ CHECK_VA_STATUS_RETURN("vaCreateContext");
+
+ VAProcFilterType filters[VAProcFilterCount];
+ unsigned int numFilters = VAProcFilterCount;
+ vaStatus = vaQueryVideoProcFilters(mVaDpy, mVaCtx, filters, &numFilters);
+ CHECK_VA_STATUS_RETURN("vaQueryVideoProcFilters");
+
+ bool supportVideoProcFilter = false;
+ for (unsigned int j = 0; j < numFilters; j++)
+ if (filters[j] == VAProcFilterNone)
+ supportVideoProcFilter = true;
+
+ if (!supportVideoProcFilter) {
+ ELOGTRACE("VAProcFilterNone is not supported");
+ return false;
+ }
+
+ VAProcFilterParameterBuffer filter;
+ filter.type = VAProcFilterNone;
+ filter.value = 0;
+
+ vaStatus = vaCreateBuffer(mVaDpy,
+ mVaCtx,
+ VAProcFilterParameterBufferType,
+ sizeof(filter),
+ 1,
+ &filter,
+ &mVaBufFilter);
+ CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+ VAProcPipelineCaps pipelineCaps;
+ unsigned int numCaps = 1;
+ vaStatus = vaQueryVideoProcPipelineCaps(mVaDpy,
+ mVaCtx,
+ &mVaBufFilter,
+ numCaps,
+ &pipelineCaps);
+ CHECK_VA_STATUS_RETURN("vaQueryVideoProcPipelineCaps");
+
+ if (!(pipelineCaps.rotation_flags & (1 << transFromHalToVa(transform)))) {
+ ELOGTRACE("VA_ROTATION_xxx: 0x%08x is not supported by the filter",
+ transFromHalToVa(transform));
+ return false;
+ }
+
+ mBobDeinterlace = payload->bob_deinterlace;
+ mVaInitialized = true;
+
+ return true;
+}
+
+bool RotationBufferProvider::setupRotationBuffer(VideoPayloadBuffer *payload, int transform)
+{
+#ifdef DEBUG_ROTATION_PERFROMANCE
+ uint32_t setup_Begin = getMilliseconds();
+#endif
+ VAStatus vaStatus;
+ int stride;
+ bool ret = false;
+
+ if (payload->format != VA_FOURCC_NV12 || payload->width == 0 || payload->height == 0) {
+ WLOGTRACE("payload data is not correct: format %#x, width %d, height %d",
+ payload->format, payload->width, payload->height);
+ return ret;
+ }
+
+ if (payload->width > 1280) {
+ payload->tiling = 1;
+ }
+
+ do {
+ if (isContextChanged(payload->width, payload->height, transform)) {
+ DLOGTRACE("VA is restarted as rotation context changes");
+
+ if (mVaInitialized) {
+ stopVA(); // need to re-initialize VA for new rotation config
+ }
+ mTransform = transform;
+ mWidth = payload->width;
+ mHeight = payload->height;
+ }
+
+ if (!mVaInitialized) {
+ ret = startVA(payload, transform);
+ if (ret == false) {
+ vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
+ break;
+ }
+ }
+
+ // start to create next target surface
+ if (!mRotatedSurfaces[mTargetIndex]) {
+ ret = createVaSurface(payload, transform, true);
+ if (ret == false) {
+ ELOGTRACE("failed to create target surface with attribute");
+ vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
+ break;
+ }
+ }
+
+ // create source surface
+ ret = createVaSurface(payload, transform, false);
+ if (ret == false) {
+ ELOGTRACE("failed to create source surface with attribute");
+ vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
+ break;
+ }
+
+#ifdef DEBUG_ROTATION_PERFROMANCE
+ uint32_t beginPicture = getMilliseconds();
+#endif
+ vaStatus = vaBeginPicture(mVaDpy, mVaCtx, mRotatedSurfaces[mTargetIndex]);
+ CHECK_VA_STATUS_BREAK("vaBeginPicture");
+
+ VABufferID pipelineBuf;
+ void *p;
+ VAProcPipelineParameterBuffer *pipelineParam;
+ vaStatus = vaCreateBuffer(mVaDpy,
+ mVaCtx,
+ VAProcPipelineParameterBufferType,
+ sizeof(*pipelineParam),
+ 1,
+ NULL,
+ &pipelineBuf);
+ CHECK_VA_STATUS_BREAK("vaCreateBuffer");
+
+ vaStatus = vaMapBuffer(mVaDpy, pipelineBuf, &p);
+ CHECK_VA_STATUS_BREAK("vaMapBuffer");
+
+ pipelineParam = (VAProcPipelineParameterBuffer*)p;
+ pipelineParam->surface = mSourceSurface;
+ pipelineParam->rotation_state = transFromHalToVa(transform);
+ pipelineParam->filters = &mVaBufFilter;
+ pipelineParam->num_filters = 1;
+ vaStatus = vaUnmapBuffer(mVaDpy, pipelineBuf);
+ CHECK_VA_STATUS_BREAK("vaUnmapBuffer");
+
+ vaStatus = vaRenderPicture(mVaDpy, mVaCtx, &pipelineBuf, 1);
+ CHECK_VA_STATUS_BREAK("vaRenderPicture");
+
+ vaStatus = vaEndPicture(mVaDpy, mVaCtx);
+ CHECK_VA_STATUS_BREAK("vaEndPicture");
+
+ vaStatus = vaSyncSurface(mVaDpy, mRotatedSurfaces[mTargetIndex]);
+ CHECK_VA_STATUS_BREAK("vaSyncSurface");
+
+#ifdef DEBUG_ROTATION_PERFROMANCE
+ ILOGTRACE("time spent %dms from vaBeginPicture to vaSyncSurface",
+ getMilliseconds() - beginPicture);
+#endif
+
+ // Populate payload fields so that overlayPlane can flip the buffer
+ payload->rotated_width = mRotatedStride;
+ payload->rotated_height = mRotatedHeight;
+ payload->rotated_buffer_handle = mKhandles[mTargetIndex];
+ // setting client transform to 0 to force re-generating rotated buffer whenever needed.
+ payload->client_transform = 0;
+ mTargetIndex++;
+ if (mTargetIndex >= MAX_SURFACE_NUM)
+ mTargetIndex = 0;
+
+ } while (0);
+
+#ifdef DEBUG_ROTATION_PERFROMANCE
+ ILOGTRACE("time spent %dms for setupRotationBuffer",
+ getMilliseconds() - setup_Begin);
+#endif
+
+ if (mSourceSurface > 0) {
+ vaStatus = vaDestroySurfaces(mVaDpy, &mSourceSurface, 1);
+ if (vaStatus != VA_STATUS_SUCCESS)
+ WLOGTRACE("vaDestroySurfaces failed, vaStatus = %d", vaStatus);
+ mSourceSurface = 0;
+ }
+
+ if (vaStatus != VA_STATUS_SUCCESS) {
+ stopVA();
+ return false; // To not block HWC, just abort instead of retry
+ }
+
+ if (!payload->khandle) {
+ WLOGTRACE("khandle is reset by decoder, surface is invalid!");
+ return false;
+ }
+
+ return true;
+}
+
+bool RotationBufferProvider::prepareBufferInfo(int w, int h, int stride, VideoPayloadBuffer *payload, void *user_pt)
+{
+ int chroma_offset, size;
+ void *buf = NULL;
+
+ payload->width = payload->crop_width = w;
+ payload->height = payload->crop_height = h;
+ payload->format = VA_FOURCC_NV12;
+ payload->tiling = 1;
+ payload->luma_stride = stride;
+ payload->chroma_u_stride = stride;
+ payload->chroma_v_stride = stride;
+ payload->client_transform = 0;
+
+ chroma_offset = stride * h;
+ size = stride * h + stride * h / 2;
+
+ ssize_t index;
+ index = mTTMWrappers.indexOfKey((uint64_t)user_pt);
+ if (index < 0) {
+ VLOGTRACE("wrapped userPt as wsbm buffer");
+ bool ret = mWsbm->allocateTTMBufferUB(size, 0, &buf, user_pt);
+ if (ret == false) {
+ ELOGTRACE("failed to allocate TTM buffer");
+ return ret;
+ }
+
+ if (mTTMWrappers.size() >= TTM_WRAPPER_COUNT) {
+ WLOGTRACE("mTTMWrappers is unexpectedly full. Invalidate caches");
+ invalidateCaches();
+ }
+
+ index = mTTMWrappers.add((uint64_t)user_pt, buf);
+ } else {
+ VLOGTRACE("got wsbmBuffer in saved caches");
+ buf = mTTMWrappers.valueAt(index);
+ }
+
+ payload->khandle = mWsbm->getKBufHandle(buf);
+ return true;
+}
+
+void RotationBufferProvider::freeVaSurfaces()
+{
+ bool ret;
+ VAStatus vaStatus;
+
+ for (int i = 0; i < MAX_SURFACE_NUM; i++) {
+ if (NULL != mDrmBuf[i]) {
+ ret = mWsbm->destroyTTMBuffer(mDrmBuf[i]);
+ if (!ret)
+ WLOGTRACE("failed to free TTMBuffer");
+ mDrmBuf[i] = NULL;
+ }
+ }
+
+ // remove wsbm buffer ref from VA
+ for (int j = 0; j < MAX_SURFACE_NUM; j++) {
+ if (0 != mRotatedSurfaces[j]) {
+ vaStatus = vaDestroySurfaces(mVaDpy, &mRotatedSurfaces[j], 1);
+ if (vaStatus != VA_STATUS_SUCCESS)
+ WLOGTRACE("vaDestroySurfaces failed, vaStatus = %d", vaStatus);
+ }
+ mRotatedSurfaces[j] = 0;
+ }
+}
+
+void RotationBufferProvider::stopVA()
+{
+ freeVaSurfaces();
+
+ if (0 != mVaBufFilter)
+ vaDestroyBuffer(mVaDpy, mVaBufFilter);
+ if (0 != mVaCfg)
+ vaDestroyConfig(mVaDpy,mVaCfg);
+ if (0 != mVaCtx)
+ vaDestroyContext(mVaDpy, mVaCtx);
+ if (0 != mVaDpy)
+ vaTerminate(mVaDpy);
+
+ mVaInitialized = false;
+
+ // reset VA variable
+ mVaDpy = 0;
+ mVaCfg = 0;
+ mVaCtx = 0;
+ mVaBufFilter = 0;
+ mSourceSurface = 0;
+
+ mWidth = 0;
+ mHeight = 0;
+ mRotatedWidth = 0;
+ mRotatedHeight = 0;
+ mRotatedStride = 0;
+ mTargetIndex = 0;
+}
+
+bool RotationBufferProvider::isContextChanged(int width, int height, int transform)
+{
+ // check rotation config
+ if (height == mHeight &&
+ width == mWidth &&
+ transform == mTransform) {
+ return false;
+ }
+
+ return true;
+}
+
+} // name space intel
+} // name space android
diff --git a/moorefield_hdmi/ips/common/RotationBufferProvider.h b/moorefield_hdmi/ips/common/RotationBufferProvider.h
new file mode 100644
index 0000000..985af27
--- /dev/null
+++ b/moorefield_hdmi/ips/common/RotationBufferProvider.h
@@ -0,0 +1,101 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#ifndef __ROTATIONO_BUFFER_PROVIDER_H__
+#define __ROTATIONO_BUFFER_PROVIDER_H__
+
+#include <va/va.h>
+#include <sys/time.h>
+#include <va/va_tpi.h>
+#include <va/va_vpp.h>
+#include <ips/common/Wsbm.h>
+#include <utils/Timers.h>
+#include <va/va_android.h>
+#include <ips/common/VideoPayloadBuffer.h>
+
+namespace android {
+namespace intel {
+
+#define Display unsigned int
+typedef void* VADisplay;
+typedef int VAStatus;
+
+class RotationBufferProvider {
+
+public:
+ RotationBufferProvider(Wsbm* wsbm);
+ ~RotationBufferProvider();
+
+ bool initialize();
+ void deinitialize();
+ void reset();
+ bool setupRotationBuffer(VideoPayloadBuffer *payload, int transform);
+ bool prepareBufferInfo(int, int, int, VideoPayloadBuffer *, void *);
+
+private:
+ void invalidateCaches();
+ bool startVA(VideoPayloadBuffer *payload, int transform);
+ void stopVA();
+ bool isContextChanged(int width, int height, int transform);
+ int transFromHalToVa(int transform);
+ uint32_t createWsbmBuffer(int width, int height, void **buf);
+ int getStride(bool isTarget, int width);
+ bool createVaSurface(VideoPayloadBuffer *payload, int transform, bool isTarget);
+ void freeVaSurfaces();
+ inline uint32_t getMilliseconds();
+
+private:
+ enum {
+ MAX_SURFACE_NUM = 4
+ };
+
+ Wsbm* mWsbm;
+
+ bool mVaInitialized;
+ VADisplay mVaDpy;
+ VAConfigID mVaCfg;
+ VAContextID mVaCtx;
+ VABufferID mVaBufFilter;
+ VASurfaceID mSourceSurface;
+ Display mDisplay;
+
+ // rotation config variables
+ int mWidth;
+ int mHeight;
+ int mTransform;
+
+ int mRotatedWidth;
+ int mRotatedHeight;
+ int mRotatedStride;
+
+ int mTargetIndex;
+ int mKhandles[MAX_SURFACE_NUM];
+ VASurfaceID mRotatedSurfaces[MAX_SURFACE_NUM];
+ void *mDrmBuf[MAX_SURFACE_NUM];
+
+ enum {
+ TTM_WRAPPER_COUNT = 10,
+ };
+
+ KeyedVector<uint64_t, void*> mTTMWrappers; /* userPt/wsbmBuffer */
+
+ int mBobDeinterlace;
+};
+
+} // name space intel
+} // name space android
+
+#endif
diff --git a/moorefield_hdmi/ips/common/SpritePlaneBase.cpp b/moorefield_hdmi/ips/common/SpritePlaneBase.cpp
new file mode 100644
index 0000000..c985793
--- /dev/null
+++ b/moorefield_hdmi/ips/common/SpritePlaneBase.cpp
@@ -0,0 +1,53 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <ips/common/SpritePlaneBase.h>
+#include <ips/common/PixelFormat.h>
+
+namespace android {
+namespace intel {
+
+SpritePlaneBase::SpritePlaneBase(int index, int disp)
+ : DisplayPlane(index, PLANE_SPRITE, disp),
+ mForceBottom(false),
+ mAbovePrimary(true)
+{
+ CTRACE();
+}
+
+SpritePlaneBase::~SpritePlaneBase()
+{
+ CTRACE();
+}
+
+bool SpritePlaneBase::flip(void *ctx)
+{
+ CTRACE();
+ return DisplayPlane::flip(ctx);
+}
+
+bool SpritePlaneBase::enable()
+{
+ return enablePlane(true);
+}
+
+bool SpritePlaneBase::disable()
+{
+ return enablePlane(false);
+}
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/common/SpritePlaneBase.h b/moorefield_hdmi/ips/common/SpritePlaneBase.h
new file mode 100644
index 0000000..32950dd
--- /dev/null
+++ b/moorefield_hdmi/ips/common/SpritePlaneBase.h
@@ -0,0 +1,51 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef SPRITE_PLANE_BASE_H
+#define SPRITE_PLANE_BASE_H
+
+#include <utils/KeyedVector.h>
+#include <common/buffers/BufferCache.h>
+#include <DisplayPlane.h>
+
+namespace android {
+namespace intel {
+
+class SpritePlaneBase : public DisplayPlane {
+public:
+ SpritePlaneBase(int index, int disp);
+ virtual ~SpritePlaneBase();
+public:
+ // hardware operations
+ virtual bool flip(void *ctx);
+ virtual bool enable();
+ virtual bool disable();
+ virtual bool isDisabled() = 0;
+
+ // display device
+ virtual void* getContext() const = 0;
+protected:
+ virtual bool setDataBuffer(BufferMapper& mapper) = 0;
+ virtual bool enablePlane(bool enabled) = 0;
+protected:
+ bool mForceBottom;
+ bool mAbovePrimary;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* SPRITE_PLANE_BASE_H */
+
diff --git a/moorefield_hdmi/ips/common/TTMBufferMapper.cpp b/moorefield_hdmi/ips/common/TTMBufferMapper.cpp
new file mode 100644
index 0000000..8f68092
--- /dev/null
+++ b/moorefield_hdmi/ips/common/TTMBufferMapper.cpp
@@ -0,0 +1,103 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <ips/common/TTMBufferMapper.h>
+
+namespace android {
+namespace intel {
+
+TTMBufferMapper::TTMBufferMapper(Wsbm& wsbm, DataBuffer& buffer)
+ : BufferMapper(buffer),
+ mRefCount(0),
+ mWsbm(wsbm),
+ mBufferObject(0),
+ mGttOffsetInPage(0),
+ mCpuAddress(0),
+ mSize(0)
+{
+ CTRACE();
+}
+
+TTMBufferMapper::~TTMBufferMapper()
+{
+ CTRACE();
+}
+
+bool TTMBufferMapper::map()
+{
+ void *wsbmBufferObject = 0;
+ uint32_t handle;
+ void *virtAddr;
+ uint32_t gttOffsetInPage;
+
+ CTRACE();
+
+ handle = getHandle();
+
+ bool ret = mWsbm.wrapTTMBuffer(handle, &wsbmBufferObject);
+ if (ret == false) {
+ ELOGTRACE("failed to map TTM buffer");
+ return false;
+ }
+
+ // TODO: review this later
+ ret = mWsbm.waitIdleTTMBuffer(wsbmBufferObject);
+ if (ret == false) {
+ ELOGTRACE("failed to wait ttm buffer idle");
+ return false;
+ }
+
+ virtAddr = mWsbm.getCPUAddress(wsbmBufferObject);
+ gttOffsetInPage = mWsbm.getGttOffset(wsbmBufferObject);
+
+ if (!gttOffsetInPage || !virtAddr) {
+ WLOGTRACE("offset = %#x, addr = %p.", gttOffsetInPage, virtAddr);
+ return false;
+ }
+
+ // update parameters
+ mBufferObject = wsbmBufferObject;
+ mGttOffsetInPage = gttOffsetInPage;
+ mCpuAddress = virtAddr;
+ mSize = 0;
+ return true;
+}
+
+bool TTMBufferMapper::unmap()
+{
+ CTRACE();
+
+ if (!mBufferObject)
+ return false;
+
+ mWsbm.unreferenceTTMBuffer(mBufferObject);
+
+ mGttOffsetInPage = 0;
+ mCpuAddress = 0;
+ mSize = 0;
+ mBufferObject = 0;
+ return true;
+}
+
+bool TTMBufferMapper::waitIdle()
+{
+ return mWsbm.waitIdleTTMBuffer(mBufferObject);
+}
+
+} // namespace intel
+} // namespace android
+
+
diff --git a/moorefield_hdmi/ips/common/TTMBufferMapper.h b/moorefield_hdmi/ips/common/TTMBufferMapper.h
new file mode 100644
index 0000000..3e1cfaf
--- /dev/null
+++ b/moorefield_hdmi/ips/common/TTMBufferMapper.h
@@ -0,0 +1,70 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef TTMBUFFERMAPPER_H_
+#define TTMBUFFERMAPPER_H_
+
+#include <DataBuffer.h>
+#include <BufferMapper.h>
+#include <ips/common/Wsbm.h>
+
+namespace android {
+namespace intel {
+
+class TTMBufferMapper : public BufferMapper {
+public:
+ TTMBufferMapper(Wsbm& wsbm, DataBuffer& buffer);
+ virtual ~TTMBufferMapper();
+public:
+ bool map();
+ bool unmap();
+
+ uint32_t getGttOffsetInPage(int /* subIndex */) const {
+ return mGttOffsetInPage;
+ }
+ void* getCpuAddress(int /* subIndex */) const {
+ return mCpuAddress;
+ }
+ uint32_t getSize(int /* subIndex */) const {
+ return mSize;
+ }
+ uint32_t getKHandle(int /* subIndex */) {
+ return 0;
+ }
+ uint32_t getFbHandle(int /* subIndex */) {
+ return 0;
+ }
+ void putFbHandle() {
+ return;
+ }
+
+ // wait idle
+ bool waitIdle();
+private:
+ int mRefCount;
+ Wsbm& mWsbm;
+ void* mBufferObject;
+
+ // mapped info
+ uint32_t mGttOffsetInPage;
+ void* mCpuAddress;
+ uint32_t mSize;
+};
+
+} //namespace intel
+} //namespace android
+
+
+#endif /* TTMBUFFERMAPPER_H_ */
diff --git a/moorefield_hdmi/ips/common/VideoPayloadBuffer.h b/moorefield_hdmi/ips/common/VideoPayloadBuffer.h
new file mode 100644
index 0000000..48dc273
--- /dev/null
+++ b/moorefield_hdmi/ips/common/VideoPayloadBuffer.h
@@ -0,0 +1,84 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef VIDEO_PAYLOAD_BUFFER_H
+#define VIDEO_PAYLOAD_BUFFER_H
+
+#include <utils/Timers.h>
+namespace android {
+namespace intel {
+
+struct VideoPayloadBuffer {
+ // transform made by clients (clients to hwc)
+ int client_transform;
+ int metadata_transform;
+ int rotated_width;
+ int rotated_height;
+ int surface_protected;
+ int force_output_method;
+ uint32_t rotated_buffer_handle;
+ uint32_t renderStatus;
+ unsigned int used_by_widi;
+ int bob_deinterlace;
+ int tiling;
+ uint32_t width;
+ uint32_t height;
+ uint32_t luma_stride;
+ uint32_t chroma_u_stride;
+ uint32_t chroma_v_stride;
+ uint32_t format;
+ uint32_t khandle;
+ int64_t timestamp;
+
+ uint32_t rotate_luma_stride;
+ uint32_t rotate_chroma_u_stride;
+ uint32_t rotate_chroma_v_stride;
+
+ nsecs_t hwc_timestamp;
+ uint32_t layer_transform;
+
+ void *native_window;
+ uint32_t scaling_khandle;
+ uint32_t scaling_width;
+ uint32_t scaling_height;
+
+ uint32_t scaling_luma_stride;
+ uint32_t scaling_chroma_u_stride;
+ uint32_t scaling_chroma_v_stride;
+
+ uint32_t crop_width;
+ uint32_t crop_height;
+
+ uint32_t coded_width;
+ uint32_t coded_height;
+};
+
+
+// force output method values
+enum {
+ FORCE_OUTPUT_INVALID = 0,
+ FORCE_OUTPUT_GPU,
+ FORCE_OUTPUT_OVERLAY,
+ FORCE_OUTPUT_SW_DECODE,
+};
+
+
+} // namespace intel
+} // namespace android
+
+
+#endif // VIDEO_PAYLOAD_BUFFER_H
+
+
diff --git a/moorefield_hdmi/ips/common/VsyncControl.cpp b/moorefield_hdmi/ips/common/VsyncControl.cpp
new file mode 100644
index 0000000..89b27e4
--- /dev/null
+++ b/moorefield_hdmi/ips/common/VsyncControl.cpp
@@ -0,0 +1,84 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <common/base/Drm.h>
+#include <Hwcomposer.h>
+#include <ips/common/VsyncControl.h>
+
+namespace android {
+namespace intel {
+
+VsyncControl::VsyncControl()
+ : IVsyncControl(),
+ mInitialized(false)
+{
+}
+
+VsyncControl::~VsyncControl()
+{
+ WARN_IF_NOT_DEINIT();
+}
+
+bool VsyncControl::initialize()
+{
+ mInitialized = true;
+ return true;
+}
+
+void VsyncControl::deinitialize()
+{
+ mInitialized = false;
+}
+
+bool VsyncControl::control(int disp, bool enabled)
+{
+ ALOGTRACE("disp = %d, enabled = %d", disp, enabled);
+
+ struct drm_psb_vsync_set_arg arg;
+ memset(&arg, 0, sizeof(struct drm_psb_vsync_set_arg));
+
+ // pipe equals to disp
+ arg.vsync.pipe = disp;
+
+ if (enabled) {
+ arg.vsync_operation_mask = VSYNC_ENABLE;
+ } else {
+ arg.vsync_operation_mask = VSYNC_DISABLE;
+ }
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ return drm->writeReadIoctl(DRM_PSB_VSYNC_SET, &arg, sizeof(arg));
+}
+
+bool VsyncControl::wait(int disp, int64_t& timestamp)
+{
+ ALOGTRACE("disp = %d", disp);
+
+ struct drm_psb_vsync_set_arg arg;
+ memset(&arg, 0, sizeof(struct drm_psb_vsync_set_arg));
+
+ arg.vsync_operation_mask = VSYNC_WAIT;
+
+ // pipe equals to disp
+ arg.vsync.pipe = disp;
+
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ bool ret = drm->writeReadIoctl(DRM_PSB_VSYNC_SET, &arg, sizeof(arg));
+ timestamp = (int64_t)arg.vsync.timestamp;
+ return ret;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/common/VsyncControl.h b/moorefield_hdmi/ips/common/VsyncControl.h
new file mode 100644
index 0000000..d5ffa11
--- /dev/null
+++ b/moorefield_hdmi/ips/common/VsyncControl.h
@@ -0,0 +1,43 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef VSYNC_CONTROL_H
+#define VSYNC_CONTROL_H
+
+#include <IVsyncControl.h>
+
+namespace android {
+namespace intel {
+
+class VsyncControl : public IVsyncControl {
+public:
+ VsyncControl();
+ virtual ~VsyncControl();
+
+public:
+ bool initialize();
+ void deinitialize();
+ bool control(int disp, bool enabled);
+ bool wait(int disp, int64_t& timestamp);
+
+private:
+ bool mInitialized;
+};
+
+} // namespace intel
+} // namespace android
+
+
+#endif /* VSYNC_CONTROL_H */
diff --git a/moorefield_hdmi/ips/common/Wsbm.cpp b/moorefield_hdmi/ips/common/Wsbm.cpp
new file mode 100644
index 0000000..a9903b9
--- /dev/null
+++ b/moorefield_hdmi/ips/common/Wsbm.cpp
@@ -0,0 +1,136 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <ips/common/Wsbm.h>
+
+Wsbm::Wsbm(int drmFD)
+ : mInitialized(false)
+{
+ CTRACE();
+ mDrmFD = drmFD;
+}
+
+Wsbm::~Wsbm()
+{
+ WARN_IF_NOT_DEINIT();
+}
+
+bool Wsbm::initialize()
+{
+ if (mInitialized) {
+ WLOGTRACE("object is initialized");
+ return true;
+ }
+
+ int ret = psbWsbmInitialize(mDrmFD);
+ if (ret) {
+ ELOGTRACE("failed to initialize Wsbm");
+ return false;
+ }
+
+ mInitialized = true;
+ return true;
+}
+
+void Wsbm::deinitialize()
+{
+ if (!mInitialized) {
+ return;
+ }
+ psbWsbmTakedown();
+ mInitialized = false;
+}
+
+bool Wsbm::allocateTTMBuffer(uint32_t size, uint32_t align, void ** buf)
+{
+ int ret = psbWsbmAllocateTTMBuffer(size, align, buf);
+ if (ret) {
+ ELOGTRACE("failed to allocate buffer");
+ return false;
+ }
+
+ return true;
+}
+
+bool Wsbm::allocateTTMBufferUB(uint32_t size, uint32_t align, void ** buf, void *user_pt)
+{
+ int ret = psbWsbmAllocateFromUB(size, align, buf, user_pt);
+ if (ret) {
+ ELOGTRACE("failed to allocate UB buffer");
+ return false;
+ }
+
+ return true;
+}
+
+bool Wsbm::destroyTTMBuffer(void * buf)
+{
+ int ret = psbWsbmDestroyTTMBuffer(buf);
+ if (ret) {
+ ELOGTRACE("failed to destroy buffer");
+ return false;
+ }
+
+ return true;
+}
+
+void * Wsbm::getCPUAddress(void * buf)
+{
+ return psbWsbmGetCPUAddress(buf);
+}
+
+uint32_t Wsbm::getGttOffset(void * buf)
+{
+ return psbWsbmGetGttOffset(buf);
+}
+
+bool Wsbm::wrapTTMBuffer(uint32_t handle, void **buf)
+{
+ int ret = psbWsbmWrapTTMBuffer(handle, buf);
+ if (ret) {
+ ELOGTRACE("failed to wrap buffer");
+ return false;
+ }
+
+ return true;
+}
+
+bool Wsbm::unreferenceTTMBuffer(void *buf)
+{
+ int ret = psbWsbmUnReference(buf);
+ if (ret) {
+ ELOGTRACE("failed to unreference buffer");
+ return false;
+ }
+
+ return true;
+}
+
+uint32_t Wsbm::getKBufHandle(void *buf)
+{
+ return psbWsbmGetKBufHandle(buf);
+}
+
+bool Wsbm::waitIdleTTMBuffer(void *buf)
+{
+ int ret = psbWsbmWaitIdle(buf);
+ if (ret) {
+ ELOGTRACE("failed to wait ttm buffer for idle");
+ return false;
+ }
+
+ return true;
+}
diff --git a/moorefield_hdmi/ips/common/Wsbm.h b/moorefield_hdmi/ips/common/Wsbm.h
new file mode 100644
index 0000000..ddfe32d
--- /dev/null
+++ b/moorefield_hdmi/ips/common/Wsbm.h
@@ -0,0 +1,47 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef WSBM_H__
+#define WSBM_H__
+
+#include <ips/common/WsbmWrapper.h>
+
+/**
+ * Class: WSBM
+ * A wrapper class to use libwsbm functionalities
+ */
+class Wsbm
+{
+private:
+ int mDrmFD;
+public:
+ Wsbm(int drmFD);
+ ~Wsbm();
+ bool initialize();
+ void deinitialize();
+ bool allocateTTMBuffer(uint32_t size, uint32_t align,void ** buf);
+ bool allocateTTMBufferUB(uint32_t size, uint32_t align, void ** buf, void *user_pt);
+ bool destroyTTMBuffer(void * buf);
+ void * getCPUAddress(void * buf);
+ uint32_t getGttOffset(void * buf);
+ bool wrapTTMBuffer(uint32_t handle, void **buf);
+ bool unreferenceTTMBuffer(void *buf);
+ bool waitIdleTTMBuffer(void *buf);
+ uint32_t getKBufHandle(void *buf);
+private:
+ bool mInitialized;
+};
+
+#endif /*__INTEL_WSBM_H__*/
diff --git a/moorefield_hdmi/ips/common/WsbmWrapper.c b/moorefield_hdmi/ips/common/WsbmWrapper.c
new file mode 100644
index 0000000..08ddefc
--- /dev/null
+++ b/moorefield_hdmi/ips/common/WsbmWrapper.c
@@ -0,0 +1,401 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <wsbm_pool.h>
+#include <wsbm_driver.h>
+#include <wsbm_manager.h>
+#include <wsbm_util.h>
+#include <drm/ttm/ttm_placement.h>
+#include <linux/psb_drm.h>
+#include <xf86drm.h>
+#include <common/utils/HwcTrace.h>
+
+struct _WsbmBufferPool * mainPool = NULL;
+
+struct PsbWsbmValidateNode
+{
+ struct _ValidateNode base;
+ struct psb_validate_arg arg;
+};
+
+static inline uint32_t align_to(uint32_t arg, uint32_t align)
+{
+ return ((arg + (align - 1)) & (~(align - 1)));
+}
+
+static struct _ValidateNode * pvrAlloc(struct _WsbmVNodeFuncs * func,
+ int typeId)
+{
+ CTRACE();
+ if(typeId == 0) {
+ struct PsbWsbmValidateNode * vNode = malloc(sizeof(*vNode));
+ if(!vNode) {
+ ELOGTRACE("failed to allocate memory");
+ return NULL;
+ }
+
+ vNode->base.func = func;
+ vNode->base.type_id = 0;
+ return &vNode->base;
+ } else {
+ struct _ValidateNode * node = malloc(sizeof(*node));
+ if(!node) {
+ ELOGTRACE("failed to allocate node");
+ return NULL;
+ }
+
+ node->func = func;
+ node->type_id = 1;
+ return node;
+ }
+}
+
+static void pvrFree(struct _ValidateNode * node)
+{
+ CTRACE();
+ if(node->type_id == 0) {
+ free(containerOf(node, struct PsbWsbmValidateNode, base));
+ } else {
+ free(node);
+ }
+}
+
+static void pvrClear(struct _ValidateNode * node)
+{
+ CTRACE();
+ if(node->type_id == 0) {
+ struct PsbWsbmValidateNode * vNode =
+ containerOf(node, struct PsbWsbmValidateNode, base);
+ memset(&vNode->arg.d.req, 0, sizeof(vNode->arg.d.req));
+ }
+}
+
+static struct _WsbmVNodeFuncs vNodeFuncs = {
+ .alloc = pvrAlloc,
+ .free = pvrFree,
+ .clear = pvrClear,
+};
+
+void psbWsbmTakedown()
+{
+ CTRACE();
+
+ if (mainPool) {
+ wsbmPoolTakeDown(mainPool);
+ mainPool = NULL;
+ }
+
+ if (wsbmIsInitialized()) {
+ wsbmTakedown();
+ }
+}
+
+int psbWsbmInitialize(int drmFD)
+{
+ union drm_psb_extension_arg arg;
+ const char drmExt[] = "psb_ttm_placement_alphadrop";
+ int ret = 0;
+
+ CTRACE();
+
+ if (drmFD <= 0) {
+ ELOGTRACE("invalid drm fd %d", drmFD);
+ return drmFD;
+ }
+
+ /*init wsbm*/
+ ret = wsbmInit(wsbmNullThreadFuncs(), &vNodeFuncs);
+ if (ret) {
+ ELOGTRACE("failed to initialize Wsbm, error code %d", ret);
+ return ret;
+ }
+
+ VLOGTRACE("DRM_PSB_EXTENSION %d", DRM_PSB_EXTENSION);
+
+ /*get devOffset via drm IOCTL*/
+ strncpy(arg.extension, drmExt, sizeof(drmExt));
+
+ ret = drmCommandWriteRead(drmFD, 6/*DRM_PSB_EXTENSION*/, &arg, sizeof(arg));
+ if(ret || !arg.rep.exists) {
+ ELOGTRACE("failed to get device offset, error code %d", ret);
+ goto out;
+ }
+
+ VLOGTRACE("ioctl offset %#x", arg.rep.driver_ioctl_offset);
+
+ mainPool = wsbmTTMPoolInit(drmFD, arg.rep.driver_ioctl_offset);
+ if(!mainPool) {
+ ELOGTRACE("failed to initialize TTM Pool");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ VLOGTRACE("Wsbm initialization succeeded. mainPool %p", mainPool);
+
+ return 0;
+
+out:
+ psbWsbmTakedown();
+ return ret;
+}
+
+int psbWsbmAllocateFromUB(uint32_t size, uint32_t align, void ** buf, void *user_pt)
+{
+ struct _WsbmBufferObject * wsbmBuf = NULL;
+ int ret = 0;
+ int offset = 0;
+
+ ALOGTRACE("size %d", align_to(size, 4096));
+
+ if(!buf || !user_pt) {
+ ELOGTRACE("invalid parameter");
+ return -EINVAL;
+ }
+
+ VLOGTRACE("mainPool %p", mainPool);
+
+ ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, align,
+ DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_CACHED |
+ WSBM_PL_FLAG_NO_EVICT | WSBM_PL_FLAG_SHARED);
+ if(ret) {
+ ELOGTRACE("wsbmGenBuffers failed with error code %d", ret);
+ return ret;
+ }
+
+ ret = wsbmBODataUB(wsbmBuf,
+ align_to(size, 4096), NULL, NULL, 0,
+ user_pt);
+
+ if(ret) {
+ ELOGTRACE("wsbmBOData failed with error code %d", ret);
+ /*FIXME: should I unreference this buffer here?*/
+ return ret;
+ }
+
+ *buf = wsbmBuf;
+
+ VLOGTRACE("ttm UB buffer allocated. %p", *buf);
+ return 0;
+}
+
+int psbWsbmAllocateTTMBuffer(uint32_t size, uint32_t align, void ** buf)
+{
+ struct _WsbmBufferObject * wsbmBuf = NULL;
+ int ret = 0;
+ int offset = 0;
+
+ ALOGTRACE("size %d", align_to(size, 4096));
+
+ if(!buf) {
+ ELOGTRACE("invalid parameter");
+ return -EINVAL;
+ }
+
+ VLOGTRACE("mainPool %p", mainPool);
+
+ ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, align,
+ (WSBM_PL_FLAG_VRAM | WSBM_PL_FLAG_TT |
+ WSBM_PL_FLAG_SHARED | WSBM_PL_FLAG_NO_EVICT));
+ if(ret) {
+ ELOGTRACE("wsbmGenBuffers failed with error code %d", ret);
+ return ret;
+ }
+
+ ret = wsbmBOData(wsbmBuf, align_to(size, 4096), NULL, NULL, 0);
+ if(ret) {
+ ELOGTRACE("wsbmBOData failed with error code %d", ret);
+ /*FIXME: should I unreference this buffer here?*/
+ return ret;
+ }
+
+ /* wsbmBOReference(wsbmBuf); */ /* no need to add reference */
+
+ *buf = wsbmBuf;
+
+ VLOGTRACE("ttm buffer allocated. %p", *buf);
+ return 0;
+}
+
+int psbWsbmWrapTTMBuffer(uint32_t handle, void **buf)
+{
+ int ret = 0;
+ struct _WsbmBufferObject *wsbmBuf;
+
+ if (!buf) {
+ ELOGTRACE("invalid parameter");
+ return -EINVAL;
+ }
+
+ ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, 0,
+ (WSBM_PL_FLAG_VRAM | WSBM_PL_FLAG_TT |
+ /*WSBM_PL_FLAG_NO_EVICT |*/ WSBM_PL_FLAG_SHARED));
+
+ if (ret) {
+ ELOGTRACE("wsbmGenBuffers failed with error code %d", ret);
+ return ret;
+ }
+
+ ret = wsbmBOSetReferenced(wsbmBuf, handle);
+ if (ret) {
+ ELOGTRACE("wsbmBOSetReferenced failed with error code %d", ret);
+ return ret;
+ }
+
+ *buf = (void *)wsbmBuf;
+
+ VLOGTRACE("wrap buffer %p for handle %#x", wsbmBuf, handle);
+ return 0;
+}
+
+int psbWsbmWrapTTMBuffer2(uint32_t handle, void **buf)
+{
+ int ret = 0;
+ struct _WsbmBufferObject *wsbmBuf;
+
+ if (!buf) {
+ ELOGTRACE("invalid parameter");
+ return -EINVAL;
+ }
+
+ ret = wsbmGenBuffers(mainPool, 1, &wsbmBuf, 4096,
+ (WSBM_PL_FLAG_SHARED | DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_UNCACHED));
+
+ if (ret) {
+ ELOGTRACE("wsbmGenBuffers failed with error code %d", ret);
+ return ret;
+ }
+
+ *buf = (void *)wsbmBuf;
+
+ VLOGTRACE("wrap buffer %p for handle %#x", wsbmBuf, handle);
+ return 0;
+}
+
+
+int psbWsbmCreateFromUB(void *buf, uint32_t size, void *vaddr)
+{
+ int ret = 0;
+ struct _WsbmBufferObject *wsbmBuf;
+
+ if (!buf || !vaddr) {
+ ELOGTRACE("invalid parameter");
+ return -EINVAL;
+ }
+
+ wsbmBuf = (struct _WsbmBufferObject *)buf;
+ ret = wsbmBODataUB(wsbmBuf, size, NULL, NULL, 0, vaddr);
+ if (ret) {
+ ELOGTRACE("wsbmBODataUB failed with error code %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int psbWsbmUnReference(void *buf)
+{
+ struct _WsbmBufferObject *wsbmBuf;
+
+ if (!buf) {
+ ELOGTRACE("invalid parameter");
+ return -EINVAL;
+ }
+
+ wsbmBuf = (struct _WsbmBufferObject *)buf;
+
+ wsbmBOUnreference(&wsbmBuf);
+
+ return 0;
+}
+
+int psbWsbmDestroyTTMBuffer(void * buf)
+{
+ CTRACE();
+
+ if(!buf) {
+ ELOGTRACE("invalid ttm buffer");
+ return -EINVAL;
+ }
+
+ /*FIXME: should I unmap this buffer object first?*/
+ wsbmBOUnmap((struct _WsbmBufferObject *)buf);
+
+ wsbmBOUnreference((struct _WsbmBufferObject **)&buf);
+
+ XLOGTRACE();
+
+ return 0;
+}
+
+void * psbWsbmGetCPUAddress(void * buf)
+{
+ if(!buf) {
+ ELOGTRACE("invalid ttm buffer");
+ return NULL;
+ }
+
+ VLOGTRACE("buffer object %p", buf);
+
+ void * address = wsbmBOMap((struct _WsbmBufferObject *)buf,
+ WSBM_ACCESS_READ | WSBM_ACCESS_WRITE);
+ if(!address) {
+ ELOGTRACE("failed to map buffer object");
+ return NULL;
+ }
+
+ VLOGTRACE("mapped successfully. %p, size %ld",
+ address, wsbmBOSize((struct _WsbmBufferObject *)buf));
+
+ return address;
+}
+
+uint32_t psbWsbmGetGttOffset(void * buf)
+{
+ if(!buf) {
+ ELOGTRACE("invalid ttm buffer");
+ return 0;
+ }
+
+ VLOGTRACE("buffer object %p", buf);
+
+ uint32_t offset =
+ wsbmBOOffsetHint((struct _WsbmBufferObject *)buf) - 0x10000000;
+
+ VLOGTRACE("offset %#x", offset >> 12);
+
+ return offset >> 12;
+}
+
+uint32_t psbWsbmGetKBufHandle(void *buf)
+{
+ if (!buf) {
+ ELOGTRACE("invalid ttm buffer");
+ return 0;
+ }
+
+ return (wsbmKBufHandle(wsbmKBuf((struct _WsbmBufferObject *)buf)));
+}
+
+uint32_t psbWsbmWaitIdle(void *buf)
+{
+ if (!buf) {
+ ELOGTRACE("invalid ttm buffer");
+ return -EINVAL;
+ }
+
+ wsbmBOWaitIdle(buf, 0);
+ return 0;
+}
diff --git a/moorefield_hdmi/ips/common/WsbmWrapper.h b/moorefield_hdmi/ips/common/WsbmWrapper.h
new file mode 100644
index 0000000..b2622a3
--- /dev/null
+++ b/moorefield_hdmi/ips/common/WsbmWrapper.h
@@ -0,0 +1,41 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef WSBM_WRAPPER_H
+#define WSBM_WRAPPER_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+extern int psbWsbmInitialize(int drmFD);
+extern void psbWsbmTakedown();
+extern int psbWsbmAllocateFromUB(uint32_t size, uint32_t align, void ** buf, void *user_pt);
+extern int psbWsbmAllocateTTMBuffer(uint32_t size, uint32_t align,void ** buf);
+extern int psbWsbmDestroyTTMBuffer(void * buf);
+extern void * psbWsbmGetCPUAddress(void * buf);
+extern uint32_t psbWsbmGetGttOffset(void * buf);
+extern int psbWsbmWrapTTMBuffer(uint32_t handle, void **buf);
+extern int psbWsbmWrapTTMBuffer2(uint32_t handle, void **buf);
+extern int psbWsbmCreateFromUB(void *buf, uint32_t size, void *vaddr);
+extern int psbWsbmUnReference(void *buf);
+extern int psbWsbmWaitIdle(void *buf);
+uint32_t psbWsbmGetKBufHandle(void *buf);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /*WSBM_WRAPPER_H*/
diff --git a/moorefield_hdmi/ips/tangier/TngDisplayContext.cpp b/moorefield_hdmi/ips/tangier/TngDisplayContext.cpp
new file mode 100755
index 0000000..f745700
--- /dev/null
+++ b/moorefield_hdmi/ips/tangier/TngDisplayContext.cpp
@@ -0,0 +1,276 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <common/base/Drm.h>
+#include <Hwcomposer.h>
+#include <DisplayPlane.h>
+#include <IDisplayDevice.h>
+#include <common/base/HwcLayerList.h>
+#include <ips/tangier/TngDisplayContext.h>
+
+
+namespace android {
+namespace intel {
+
+TngDisplayContext::TngDisplayContext()
+ : mIMGDisplayDevice(0),
+ mInitialized(false),
+ mCount(0)
+{
+ CTRACE();
+}
+
+TngDisplayContext::~TngDisplayContext()
+{
+ WARN_IF_NOT_DEINIT();
+}
+
+bool TngDisplayContext::initialize()
+{
+ CTRACE();
+
+ // open frame buffer device
+ hw_module_t const* module;
+ int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ if (err) {
+ ELOGTRACE("failed to load gralloc module, error = %d", err);
+ return false;
+ }
+
+ // init IMG display device
+ mIMGDisplayDevice = (((IMG_gralloc_module_public_t *)module)->getDisplayDevice((IMG_gralloc_module_public_t *)module));
+ if (!mIMGDisplayDevice) {
+ ELOGTRACE("failed to get display device");
+ return false;
+ }
+
+ mCount = 0;
+ mInitialized = true;
+ return true;
+}
+
+bool TngDisplayContext::commitBegin(size_t /* numDisplays */,
+ hwc_display_contents_1_t ** /* displays */)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+ mCount = 0;
+ return true;
+}
+
+bool TngDisplayContext::commitContents(hwc_display_contents_1_t *display, HwcLayerList *layerList)
+{
+ bool ret;
+
+ RETURN_FALSE_IF_NOT_INIT();
+
+ if (!display || !layerList) {
+ ELOGTRACE("invalid parameters");
+ return false;
+ }
+
+ IMG_hwc_layer_t *imgLayerList = (IMG_hwc_layer_t*)mImgLayers;
+
+ for (size_t i = 0; i < display->numHwLayers; i++) {
+ if (mCount >= MAXIMUM_LAYER_NUMBER) {
+ ELOGTRACE("layer count exceeds the limit");
+ return false;
+ }
+
+ // check layer parameters
+ if (!display->hwLayers[i].handle) {
+ continue;
+ }
+
+ DisplayPlane* plane = layerList->getPlane(i);
+ if (!plane) {
+ continue;
+ }
+
+ ret = plane->flip(NULL);
+ if (ret == false) {
+ VLOGTRACE("failed to flip plane %d", i);
+ continue;
+ }
+
+ IMG_hwc_layer_t *imgLayer = &imgLayerList[mCount++];
+ // update IMG layer
+ imgLayer->psLayer = &display->hwLayers[i];
+ imgLayer->custom = (uint32_t)plane->getContext();
+ struct intel_dc_plane_ctx *ctx =
+ (struct intel_dc_plane_ctx *)imgLayer->custom;
+ // update z order
+ Hwcomposer& hwc = Hwcomposer::getInstance();
+ DisplayPlaneManager *pm = hwc.getPlaneManager();
+ void *config = pm->getZOrderConfig();
+ if (config) {
+ memcpy(&ctx->zorder, config, sizeof(ctx->zorder));
+ } else {
+ memset(&ctx->zorder, 0, sizeof(ctx->zorder));
+ }
+
+ VLOGTRACE("count %d, handle %#x, trans %#x, blending %#x"
+ " sourceCrop %f,%f - %fx%f, dst %d,%d - %dx%d, custom %#x",
+ mCount,
+ (uint32_t)imgLayer->psLayer->handle,
+ imgLayer->psLayer->transform,
+ imgLayer->psLayer->blending,
+ imgLayer->psLayer->sourceCropf.left,
+ imgLayer->psLayer->sourceCropf.top,
+ imgLayer->psLayer->sourceCropf.right - imgLayer->psLayer->sourceCropf.left,
+ imgLayer->psLayer->sourceCropf.bottom - imgLayer->psLayer->sourceCropf.top,
+ imgLayer->psLayer->displayFrame.left,
+ imgLayer->psLayer->displayFrame.top,
+ imgLayer->psLayer->displayFrame.right - imgLayer->psLayer->displayFrame.left,
+ imgLayer->psLayer->displayFrame.bottom - imgLayer->psLayer->displayFrame.top,
+ imgLayer->custom);
+ }
+
+ layerList->postFlip();
+ return true;
+}
+
+bool TngDisplayContext::commitEnd(size_t numDisplays, hwc_display_contents_1_t **displays)
+{
+ int releaseFenceFd = -1;
+
+ VLOGTRACE("count = %d", mCount);
+
+ if (mIMGDisplayDevice && mCount) {
+ int err = mIMGDisplayDevice->post(mIMGDisplayDevice,
+ mImgLayers,
+ mCount,
+ &releaseFenceFd);
+ if (err) {
+ ELOGTRACE("post failed, err = %d", err);
+ return false;
+ }
+ }
+
+ // close acquire fence
+ for (size_t i = 0; i < numDisplays; i++) {
+ // Wait and close HWC_OVERLAY typed layer's acquire fence
+ hwc_display_contents_1_t* display = displays[i];
+ if (!display) {
+ continue;
+ }
+
+ for (size_t j = 0; j < display->numHwLayers-1; j++) {
+ hwc_layer_1_t& layer = display->hwLayers[j];
+ if (layer.compositionType == HWC_OVERLAY) {
+ if (layer.acquireFenceFd != -1) {
+ // sync_wait(layer.acquireFenceFd, 16ms);
+ close(layer.acquireFenceFd);
+ layer.acquireFenceFd = -1;
+ }
+ }
+ }
+
+ // Wait and close framebuffer target layer's acquire fence
+ hwc_layer_1_t& fbt = display->hwLayers[display->numHwLayers-1];
+ if (fbt.acquireFenceFd != -1) {
+ // sync_wait(fbt.acquireFencdFd, 16ms);
+ close(fbt.acquireFenceFd);
+ fbt.acquireFenceFd = -1;
+ }
+
+ // Wait and close outbuf's acquire fence
+ if (display->outbufAcquireFenceFd != -1) {
+ // sync_wait(display->outbufAcquireFenceFd, 16ms);
+ close(display->outbufAcquireFenceFd);
+ display->outbufAcquireFenceFd = -1;
+ }
+ }
+
+ // update release fence and retire fence
+ if (mCount > 0) {
+ // For physical displays, dup the releaseFenceFd only for
+ // HWC layers which successfully flipped to display planes
+ IMG_hwc_layer_t *imgLayerList = (IMG_hwc_layer_t*)mImgLayers;
+
+ for (size_t i = 0; i < mCount; i++) {
+ IMG_hwc_layer_t *imgLayer = &imgLayerList[i];
+ imgLayer->psLayer->releaseFenceFd =
+ (releaseFenceFd != -1) ? dup(releaseFenceFd) : -1;
+ }
+ }
+
+ for (size_t i = 0; i < numDisplays; i++) {
+ if (!displays[i]) {
+ continue;
+ }
+
+ // log for layer fence status
+ for (size_t j = 0; j < displays[i]->numHwLayers; j++) {
+ VLOGTRACE("handle %#x, acquiredFD %d, releaseFD %d",
+ (uint32_t)displays[i]->hwLayers[j].handle,
+ displays[i]->hwLayers[j].acquireFenceFd,
+ displays[i]->hwLayers[j].releaseFenceFd);
+ }
+
+ // retireFence is used for SurfaceFlinger to do DispSync;
+ // dup releaseFenceFd for physical displays and ignore virtual
+ // display; we don't distinguish between release and retire, and all
+ // physical displays are using a single releaseFence; for virtual
+ // display, fencing is handled by the VirtualDisplay class
+ if (i < IDisplayDevice::DEVICE_VIRTUAL) {
+ displays[i]->retireFenceFd =
+ (releaseFenceFd != -1) ? dup(releaseFenceFd) : -1;
+ }
+ }
+
+ // close original release fence fd
+ if (releaseFenceFd != -1) {
+ close(releaseFenceFd);
+ }
+ return true;
+}
+
+bool TngDisplayContext::compositionComplete()
+{
+ return true;
+}
+
+bool TngDisplayContext::setCursorPosition(int disp, int x, int y)
+{
+ DLOGTRACE("setCursorPosition");
+ struct intel_dc_cursor_ctx ctx;
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.pipe = disp;
+ if (x < 0) {
+ ctx.pos |= 1 << 15;
+ x = -x;
+ }
+ if (y < 0) {
+ ctx.pos |= 1 << 31;
+ y = -y;
+ }
+ ctx.pos |= (y & 0xfff) << 16 | (x & 0xfff);
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ return drm->writeIoctl(DRM_PSB_UPDATE_CURSOR_POS, &ctx, sizeof(ctx));
+}
+
+
+void TngDisplayContext::deinitialize()
+{
+ mIMGDisplayDevice = 0;
+
+ mCount = 0;
+ mInitialized = false;
+}
+
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/tangier/TngDisplayContext.h b/moorefield_hdmi/ips/tangier/TngDisplayContext.h
new file mode 100755
index 0000000..fa526d7
--- /dev/null
+++ b/moorefield_hdmi/ips/tangier/TngDisplayContext.h
@@ -0,0 +1,51 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef TNG_DISPLAY_CONTEXT_H
+#define TNG_DISPLAY_CONTEXT_H
+
+#include <IDisplayContext.h>
+#include <hal_public.h>
+
+namespace android {
+namespace intel {
+
+class TngDisplayContext : public IDisplayContext {
+public:
+ TngDisplayContext();
+ virtual ~TngDisplayContext();
+public:
+ bool initialize();
+ void deinitialize();
+ bool commitBegin(size_t numDisplays, hwc_display_contents_1_t **displays);
+ bool commitContents(hwc_display_contents_1_t *display, HwcLayerList* layerList);
+ bool commitEnd(size_t numDisplays, hwc_display_contents_1_t **displays);
+ bool compositionComplete();
+ bool setCursorPosition(int disp, int x, int y);
+
+private:
+ enum {
+ MAXIMUM_LAYER_NUMBER = 20,
+ };
+ IMG_display_device_public_t *mIMGDisplayDevice;
+ IMG_hwc_layer_t mImgLayers[MAXIMUM_LAYER_NUMBER];
+ bool mInitialized;
+ size_t mCount;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* TNG_DISPLAY_CONTEXT_H */
diff --git a/moorefield_hdmi/ips/tangier/TngDisplayQuery.cpp b/moorefield_hdmi/ips/tangier/TngDisplayQuery.cpp
new file mode 100755
index 0000000..13350aa
--- /dev/null
+++ b/moorefield_hdmi/ips/tangier/TngDisplayQuery.cpp
@@ -0,0 +1,88 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <common/utils/HwcTrace.h>
+#include <DisplayPlane.h>
+#include <hal_public.h>
+#include <DisplayQuery.h>
+#include <khronos/openmax/OMX_IntelVideoExt.h>
+#include <Hwcomposer.h>
+
+
+namespace android {
+namespace intel {
+
+bool DisplayQuery::isVideoFormat(uint32_t format)
+{
+ switch (format) {
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar:
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled:
+ // Expand format to support the case: Software decoder + HW rendering
+ // Only VP9 use this foramt now
+ case HAL_PIXEL_FORMAT_YV12:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int DisplayQuery::getOverlayLumaStrideAlignment(uint32_t format)
+{
+ // both luma and chroma stride need to be 64-byte aligned for overlay
+ switch (format) {
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_I420:
+ // for these two formats, chroma stride is calculated as half of luma stride
+ // so luma stride needs to be 128-byte aligned.
+ return 128;
+ default:
+ return 64;
+ }
+}
+
+uint32_t DisplayQuery::queryNV12Format()
+{
+ return HAL_PIXEL_FORMAT_NV12;
+}
+
+bool DisplayQuery::forceFbScaling(int device)
+{
+ // RGB planes don't support scaling. Panel fitter can be used to scale frame buffer to device's resolution
+ // if scaling factor is less than 1.5. Otherwise, GPU scaling is needed on RGB buffer, or hardware overlay
+ // scaling is needed on NV12 buffer
+
+ // this needs to work together with kernel driver. Panel fitter needs to be disabled if scaling factor is greater
+ // than 1.5
+
+ uint32_t width, height;
+ if (!Hwcomposer::getInstance().getDrm()->getDisplayResolution(device, width, height)) {
+ return false;
+ }
+
+ if (DEFAULT_DRM_FB_WIDTH / (float)width > 1.5) {
+ return true;
+ }
+
+ if (DEFAULT_DRM_FB_HEIGHT / (float)height > 1.5) {
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace intel
+} // namespace android
+
diff --git a/moorefield_hdmi/ips/tangier/TngGrallocBuffer.cpp b/moorefield_hdmi/ips/tangier/TngGrallocBuffer.cpp
new file mode 100644
index 0000000..47d36d4
--- /dev/null
+++ b/moorefield_hdmi/ips/tangier/TngGrallocBuffer.cpp
@@ -0,0 +1,62 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <ips/tangier/TngGrallocBuffer.h>
+
+namespace android {
+namespace intel {
+
+TngGrallocBuffer::TngGrallocBuffer(uint32_t handle)
+ :GrallocBufferBase(handle)
+{
+ initBuffer(handle);
+}
+
+TngGrallocBuffer::~TngGrallocBuffer()
+{
+}
+
+void TngGrallocBuffer::resetBuffer(uint32_t handle)
+{
+ GrallocBufferBase::resetBuffer(handle);
+ initBuffer(handle);
+}
+
+void TngGrallocBuffer::initBuffer(uint32_t handle)
+{
+ TngIMGGrallocBuffer *grallocHandle = (TngIMGGrallocBuffer *)handle;
+
+ CTRACE();
+
+ if (!grallocHandle) {
+ ELOGTRACE("gralloc handle is null");
+ return;
+ }
+
+ mFormat = grallocHandle->iFormat;
+ mWidth = grallocHandle->iWidth;
+ mHeight = grallocHandle->iHeight;
+ mUsage = grallocHandle->usage;
+ mKey = grallocHandle->ui64Stamp;
+ mBpp = grallocHandle->uiBpp;
+
+ // stride can only be initialized after format is set
+ initStride();
+}
+
+
+}
+}
diff --git a/moorefield_hdmi/ips/tangier/TngGrallocBuffer.h b/moorefield_hdmi/ips/tangier/TngGrallocBuffer.h
new file mode 100644
index 0000000..80c096e
--- /dev/null
+++ b/moorefield_hdmi/ips/tangier/TngGrallocBuffer.h
@@ -0,0 +1,44 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef TNG_GRALLOC_BUFFER_H
+#define TNG_GRALLOC_BUFFER_H
+
+#include <DataBuffer.h>
+#include <hal_public.h>
+#include <ips/common/GrallocSubBuffer.h>
+#include <ips/common/GrallocBufferBase.h>
+
+namespace android {
+namespace intel {
+
+typedef IMG_native_handle_t TngIMGGrallocBuffer;
+
+class TngGrallocBuffer : public GrallocBufferBase {
+public:
+ TngGrallocBuffer(uint32_t handle);
+ virtual ~TngGrallocBuffer();
+
+ void resetBuffer(uint32_t handle);
+
+private:
+ void initBuffer(uint32_t handle);
+};
+
+} // namespace intel
+} // namespace android
+
+
+#endif /* TNG_GRALLOC_BUFFER_H */
diff --git a/moorefield_hdmi/ips/tangier/TngGrallocBufferMapper.cpp b/moorefield_hdmi/ips/tangier/TngGrallocBufferMapper.cpp
new file mode 100644
index 0000000..5742f6a
--- /dev/null
+++ b/moorefield_hdmi/ips/tangier/TngGrallocBufferMapper.cpp
@@ -0,0 +1,245 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include <common/utils/HwcTrace.h>
+#include <common/base/Drm.h>
+#include <Hwcomposer.h>
+#include <ips/tangier/TngGrallocBufferMapper.h>
+#include <ips/common/WsbmWrapper.h>
+
+namespace android {
+namespace intel {
+
+TngGrallocBufferMapper::TngGrallocBufferMapper(IMG_gralloc_module_public_t& module,
+ DataBuffer& buffer)
+ : GrallocBufferMapperBase(buffer),
+ mIMGGrallocModule(module),
+ mBufferObject(0)
+{
+ CTRACE();
+}
+
+TngGrallocBufferMapper::~TngGrallocBufferMapper()
+{
+ CTRACE();
+}
+
+bool TngGrallocBufferMapper::gttMap(void *vaddr,
+ uint32_t size,
+ uint32_t gttAlign,
+ int *offset)
+{
+ struct psb_gtt_mapping_arg arg;
+ bool ret;
+
+ ALOGTRACE("vaddr = %p, size = %d", vaddr, size);
+
+ if (!vaddr || !size || !offset) {
+ VLOGTRACE("invalid parameters");
+ return false;
+ }
+
+ arg.type = PSB_GTT_MAP_TYPE_VIRTUAL;
+ arg.page_align = gttAlign;
+ arg.vaddr = (uint32_t)vaddr;
+ arg.size = size;
+
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ ret = drm->writeReadIoctl(DRM_PSB_GTT_MAP, &arg, sizeof(arg));
+ if (ret == false) {
+ ELOGTRACE("gtt mapping failed");
+ return false;
+ }
+
+ VLOGTRACE("offset = %#x", arg.offset_pages);
+ *offset = arg.offset_pages;
+ return true;
+}
+
+bool TngGrallocBufferMapper::gttUnmap(void *vaddr)
+{
+ struct psb_gtt_mapping_arg arg;
+ bool ret;
+
+ ALOGTRACE("vaddr = %p", vaddr);
+
+ if (!vaddr) {
+ ELOGTRACE("invalid parameter");
+ return false;
+ }
+
+ arg.type = PSB_GTT_MAP_TYPE_VIRTUAL;
+ arg.vaddr = (uint32_t)vaddr;
+
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ ret = drm->writeIoctl(DRM_PSB_GTT_UNMAP, &arg, sizeof(arg));
+ if (ret == false) {
+ ELOGTRACE("gtt unmapping failed");
+ return false;
+ }
+
+ return true;
+}
+
+bool TngGrallocBufferMapper::map()
+{
+ void *vaddr[SUB_BUFFER_MAX];
+ uint32_t size[SUB_BUFFER_MAX];
+ int gttOffsetInPage = 0;
+ bool ret;
+ int err;
+ int i;
+
+ CTRACE();
+ // get virtual address
+ err = mIMGGrallocModule.getCpuAddress(&mIMGGrallocModule,
+ (buffer_handle_t)getHandle(),
+ vaddr,
+ size);
+ if (err) {
+ ELOGTRACE("failed to map. err = %d", err);
+ return false;
+ }
+
+ for (i = 0; i < SUB_BUFFER_MAX; i++) {
+ // skip gtt mapping for empty sub buffers
+ if (!vaddr[i] || !size[i])
+ continue;
+
+ // map to gtt
+ ret = gttMap(vaddr[i], size[i], 0, &gttOffsetInPage);
+ if (!ret) {
+ VLOGTRACE("failed to map %d into gtt", i);
+ break;
+ }
+
+ mCpuAddress[i] = vaddr[i];
+ mSize[i] = size[i];
+ mGttOffsetInPage[i] = gttOffsetInPage;
+ // TODO: set kernel handle
+ mKHandle[i] = 0;
+ }
+
+ if (i == SUB_BUFFER_MAX) {
+ return true;
+ }
+
+ // error handling
+ for (i = 0; i < SUB_BUFFER_MAX; i++) {
+ if (mCpuAddress[i]) {
+ gttUnmap(mCpuAddress[i]);
+ }
+ }
+
+ err = mIMGGrallocModule.putCpuAddress(&mIMGGrallocModule,
+ (buffer_handle_t)getHandle());
+ return false;
+}
+
+bool TngGrallocBufferMapper::unmap()
+{
+ int i;
+ int err;
+
+ CTRACE();
+
+ for (i = 0; i < SUB_BUFFER_MAX; i++) {
+ if (mCpuAddress[i])
+ gttUnmap(mCpuAddress[i]);
+
+ mGttOffsetInPage[i] = 0;
+ mCpuAddress[i] = 0;
+ mSize[i] = 0;
+ }
+
+ err = mIMGGrallocModule.putCpuAddress(&mIMGGrallocModule,
+ (buffer_handle_t)getHandle());
+ if (err) {
+ ELOGTRACE("failed to unmap. err = %d", err);
+ }
+ return err;
+}
+
+uint32_t TngGrallocBufferMapper::getKHandle(int subIndex)
+{
+ uint32_t ret = GrallocBufferMapperBase::getKHandle(subIndex);
+ if (subIndex == 0 && ret == 0) {
+ if (mapKhandle())
+ return mKHandle[subIndex];
+ }
+
+ return ret;
+}
+
+bool TngGrallocBufferMapper::mapKhandle()
+{
+ // TODO: this is a complete hack and temporary workaround
+ // need support from DDK to map khandle
+ void *wsbmBufferObject = 0;
+ int ret = psbWsbmWrapTTMBuffer2(mHandle, &wsbmBufferObject);
+ if (ret != 0) {
+ ELOGTRACE("Wrap ttm buffer failed!");
+ return false;
+ }
+
+ ret = psbWsbmCreateFromUB(wsbmBufferObject, mWidth * mHeight, mCpuAddress[0]);
+ if (ret != 0) {
+ ELOGTRACE("Create from UB failed!");
+ return false;
+ }
+
+ mKHandle[0] = psbWsbmGetKBufHandle(wsbmBufferObject);
+ psbWsbmUnReference(wsbmBufferObject);
+ return true;
+}
+
+uint32_t TngGrallocBufferMapper::getFbHandle(int subIndex)
+{
+ void *vaddr[SUB_BUFFER_MAX];
+ uint32_t size[SUB_BUFFER_MAX];
+ int err;
+
+ CTRACE();
+
+ if (subIndex < 0 || subIndex >= SUB_BUFFER_MAX) {
+ return 0;
+ }
+
+ // get virtual address
+ err = mIMGGrallocModule.getCpuAddress(&mIMGGrallocModule,
+ (buffer_handle_t)getHandle(),
+ vaddr,
+ size);
+ if (err) {
+ ELOGTRACE("failed to map. err = %d", err);
+ return 0;
+ }
+
+ return (uint32_t)vaddr[subIndex];
+}
+
+void TngGrallocBufferMapper::putFbHandle()
+{
+ int err = mIMGGrallocModule.putCpuAddress(&mIMGGrallocModule,
+ (buffer_handle_t)getHandle());
+ if (err) {
+ ELOGTRACE("failed to unmap. err = %d", err);
+ }
+ return;
+
+}
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/ips/tangier/TngGrallocBufferMapper.h b/moorefield_hdmi/ips/tangier/TngGrallocBufferMapper.h
new file mode 100644
index 0000000..87a16e5
--- /dev/null
+++ b/moorefield_hdmi/ips/tangier/TngGrallocBufferMapper.h
@@ -0,0 +1,50 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#ifndef TNG_GRALLOC_BUFFER_MAPPER_H
+#define TNG_GRALLOC_BUFFER_MAPPER_H
+
+#include <BufferMapper.h>
+#include <ips/common/GrallocBufferMapperBase.h>
+#include <ips/tangier/TngGrallocBuffer.h>
+
+namespace android {
+namespace intel {
+
+class TngGrallocBufferMapper : public GrallocBufferMapperBase {
+public:
+ TngGrallocBufferMapper(IMG_gralloc_module_public_t& module,
+ DataBuffer& buffer);
+ virtual ~TngGrallocBufferMapper();
+public:
+ bool map();
+ bool unmap();
+ uint32_t getKHandle(int subIndex);
+ uint32_t getFbHandle(int subIndex);
+ void putFbHandle();
+private:
+ bool gttMap(void *vaddr, uint32_t size, uint32_t gttAlign, int *offset);
+ bool gttUnmap(void *vaddr);
+ bool mapKhandle();
+
+private:
+ IMG_gralloc_module_public_t& mIMGGrallocModule;
+ void* mBufferObject;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* TNG_GRALLOC_BUFFER_MAPPER_H */