summaryrefslogtreecommitdiff
path: root/merrifield/ips
diff options
context:
space:
mode:
Diffstat (limited to 'merrifield/ips')
-rw-r--r--merrifield/ips/anniedale/AnnCursorPlane.cpp223
-rw-r--r--merrifield/ips/anniedale/AnnCursorPlane.h59
-rw-r--r--merrifield/ips/anniedale/AnnOverlayPlane.cpp834
-rw-r--r--merrifield/ips/anniedale/AnnOverlayPlane.h78
-rw-r--r--merrifield/ips/anniedale/AnnPlaneManager.cpp461
-rw-r--r--merrifield/ips/anniedale/AnnPlaneManager.h48
-rw-r--r--merrifield/ips/anniedale/AnnRGBPlane.cpp335
-rw-r--r--merrifield/ips/anniedale/AnnRGBPlane.h57
-rw-r--r--merrifield/ips/anniedale/PlaneCapabilities.cpp280
-rw-r--r--merrifield/ips/common/BlankControl.cpp43
-rw-r--r--merrifield/ips/common/BlankControl.h36
-rw-r--r--merrifield/ips/common/DrmConfig.cpp90
-rw-r--r--merrifield/ips/common/DrmControl.cpp58
-rw-r--r--merrifield/ips/common/DrmControl.h38
-rw-r--r--merrifield/ips/common/GrallocBufferBase.cpp91
-rw-r--r--merrifield/ips/common/GrallocBufferBase.h45
-rw-r--r--merrifield/ips/common/GrallocBufferMapperBase.cpp72
-rw-r--r--merrifield/ips/common/GrallocBufferMapperBase.h52
-rw-r--r--merrifield/ips/common/GrallocSubBuffer.h35
-rw-r--r--merrifield/ips/common/HdcpControl.cpp380
-rw-r--r--merrifield/ips/common/HdcpControl.h87
-rw-r--r--merrifield/ips/common/OverlayHardware.h160
-rw-r--r--merrifield/ips/common/OverlayPlaneBase.cpp1310
-rw-r--r--merrifield/ips/common/OverlayPlaneBase.h129
-rw-r--r--merrifield/ips/common/PixelFormat.cpp55
-rw-r--r--merrifield/ips/common/PixelFormat.h41
-rw-r--r--merrifield/ips/common/PlaneCapabilities.cpp234
-rw-r--r--merrifield/ips/common/PrepareListener.cpp50
-rw-r--r--merrifield/ips/common/PrepareListener.h35
-rw-r--r--merrifield/ips/common/RotationBufferProvider.cpp637
-rw-r--r--merrifield/ips/common/RotationBufferProvider.h102
-rw-r--r--merrifield/ips/common/SpritePlaneBase.cpp53
-rw-r--r--merrifield/ips/common/SpritePlaneBase.h52
-rw-r--r--merrifield/ips/common/TTMBufferMapper.cpp103
-rw-r--r--merrifield/ips/common/TTMBufferMapper.h70
-rw-r--r--merrifield/ips/common/VideoPayloadBuffer.h87
-rw-r--r--merrifield/ips/common/VideoPayloadManager.cpp123
-rw-r--r--merrifield/ips/common/VideoPayloadManager.h42
-rw-r--r--merrifield/ips/common/VsyncControl.cpp84
-rw-r--r--merrifield/ips/common/VsyncControl.h43
-rw-r--r--merrifield/ips/common/Wsbm.cpp136
-rw-r--r--merrifield/ips/common/Wsbm.h47
-rw-r--r--merrifield/ips/common/WsbmWrapper.c401
-rw-r--r--merrifield/ips/common/WsbmWrapper.h41
-rw-r--r--merrifield/ips/penwell/PnwGrallocBuffer.cpp46
-rw-r--r--merrifield/ips/penwell/PnwGrallocBuffer.h46
-rw-r--r--merrifield/ips/penwell/PnwGrallocBufferMapper.cpp48
-rw-r--r--merrifield/ips/penwell/PnwGrallocBufferMapper.h38
-rw-r--r--merrifield/ips/penwell/PnwOverlayPlane.cpp51
-rw-r--r--merrifield/ips/penwell/PnwOverlayPlane.h42
-rw-r--r--merrifield/ips/penwell/PnwPrimaryPlane.cpp65
-rw-r--r--merrifield/ips/penwell/PnwPrimaryPlane.h38
-rw-r--r--merrifield/ips/penwell/PnwSpritePlane.cpp50
-rw-r--r--merrifield/ips/penwell/PnwSpritePlane.h42
-rw-r--r--merrifield/ips/tangier/TngCursorPlane.cpp244
-rw-r--r--merrifield/ips/tangier/TngCursorPlane.h58
-rw-r--r--merrifield/ips/tangier/TngDisplayContext.cpp278
-rw-r--r--merrifield/ips/tangier/TngDisplayContext.h51
-rw-r--r--merrifield/ips/tangier/TngDisplayQuery.cpp63
-rw-r--r--merrifield/ips/tangier/TngGrallocBuffer.cpp62
-rw-r--r--merrifield/ips/tangier/TngGrallocBuffer.h44
-rw-r--r--merrifield/ips/tangier/TngGrallocBufferMapper.cpp263
-rw-r--r--merrifield/ips/tangier/TngGrallocBufferMapper.h52
-rw-r--r--merrifield/ips/tangier/TngOverlayPlane.cpp218
-rw-r--r--merrifield/ips/tangier/TngOverlayPlane.h55
-rw-r--r--merrifield/ips/tangier/TngPlaneManager.cpp196
-rw-r--r--merrifield/ips/tangier/TngPlaneManager.h50
-rw-r--r--merrifield/ips/tangier/TngPrimaryPlane.cpp167
-rw-r--r--merrifield/ips/tangier/TngPrimaryPlane.h40
-rw-r--r--merrifield/ips/tangier/TngSpritePlane.cpp215
-rw-r--r--merrifield/ips/tangier/TngSpritePlane.h48
71 files changed, 10007 insertions, 0 deletions
diff --git a/merrifield/ips/anniedale/AnnCursorPlane.cpp b/merrifield/ips/anniedale/AnnCursorPlane.cpp
new file mode 100644
index 0000000..c6607dd
--- /dev/null
+++ b/merrifield/ips/anniedale/AnnCursorPlane.cpp
@@ -0,0 +1,223 @@
+/*
+// 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 <HwcTrace.h>
+#include <Hwcomposer.h>
+#include <BufferManager.h>
+#include <anniedale/AnnCursorPlane.h>
+#include <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(buffer_handle_t handle)
+{
+ bool ret;
+
+ if (!handle) {
+ ETRACE("handle is NULL");
+ return false;
+ }
+
+ ret = DisplayPlane::setDataBuffer(handle);
+ if (ret == false) {
+ ETRACE("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;
+
+ 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 {
+ ETRACE("invalid color format");
+ return false;
+ }
+
+ // 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) {
+ WTRACE("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) {
+ WTRACE("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/merrifield/ips/anniedale/AnnCursorPlane.h b/merrifield/ips/anniedale/AnnCursorPlane.h
new file mode 100644
index 0000000..88d8075
--- /dev/null
+++ b/merrifield/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 <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(buffer_handle_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_CUR_PLANE_H */
diff --git a/merrifield/ips/anniedale/AnnOverlayPlane.cpp b/merrifield/ips/anniedale/AnnOverlayPlane.cpp
new file mode 100644
index 0000000..930f895
--- /dev/null
+++ b/merrifield/ips/anniedale/AnnOverlayPlane.cpp
@@ -0,0 +1,834 @@
+/*
+// 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 <HwcTrace.h>
+#include <Drm.h>
+#include <Hwcomposer.h>
+#include <anniedale/AnnOverlayPlane.h>
+#include <tangier/TngGrallocBuffer.h>
+
+// FIXME: remove it
+#include <OMX_IVCommon.h>
+#include <OMX_IntelVideoExt.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();
+}
+
+void AnnOverlayPlane::setZOrderConfig(ZOrderConfig& zorderConfig,
+ void *nativeConfig)
+{
+ long slot = (long)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:
+ ETRACE("Invalid overlay plane zorder %ld", slot);
+ return;
+ }
+}
+
+bool AnnOverlayPlane::reset()
+{
+ 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) {
+ ETRACE("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;
+ 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:
+ ETRACE("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;
+
+ VTRACE("done. offset (%d, %d, %d)",
+ backBuffer->OBUF_0Y,
+ backBuffer->OBUF_0U,
+ backBuffer->OBUF_0V);
+
+ 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) {
+ ETRACE("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);
+ VTRACE("final position (%d, %d, %d, %d)", x, y, w, h);
+
+ if ((w <= 0) || (h <= 0)) {
+ ETRACE("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;
+
+ if (mBobDeinterlace && !mTransform)
+ deinterlace_factor = 2;
+
+ VTRACE("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) {
+ ETRACE("xscaleInt > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
+ return false;
+ }
+
+ // shouldn't get here
+ if (xscaleIntUV > INTEL_OVERLAY_MAX_SCALING_RATIO) {
+ ETRACE("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);
+ }
+ }
+ }
+
+ XTRACE();
+ 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:
+ ETRACE("Invalid transform %d", mTransform);
+ mRotationConfig = 0;
+ break;
+ }
+}
+
+// HSD 4645510:
+// This is a SOC limition, that when source buffer width range is
+// in (960, 1024] - one cache line length, and rotation bit is set
+// in portrait mode, video will show distortion.
+bool AnnOverlayPlane::isSettingRotBitAllowed()
+{
+ uint32_t width = mSrcCrop.w;
+
+ if ((width > 960 && width <= 1024) &&
+ (mTransform == 0 || mTransform == HAL_TRANSFORM_ROT_180))
+ return false;
+ return true;
+}
+
+bool AnnOverlayPlane::flip(void *ctx)
+{
+ uint32_t ovadd = 0;
+
+ RETURN_FALSE_IF_NOT_INIT();
+
+ if (!DisplayPlane::flip(ctx)) {
+ ETRACE("failed to flip display plane.");
+ return false;
+ }
+
+ // update back buffer address
+ ovadd = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
+
+ // enable rotation mode and setup rotation config
+ // if video is interlaced, cannot use overlay rotation
+ if (mIndex == 0 && !mBobDeinterlace) {
+ if (isSettingRotBitAllowed())
+ 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;
+
+ VTRACE("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 (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;
+ }
+
+ mContext.gtt_key = (unsigned long)mapper.getCpuAddress(0);
+
+ return true;
+}
+
+bool AnnOverlayPlane::initialize(uint32_t bufferCount)
+{
+ if (!OverlayPlaneBase::initialize(bufferCount)) {
+ ETRACE("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) {
+ ETRACE("invalid video format %#x", format);
+ return false;
+ }
+
+ payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
+ // check payload
+ if (!payload) {
+ ETRACE("no payload found");
+ return false;
+ }
+
+ if (payload->force_output_method == FORCE_OUTPUT_GPU) {
+ ETRACE("Output method is not supported!");
+ return false;
+ }
+
+ if (payload->client_transform != mTransform ||
+ mBobDeinterlace) {
+ if (!mRotationBufProvider->setupRotationBuffer(payload, mTransform)) {
+ DTRACE("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) {
+ ETRACE("no payload found");
+ return;
+ }
+
+ /* if use overlay rotation, signal decoder to stop rotation */
+ if (mUseOverlayRotation) {
+ if (payload->client_transform) {
+ WTRACE("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) {
+ WTRACE("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;
+
+ if (!isSettingRotBitAllowed()) {
+ mUseOverlayRotation = false;
+ mRotationConfig = 0;
+ return false;
+ }
+
+ // 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) {
+ if (mUseOverlayRotation) {
+ DTRACE("overlay rotation with scaling >= 3, use VA rotated buffer");
+ }
+ fallback = true;
+ } else if ((int)mSrcCrop.x & 63) {
+ if (mUseOverlayRotation) {
+ DTRACE("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) {
+ DTRACE("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) {
+ DTRACE("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::scaledBufferReady(BufferMapper& mapper, BufferMapper* &scaledMapper, VideoPayloadBuffer *payload)
+{
+ mUseScaledBuffer = (payload->scaling_khandle != 0);
+
+ if (mUseScaledBuffer) {
+ mapper.setCrop(mapper.getCrop().x, mapper.getCrop().y, payload->scaling_width, payload->scaling_height);
+ scaledMapper = getTTMMapper(mapper, payload);
+ return (scaledMapper != 0);
+ }
+
+ return mUseScaledBuffer;
+}
+
+bool AnnOverlayPlane::flush(uint32_t flags)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+ ATRACE("flags = %#x, type = %d, index = %d", flags, mType, mIndex);
+
+ if (!(flags & PLANE_ENABLE) && !(flags & PLANE_DISABLE)) {
+ ETRACE("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) {
+ DTRACE("disabling overlay %d on device %d", mIndex, mDevice);
+ }
+
+ // issue ioctl
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
+ if (ret == false) {
+ WTRACE("overlay update failed with error code %d", ret);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/anniedale/AnnOverlayPlane.h b/merrifield/ips/anniedale/AnnOverlayPlane.h
new file mode 100644
index 0000000..3cea338
--- /dev/null
+++ b/merrifield/ips/anniedale/AnnOverlayPlane.h
@@ -0,0 +1,78 @@
+/*
+// 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 <common/Wsbm.h>
+#include <common/OverlayPlaneBase.h>
+#include <common/RotationBufferProvider.h>
+
+namespace android {
+namespace intel {
+
+class AnnOverlayPlane : public OverlayPlaneBase {
+public:
+ AnnOverlayPlane(int index, int disp);
+ virtual ~AnnOverlayPlane();
+
+ 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);
+ virtual bool scaledBufferReady(BufferMapper& mapper, BufferMapper* &scaledMapper, VideoPayloadBuffer *payload);
+
+private:
+ void signalVideoRotation(BufferMapper& mapper);
+ bool isSettingRotBitAllowed();
+
+protected:
+ virtual bool setDataBuffer(BufferMapper& mapper);
+ virtual bool flush(uint32_t flags);
+ virtual bool bufferOffsetSetup(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;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* ANN_OVERLAY_PLANE_H */
+
diff --git a/merrifield/ips/anniedale/AnnPlaneManager.cpp b/merrifield/ips/anniedale/AnnPlaneManager.cpp
new file mode 100644
index 0000000..b20f851
--- /dev/null
+++ b/merrifield/ips/anniedale/AnnPlaneManager.cpp
@@ -0,0 +1,461 @@
+/*
+// 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 <HwcTrace.h>
+#include <utils/String8.h>
+#include <anniedale/AnnPlaneManager.h>
+#include <anniedale/AnnRGBPlane.h>
+#include <anniedale/AnnOverlayPlane.h>
+#include <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
+// Cursor plane can be placed on top of any plane below and is intentionally ignored
+// in the zorder table.
+
+// video mode panel doesn't need the primay plane A always on hack
+static ZOrderDescription PIPE_A_ZORDER_DESC_VID[] =
+{
+ {0, "ADEF"}, // no overlay
+ {1, "GDEF"}, // overlay A at bottom (1 << 0)
+ {1, "HDEF"}, // overlay C at bottom (1 << 0)
+ {2, "AGEF"}, // overlay A at next to bottom (1 << 1)
+ {2, "AHEF"}, // overlay C at next to bottom (1 << 1)
+ {3, "GHEF"}, // overlay A, C at bottom
+ {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
+};
+
+static ZOrderDescription PIPE_A_ZORDER_DESC_CMD[] =
+{
+ {0, "ADEF"}, // no overlay
+ {1, "GEF"}, // overlay A at bottom (1 << 0)
+ {1, "HEF"}, // overlay C at bottom (1 << 0)
+ {2, "AGEF"}, // overlay A at next to bottom (1 << 1)
+ {2, "AHEF"}, // overlay C at next to bottom (1 << 1)
+ {3, "GHF"}, // overlay A, C at bottom
+ {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
+static ZOrderDescription PIPE_B_ZORDER_DESC[] =
+{
+ {0, "BD"}, // no overlay
+ {1, "HBD"}, // overlay C at bottom (1 << 0)
+// {1, "GBD"}, // overlay A at bottom (1 << 0), overlay A don`t switch to pipeB and only overlay C on pipeB
+ {2, "BHD"}, // overlay C at middle (1 << 1)
+// {2, "BGD"}, // overlay A at middle (1 << 1), overlay A don`t switch to pipeB and only overaly C on pipeB
+ {3, "GHBD"}, // overlay A and C at bottom ( 1 << 0 + 1 << 1)
+ {4, "BDH"}, // overlay C at top (1 << 2)
+ {4, "BDG"}, // overlay A 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 ZOrderDescription *PIPE_A_ZORDER_TBL;
+static int PIPE_A_ZORDER_COMBINATIONS;
+static ZOrderDescription *PIPE_B_ZORDER_TBL;
+static int PIPE_B_ZORDER_COMBINATIONS;
+static bool OVERLAY_HW_WORKAROUND;
+
+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;
+
+ uint32_t videoMode = 0;
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ drm->readIoctl(DRM_PSB_PANEL_QUERY, &videoMode, sizeof(uint32_t));
+ if (videoMode == 1) {
+ DTRACE("video mode panel, no primay A always on hack");
+ PIPE_A_ZORDER_TBL = PIPE_A_ZORDER_DESC_VID;
+ PIPE_A_ZORDER_COMBINATIONS =
+ sizeof(PIPE_A_ZORDER_DESC_VID)/sizeof(ZOrderDescription);
+ } else {
+ DTRACE("command mode panel, need primay A always on hack");
+ PIPE_A_ZORDER_TBL = PIPE_A_ZORDER_DESC_CMD;
+ PIPE_A_ZORDER_COMBINATIONS =
+ sizeof(PIPE_A_ZORDER_DESC_CMD)/sizeof(ZOrderDescription);
+ OVERLAY_HW_WORKAROUND = true;
+ }
+
+ PIPE_B_ZORDER_TBL = PIPE_B_ZORDER_DESC;
+ PIPE_B_ZORDER_COMBINATIONS =
+ sizeof(PIPE_B_ZORDER_DESC)/sizeof(ZOrderDescription);
+
+ 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:
+ ETRACE("unsupported type %d", type);
+ break;
+ }
+
+ if (plane && !plane->initialize(DisplayPlane::MIN_DATA_BUFFER_COUNT)) {
+ ETRACE("failed to initialize plane.");
+ DEINIT_AND_DELETE_OBJ(plane);
+ }
+
+ return plane;
+}
+
+bool AnnPlaneManager::isValidZOrder(int dsp, ZOrderConfig& config)
+{
+ int size = (int)config.size();
+ bool hasCursor = false;
+
+ for (int i = 0; i < size; i++) {
+ if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
+ hasCursor = true;
+ break;
+ }
+ }
+
+ if (size <= 0 ||
+ (hasCursor && size > 5) ||
+ (!hasCursor && size > 4)) {
+ VTRACE("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) {
+ VTRACE("not capable to support more than 4 sprite layers");
+ return false;
+ }
+
+ if (OVERLAY_HW_WORKAROUND) {
+ if (firstOverlay == 0 && size > 2) {
+ VTRACE("can not support 3 sprite layers on top of overlay");
+ return false;
+ }
+ }
+ } 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) {
+ ETRACE("number of sprite: %d, maximum 1 sprite and 1 primary supported on pipe 1", sprites);
+ return false;
+ }
+ } else {
+ ETRACE("invalid display device %d", dsp);
+ return false;
+ }
+ return true;
+}
+
+bool AnnPlaneManager::assignPlanes(int dsp, ZOrderConfig& config)
+{
+ if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
+ ETRACE("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;
+ ZOrderDescription *table;
+ if (dsp == IDisplayDevice::DEVICE_PRIMARY) {
+ combinations = PIPE_A_ZORDER_COMBINATIONS;
+ table = PIPE_A_ZORDER_TBL;
+ } else {
+ combinations = PIPE_B_ZORDER_COMBINATIONS;
+ table = PIPE_B_ZORDER_TBL;
+ }
+
+ for (int i = 0; i < combinations; i++) {
+ ZOrderDescription *zorderDesc = table + i;
+
+ if (zorderDesc->index != index)
+ continue;
+
+ if (assignPlanes(dsp, config, zorderDesc->zorder)) {
+ VTRACE("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) {
+ //DTRACE("invalid zorder or ZOrder config.");
+ return false;
+ }
+
+ int zorderLen = (int)strlen(zorder);
+
+ // test if plane is avalable
+ for (int i = 0; i < size; i++) {
+ if (config[i]->planeType == DisplayPlane::PLANE_CURSOR) {
+ if (i != size - 1) {
+ ETRACE("invalid zorder of cursor layer");
+ return false;
+ }
+ PlaneDescription& desc = PLANE_DESC['I' - 'A' + dsp];
+ if (!isFreePlane(desc.type, desc.index)) {
+ ETRACE("cursor plane is not available");
+ return false;
+ }
+ continue;
+ }
+ if (i >= zorderLen) {
+ DTRACE("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)) {
+ DTRACE("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) {
+ ETRACE("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) {
+ ETRACE("invalid plane type %d,", config[i]->planeType);
+ return false;
+ }
+ if (desc.type != DisplayPlane::PLANE_PRIMARY &&
+ desc.type != DisplayPlane::PLANE_SPRITE) {
+ ETRACE("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) {
+ DTRACE("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) {
+ ETRACE("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) {
+ ETRACE("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;
+
+ if (OVERLAY_HW_WORKAROUND) {
+ if (!primaryPlaneActive &&
+ config[i]->planeType == DisplayPlane::PLANE_OVERLAY) {
+ slot += 1;
+ }
+ }
+
+ config[i]->plane->setZOrderConfig(config, (void *)(unsigned long)slot);
+ config[i]->plane->enable();
+ }
+
+#if 0
+ DTRACE("config size %d, zorder %s", size, zorder);
+ for (int i = 0; i < size; i++) {
+ const ZOrderLayer *l = config.itemAt(i);
+ ITRACE("%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) {
+ ETRACE("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/merrifield/ips/anniedale/AnnPlaneManager.h b/merrifield/ips/anniedale/AnnPlaneManager.h
new file mode 100644
index 0000000..5a7971e
--- /dev/null
+++ b/merrifield/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/merrifield/ips/anniedale/AnnRGBPlane.cpp b/merrifield/ips/anniedale/AnnRGBPlane.cpp
new file mode 100644
index 0000000..dfc4b8c
--- /dev/null
+++ b/merrifield/ips/anniedale/AnnRGBPlane.cpp
@@ -0,0 +1,335 @@
+/*
+// 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 <HwcTrace.h>
+#include <Hwcomposer.h>
+#include <BufferManager.h>
+#include <anniedale/AnnRGBPlane.h>
+#include <tangier/TngGrallocBuffer.h>
+#include <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);
+}
+
+void* AnnRGBPlane::getContext() const
+{
+ CTRACE();
+ return (void *)&mContext;
+}
+
+void AnnRGBPlane::setZOrderConfig(ZOrderConfig& config, void *nativeConfig)
+{
+ CTRACE();
+}
+
+bool AnnRGBPlane::setDataBuffer(buffer_handle_t handle)
+{
+ if (!handle) {
+ setFramebufferTarget(handle);
+ return true;
+ }
+
+ TngGrallocBuffer tmpBuf(handle);
+ uint32_t usage;
+ bool ret;
+
+ ATRACE("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) {
+ ETRACE("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)) {
+ ETRACE("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())) {
+ ETRACE("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;
+ mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0);
+
+ 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;
+
+ VTRACE("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) {
+ WTRACE("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) {
+ WTRACE("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(buffer_handle_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);
+
+ VTRACE("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/merrifield/ips/anniedale/AnnRGBPlane.h b/merrifield/ips/anniedale/AnnRGBPlane.h
new file mode 100644
index 0000000..d1a9e60
--- /dev/null
+++ b/merrifield/ips/anniedale/AnnRGBPlane.h
@@ -0,0 +1,57 @@
+/*
+// 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 <hal_public.h>
+#include <Hwcomposer.h>
+#include <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 isDisabled();
+ void postFlip();
+
+ void* getContext() const;
+ void setZOrderConfig(ZOrderConfig& config, void *nativeConfig);
+
+ bool setDataBuffer(buffer_handle_t handle);
+protected:
+ bool setDataBuffer(BufferMapper& mapper);
+ bool enablePlane(bool enabled);
+private:
+ void setFramebufferTarget(buffer_handle_t handle);
+protected:
+ struct intel_dc_plane_ctx mContext;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* ANN_RGB_PLANE_H */
diff --git a/merrifield/ips/anniedale/PlaneCapabilities.cpp b/merrifield/ips/anniedale/PlaneCapabilities.cpp
new file mode 100644
index 0000000..853511b
--- /dev/null
+++ b/merrifield/ips/anniedale/PlaneCapabilities.cpp
@@ -0,0 +1,280 @@
+/*
+// 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 <HwcTrace.h>
+#include <DisplayPlane.h>
+#include <hal_public.h>
+#include <OMX_IVCommon.h>
+#include <OMX_IntelVideoExt.h>
+#include <PlaneCapabilities.h>
+#include <common/OverlayHardware.h>
+#include <HwcLayer.h>
+#include <BufferManager.h>
+#include <Hwcomposer.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:
+ VTRACE("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) {
+ WTRACE("180 degree rotation is not supported yet");
+ }
+ return trans ? false : true;
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_NV12:
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar:
+ case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled:
+ return true;
+ default:
+ VTRACE("unsupported format %#x", format);
+ return false;
+ }
+ } else {
+ ETRACE("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:
+ VTRACE("stride %d", stride.rgb.stride);
+ if (stride.rgb.stride > SPRITE_PLANE_MAX_STRIDE_LINEAR) {
+ VTRACE("too large stride %d", stride.rgb.stride);
+ return false;
+ }
+ return true;
+ default:
+ VTRACE("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:
+ VTRACE("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) {
+ VTRACE("stride %d is too large", stride.yuv.yStride);
+ return false;
+ }
+
+ hwc_frect_t& srcCrop = hwcLayer->getLayer()->sourceCropf;
+ uint32_t width = srcCrop.right - srcCrop.left;
+ uint32_t height = srcCrop.bottom - srcCrop.top;
+
+ if (width <= 64 || height <= 64) {
+ DTRACE("width or height of source crop is less than 64, fallback to GLES");
+ return false;
+ }
+
+ if ((height & 0x1) || (width & 0x1)){
+ if (!hwcLayer->isProtected()) {
+ DTRACE("unprotected video content, height or width of source crop is not even, fallback to GLES ");
+ return false;
+ }
+ }
+
+ return true;
+ } else {
+ ETRACE("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:
+ VTRACE("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 {
+ ETRACE("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)) {
+ uint32_t format = hwcLayer->getFormat();
+ if (format == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar ||
+ format == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
+ // will fall back to GLES if no scaling buffer provided by ved later
+ // so don't return false and print a warning, it's for video format only.
+ WTRACE("source size %dx%d hit overlay resolution limitation.", srcW, srcH);
+ } else {
+ return false;
+ }
+ }
+
+ if (dstW <= 100 || dstH <= 1 || srcW <= 100 || srcH <= 1) {
+ // Workaround: Overlay flip when height is 1 causes MIPI stall on TNG
+ DTRACE("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) {
+ DTRACE("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 >= 3 || scaleY >= 3) {
+ DTRACE("overlay rotation with scaling >= 3, fall back to GLES");
+ return false;
+ }
+#if 0
+ if (trans == HAL_TRANSFORM_ROT_90 && (float)srcW / srcH != (float)dstW / dstH) {
+ // FIXME: work aournd for pipe crashing issue, when rotate screen
+ // from 90 to 0 degree (with Sharp 25x16 panel).
+ DTRACE("overlay rotation with uneven scaling, fall back to GLES");
+ return false;
+ }
+#endif
+ }
+
+ return true;
+ } else {
+ ETRACE("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/merrifield/ips/common/BlankControl.cpp b/merrifield/ips/common/BlankControl.cpp
new file mode 100644
index 0000000..3ac0736
--- /dev/null
+++ b/merrifield/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 <HwcTrace.h>
+#include <Drm.h>
+#include <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
+ VTRACE("blank is not supported yet, disp %d, blank %d", disp, blank);
+ return true;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/common/BlankControl.h b/merrifield/ips/common/BlankControl.h
new file mode 100644
index 0000000..1c0de05
--- /dev/null
+++ b/merrifield/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/merrifield/ips/common/DrmConfig.cpp b/merrifield/ips/common/DrmConfig.cpp
new file mode 100644
index 0000000..59b1c72
--- /dev/null
+++ b/merrifield/ips/common/DrmConfig.cpp
@@ -0,0 +1,90 @@
+/*
+// 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 <HwcTrace.h>
+#include <IDisplayDevice.h>
+#include <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";
+}
+
+uint32_t DrmConfig::convertHalFormatToDrmFormat(uint32_t halFormat)
+{
+ switch (halFormat) {
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return DRM_FORMAT_XRGB8888;
+ default:
+ ETRACE("format %#x isn't supported by drm", halFormat);
+ return 0;
+ }
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/common/DrmControl.cpp b/merrifield/ips/common/DrmControl.cpp
new file mode 100644
index 0000000..9c34658
--- /dev/null
+++ b/merrifield/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 <HwcTrace.h>
+#include <linux/psb_drm.h>
+#include <Hwcomposer.h>
+#include <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) {
+ VTRACE("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/merrifield/ips/common/DrmControl.h b/merrifield/ips/common/DrmControl.h
new file mode 100644
index 0000000..fbd0284
--- /dev/null
+++ b/merrifield/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/merrifield/ips/common/GrallocBufferBase.cpp b/merrifield/ips/common/GrallocBufferBase.cpp
new file mode 100644
index 0000000..e50b777
--- /dev/null
+++ b/merrifield/ips/common/GrallocBufferBase.cpp
@@ -0,0 +1,91 @@
+/*
+// 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 <HwcTrace.h>
+#include <common/GrallocBufferBase.h>
+#include <DisplayQuery.h>
+
+
+namespace android {
+namespace intel {
+
+GrallocBufferBase::GrallocBufferBase(buffer_handle_t handle)
+ : GraphicBuffer(handle)
+{
+ ATRACE("handle = %#x", handle);
+ initBuffer(handle);
+}
+
+void GrallocBufferBase::resetBuffer(buffer_handle_t handle)
+{
+ GraphicBuffer::resetBuffer(handle);
+ initBuffer(handle);
+}
+
+void GrallocBufferBase::initBuffer(buffer_handle_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/merrifield/ips/common/GrallocBufferBase.h b/merrifield/ips/common/GrallocBufferBase.h
new file mode 100644
index 0000000..5ae8c95
--- /dev/null
+++ b/merrifield/ips/common/GrallocBufferBase.h
@@ -0,0 +1,45 @@
+/*
+// 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>
+#include <hal_public.h>
+// FIXME: remove it, why define NV12_VED based on OMX's value?
+#include <OMX_IVCommon.h>
+#include <OMX_IntelVideoExt.h>
+
+namespace android {
+namespace intel {
+
+class GrallocBufferBase : public GraphicBuffer {
+public:
+ GrallocBufferBase(buffer_handle_t handle);
+ virtual ~GrallocBufferBase() {}
+ virtual void resetBuffer(buffer_handle_t handle);
+
+protected:
+ // helper function to be invoked by the derived class
+ void initStride();
+
+private:
+ void initBuffer(buffer_handle_t handle);
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* GRALLOC_BUFFER_BASE_H */
diff --git a/merrifield/ips/common/GrallocBufferMapperBase.cpp b/merrifield/ips/common/GrallocBufferMapperBase.cpp
new file mode 100644
index 0000000..ac236e3
--- /dev/null
+++ b/merrifield/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 <HwcTrace.h>
+#include <Drm.h>
+#include <Hwcomposer.h>
+#include <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;
+}
+
+buffer_handle_t GrallocBufferMapperBase::getKHandle(int subIndex)
+{
+ if (subIndex >= 0 && subIndex < SUB_BUFFER_MAX)
+ return mKHandle[subIndex];
+ return 0;
+}
+
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/common/GrallocBufferMapperBase.h b/merrifield/ips/common/GrallocBufferMapperBase.h
new file mode 100644
index 0000000..fed0d8e
--- /dev/null
+++ b/merrifield/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 <common/GrallocSubBuffer.h>
+#include <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 buffer_handle_t getKHandle(int subIndex);
+ virtual buffer_handle_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];
+ buffer_handle_t mKHandle[SUB_BUFFER_MAX];
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* TNG_GRALLOC_BUFFER_MAPPER_H */
diff --git a/merrifield/ips/common/GrallocSubBuffer.h b/merrifield/ips/common/GrallocSubBuffer.h
new file mode 100644
index 0000000..15170f2
--- /dev/null
+++ b/merrifield/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/merrifield/ips/common/HdcpControl.cpp b/merrifield/ips/common/HdcpControl.cpp
new file mode 100644
index 0000000..620d28f
--- /dev/null
+++ b/merrifield/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 <HwcTrace.h>
+#include <DrmConfig.h>
+#include <Hwcomposer.h>
+#include <DisplayQuery.h>
+#include <common/DrmControl.h>
+#include <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) {
+ WTRACE("HDCP is disabled");
+ return false;
+ }
+ }
+
+ if (!mStopped) {
+ WTRACE("HDCP has been started");
+ return true;
+ }
+
+ mStopped = false;
+ mAuthenticated = false;
+ mWaitForCompletion = false;
+
+ mThread = new HdcpControlThread(this);
+ if (!mThread.get()) {
+ ETRACE("failed to create hdcp control thread");
+ return false;
+ }
+
+ if (!runHdcp()) {
+ ETRACE("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) {
+ WTRACE("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) {
+ WTRACE("HDCP is disabled");
+ return false;
+ }
+ }
+
+ if (cb == NULL || userData == NULL) {
+ ETRACE("invalid callback or user data");
+ return false;
+ }
+
+ Mutex::Autolock lock(mMutex);
+
+ if (!mStopped) {
+ WTRACE("HDCP has been started");
+ return true;
+ }
+
+ mThread = new HdcpControlThread(this);
+ if (!mThread.get()) {
+ ETRACE("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) {
+ ETRACE("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) {
+ ETRACE("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) {
+ ETRACE("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) {
+ ETRACE("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) {
+ ETRACE("failed to query HDCP capability");
+ return false;
+ }
+ if (caps == 0) {
+ WTRACE("HDCP is not supported");
+ return false;
+ } else {
+ ITRACE("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) {
+ ETRACE("failed to get hdcp link status");
+ return false;
+ }
+ if (match) {
+ VTRACE("HDCP is authenticated");
+ mAuthenticated = true;
+ } else {
+ ETRACE("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++) {
+ VTRACE("enable and verify HDCP, iteration# %d", i);
+ if (mStopped) {
+ WTRACE("HDCP authentication has been stopped");
+ ret = false;
+ break;
+ }
+
+ if (!enableAuthentication()) {
+ ETRACE("HDCP authentication failed. Retry");
+ mAuthenticated = false;
+ ret = true;
+ } else {
+ ITRACE("HDCP is authenticated");
+ mAuthenticated = true;
+ ret = true;
+ break;
+ }
+
+ if (mStopped) {
+ WTRACE("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) {
+ ITRACE("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) {
+ ITRACE("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/merrifield/ips/common/HdcpControl.h b/merrifield/ips/common/HdcpControl.h
new file mode 100644
index 0000000..5dc33c9
--- /dev/null
+++ b/merrifield/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 <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/merrifield/ips/common/OverlayHardware.h b/merrifield/ips/common/OverlayHardware.h
new file mode 100644
index 0000000..a06f304
--- /dev/null
+++ b/merrifield/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/merrifield/ips/common/OverlayPlaneBase.cpp b/merrifield/ips/common/OverlayPlaneBase.cpp
new file mode 100644
index 0000000..5987b50
--- /dev/null
+++ b/merrifield/ips/common/OverlayPlaneBase.cpp
@@ -0,0 +1,1310 @@
+/*
+// 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 <HwcTrace.h>
+#include <Drm.h>
+#include <Hwcomposer.h>
+#include <PhysicalDevice.h>
+#include <common/OverlayPlaneBase.h>
+#include <common/TTMBufferMapper.h>
+#include <common/GrallocSubBuffer.h>
+#include <DisplayQuery.h>
+
+
+// FIXME: remove it
+#include <OMX_IVCommon.h>
+#include <OMX_IntelVideoExt.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),
+ mUseScaledBuffer(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) {
+ ITRACE("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) {
+ WTRACE("overlay plane query failed with error code %d", ret);
+ return false;
+ }
+
+ DTRACE("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();
+ VTRACE("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) {
+ DTRACE("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) {
+ ETRACE("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) {
+ ETRACE("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 = wsbmBufferObject;
+
+ VTRACE("cpu %p, gtt %d", virtAddr, gttOffsetInPage);
+
+ return backBuffer;
+}
+
+void OverlayPlaneBase::deleteBackBuffer(int buf)
+{
+ if (!mBackBuffer[buf])
+ return;
+
+ void *wsbmBufferObject = mBackBuffer[buf]->bufObject;
+ bool ret = mWsbm->destroyTTMBuffer(wsbmBufferObject);
+ if (ret == false) {
+ WTRACE("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)
+{
+ buffer_handle_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) {
+ ETRACE("invalid payload buffer");
+ return 0;
+ }
+
+ srcX = grallocMapper.getCrop().x;
+ srcY = grallocMapper.getCrop().y;
+ srcW = grallocMapper.getCrop().w;
+ srcH = grallocMapper.getCrop().h;
+
+ // init ttm buffer
+ if (mUseScaledBuffer) {
+ khandle = payload->scaling_khandle;
+ } else {
+ khandle = payload->rotated_buffer_handle;
+ }
+ index = mTTMBuffers.indexOfKey(khandle);
+ if (index < 0) {
+ VTRACE("unmapped TTM buffer, will map it");
+
+ if (mUseScaledBuffer) {
+ w = payload->scaling_width;
+ h = payload->scaling_height;
+ } else {
+ 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:
+ if (mUseScaledBuffer) {
+ stride.yuv.yStride = payload->scaling_luma_stride;
+ stride.yuv.uvStride = payload->scaling_chroma_u_stride;
+ } else {
+ 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) {
+ ETRACE("failed to allocate mapper");
+ break;
+ }
+ // map ttm buffer
+ ret = mapper->map();
+ if (!ret) {
+ ETRACE("failed to map");
+ invalidateTTMBuffers();
+ ret = mapper->map();
+ if (!ret) {
+ ETRACE("failed to remap");
+ break;
+ }
+ }
+
+ if (mTTMBuffers.size() >= OVERLAY_DATA_BUFFER_COUNT) {
+ invalidateTTMBuffers();
+ }
+
+ // add mapper
+ index = mTTMBuffers.add(khandle, mapper);
+ if (index < 0) {
+ ETRACE("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 {
+ VTRACE("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) {
+ if(!mUseScaledBuffer)
+ checkCrop(srcX, srcY, srcW, srcH, payload->coded_width, payload->coded_height);
+ mapper->setCrop(srcX, srcY, srcW, srcH);
+ }
+ }
+
+ XTRACE();
+ 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) {
+ ETRACE("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;
+ }
+ WTRACE("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;
+}
+
+bool OverlayPlaneBase::scaledBufferReady(BufferMapper& mapper, BufferMapper* &scaledMapper, VideoPayloadBuffer *payload)
+{
+ 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) {
+ ETRACE("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:
+ ETRACE("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;
+
+ VTRACE("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)
+{
+ ATRACE("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) {
+ ETRACE("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:
+ ETRACE("unsupported format %d", format);
+ return false;
+ }
+
+ if (width <= 0 || height <= 0) {
+ ETRACE("invalid src dim");
+ return false;
+ }
+
+ if (yStride <=0 && uvStride <= 0) {
+ ETRACE("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);
+
+ XTRACE();
+
+ 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) {
+ ETRACE("invalid back buffer");
+ return false;
+ }
+
+ x = mPosition.x;
+ y = mPosition.y;
+ w = mPosition.w;
+ h = mPosition.h;
+
+ // check position
+ checkPosition(x, y, w, h);
+ VTRACE("final position (%d, %d, %d, %d)", x, y, w, h);
+
+ if ((w <= 0) || (h <= 0)) {
+ ETRACE("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;
+
+ if (mBobDeinterlace && !mTransform)
+ deinterlace_factor = 2;
+
+ VTRACE("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) {
+ ETRACE("xscaleInt > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
+ return false;
+ }
+
+ // shouldn't get here
+ if (xscaleIntUV > INTEL_OVERLAY_MAX_SCALING_RATIO) {
+ ETRACE("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);
+ }
+ }
+ }
+
+ XTRACE();
+ return true;
+}
+
+bool OverlayPlaneBase::colorSetup(BufferMapper& mapper)
+{
+ CTRACE();
+
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
+ if (!backBuffer) {
+ ETRACE("invalid back buffer");
+ return false;
+ }
+
+ uint32_t format = mapper.getFormat();
+ if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
+ format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
+
+ VTRACE("Not video layer, use default color setting");
+ backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) |
+ (OVERLAY_INIT_BRIGHTNESS & 0xff);
+ backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION;
+ backBuffer->OCONFIG &= ~(1 << 5);
+
+ return true;
+ }
+
+ struct VideoPayloadBuffer *payload;
+ payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
+ // check payload
+ if (!payload) {
+ ETRACE("no payload found");
+ return false;
+ }
+
+ // BT.601 or BT.709
+ backBuffer->OCONFIG &= ~(1 << 5);
+ backBuffer->OCONFIG |= ((payload->csc_mode & 1) << 5);
+
+ // no level expansion for video on HDMI
+ if (payload->video_range || mPipeConfig == (0x2 << 6)) {
+ // full range, no need to do level expansion
+ backBuffer->OCLRC0 = 0x1000000;
+ backBuffer->OCLRC1 = 0x80;
+ } else {
+ // level expansion for limited range
+ backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) |
+ (OVERLAY_INIT_BRIGHTNESS & 0xff);
+ backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION;
+ }
+
+ return true;
+}
+
+bool OverlayPlaneBase::setDataBuffer(BufferMapper& grallocMapper)
+{
+ BufferMapper *mapper;
+ BufferMapper *videoBufferMapper = 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) {
+ ETRACE("invalid payload buffer");
+ return 0;
+ }
+
+ mBobDeinterlace = payload->bob_deinterlace;
+
+ int srcW, srcH;
+ srcW = grallocMapper.getCrop().w - grallocMapper.getCrop().x;
+ srcH = grallocMapper.getCrop().h - grallocMapper.getCrop().y;
+ if ((srcW > INTEL_OVERLAY_MAX_WIDTH - 1) || (srcH > INTEL_OVERLAY_MAX_HEIGHT - 1)) {
+ if (mTransform) {
+ int x, y, w, h;
+ x = mSrcCrop.x;
+ y = mSrcCrop.y;
+ w = mSrcCrop.w;
+ h = mSrcCrop.h;
+ setSourceCrop(0, 0, payload->scaling_width, payload->scaling_height);
+ if (!useOverlayRotation(grallocMapper)) {
+ DTRACE("The scaled buffer will hit overlay rotation limitation, fall back to GLES");
+ setSourceCrop(x, y, w, h);
+ return false;
+ }
+ }
+
+ if (!scaledBufferReady(grallocMapper, videoBufferMapper, payload)) {
+ DTRACE("scaled buffer is not ready, fall back to GLES");
+ return false;
+ } else {
+ videoBufferMapper->setFormat(OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar);
+ mapper = videoBufferMapper;
+ }
+ }
+ }
+
+ if (!mUseScaledBuffer && mTransform && !useOverlayRotation(grallocMapper)) {
+ if (!rotatedBufferReady(grallocMapper, videoBufferMapper)) {
+ DTRACE("rotated buffer is not ready");
+ return false;
+ }
+
+ if (!videoBufferMapper) {
+ ETRACE("failed to get rotated buffer");
+ return false;
+ }
+ mapper = videoBufferMapper;
+ }
+
+ OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
+ if (!backBuffer) {
+ ETRACE("invalid back buffer");
+ return false;
+ }
+
+ ret = bufferOffsetSetup(*mapper);
+ if (ret == false) {
+ ETRACE("failed to set up buffer offsets");
+ return false;
+ }
+
+ ret = coordinateSetup(*mapper);
+ if (ret == false) {
+ ETRACE("failed to set up overlay coordinates");
+ return false;
+ }
+
+ ret = scalingSetup(*mapper);
+ if (ret == false) {
+ ETRACE("failed to set up scaling parameters");
+ return false;
+ }
+
+ backBuffer->OCMD |= 0x1;
+
+ ret = colorSetup(grallocMapper);
+ if (ret == false) {
+ ETRACE("failed to set up color parameters");
+ return false;
+ }
+ 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 (videoBufferMapper) {
+ updateActiveTTMBuffers(mapper);
+ }
+
+ mUseScaledBuffer = 0;
+ return true;
+}
+
+} // namespace intel
+} // namespace android
+
diff --git a/merrifield/ips/common/OverlayPlaneBase.h b/merrifield/ips/common/OverlayPlaneBase.h
new file mode 100644
index 0000000..fc76a61
--- /dev/null
+++ b/merrifield/ips/common/OverlayPlaneBase.h
@@ -0,0 +1,129 @@
+/*
+// 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 <hal_public.h>
+#include <DisplayPlane.h>
+#include <BufferMapper.h>
+#include <common/Wsbm.h>
+#include <common/OverlayHardware.h>
+#include <common/VideoPayloadBuffer.h>
+
+namespace android {
+namespace intel {
+
+typedef struct {
+ OverlayBackBufferBlk *buf;
+ uint32_t gttOffsetInPage;
+ void* 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 bool colorSetup(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);
+ virtual bool scaledBufferReady(BufferMapper& mapper, BufferMapper* &scaledMapper, VideoPayloadBuffer *payload);
+
+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<buffer_handle_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;
+ int mUseScaledBuffer;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* OVERLAY_PLANE_BASE_H */
+
diff --git a/merrifield/ips/common/PixelFormat.cpp b/merrifield/ips/common/PixelFormat.cpp
new file mode 100644
index 0000000..758788c
--- /dev/null
+++ b/merrifield/ips/common/PixelFormat.cpp
@@ -0,0 +1,55 @@
+/*
+// 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 <hal_public.h>
+#include <HwcTrace.h>
+#include <common/PixelFormat.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/merrifield/ips/common/PixelFormat.h b/merrifield/ips/common/PixelFormat.h
new file mode 100644
index 0000000..cea69e0
--- /dev/null
+++ b/merrifield/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/merrifield/ips/common/PlaneCapabilities.cpp b/merrifield/ips/common/PlaneCapabilities.cpp
new file mode 100644
index 0000000..973c535
--- /dev/null
+++ b/merrifield/ips/common/PlaneCapabilities.cpp
@@ -0,0 +1,234 @@
+/*
+// 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 <HwcTrace.h>
+#include <DisplayPlane.h>
+#include <hal_public.h>
+#include <OMX_IVCommon.h>
+#include <OMX_IntelVideoExt.h>
+#include <PlaneCapabilities.h>
+#include "OverlayHardware.h"
+#include <HwcLayer.h>
+
+#define SPRITE_PLANE_MAX_STRIDE_TILED 16384
+//FIXME: need confirmation about this stride
+#define SPRITE_PLANE_MAX_STRIDE_LINEAR 8192
+
+#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:
+ VTRACE("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) {
+ WTRACE("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:
+ VTRACE("unsupported format %#x", format);
+ return false;
+ }
+ } else {
+ ETRACE("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:
+ if (stride.rgb.stride > SPRITE_PLANE_MAX_STRIDE_LINEAR) {
+ VTRACE("too large stride %d", stride.rgb.stride);
+ return false;
+ }
+ return true;
+ default:
+ VTRACE("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:
+ VTRACE("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) {
+ VTRACE("stride %d is too large", stride.yuv.yStride);
+ return false;
+ }
+ return true;
+ } else {
+ ETRACE("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) {
+ bool ret = false;
+
+ // support premultipled & none blanding
+ switch (blending) {
+ case HWC_BLENDING_NONE:
+ return true;
+ case HWC_BLENDING_PREMULT:
+ ret = false;
+ if ((planeAlpha == 0) || (planeAlpha == 255)) {
+ ret = true;
+ }
+ return ret;
+ default:
+ VTRACE("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 {
+ ETRACE("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;
+
+ 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
+ return false;
+ }
+
+ return true;
+ } else if (planeType == DisplayPlane::PLANE_CURSOR) {
+ if (srcW > 256 || srcH > 256) {
+ return false;
+ }
+ return true;
+ } else {
+ ETRACE("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/merrifield/ips/common/PrepareListener.cpp b/merrifield/ips/common/PrepareListener.cpp
new file mode 100644
index 0000000..0b4b05d
--- /dev/null
+++ b/merrifield/ips/common/PrepareListener.cpp
@@ -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.
+*/
+
+#include <HwcTrace.h>
+#include <Drm.h>
+#include <Hwcomposer.h>
+#include <common/PrepareListener.h>
+
+namespace android {
+namespace intel {
+
+PrepareListener::PrepareListener()
+ : IPrepareListener()
+{
+}
+
+PrepareListener::~PrepareListener()
+{
+}
+
+void PrepareListener::onProtectedLayerStart(int disp)
+{
+ WTRACE("disp = %d, ignored for now", disp);
+ // need chaabi support for granular IED control
+ return;
+
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ int ret = drmCommandNone(drm->getDrmFd(), DRM_PSB_HDCP_DISPLAY_IED_ON);
+ if (ret != 0) {
+ ETRACE("failed to turn on display IED");
+ } else {
+ ITRACE("display IED is turned on");
+ }
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/common/PrepareListener.h b/merrifield/ips/common/PrepareListener.h
new file mode 100644
index 0000000..e048b92
--- /dev/null
+++ b/merrifield/ips/common/PrepareListener.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 PREPARE_LISTENER_H
+#define PREPARE_LISTENER_H
+
+#include <IPrepareListener.h>
+
+namespace android {
+namespace intel {
+
+class PrepareListener : public IPrepareListener {
+public:
+ PrepareListener();
+ virtual ~PrepareListener();
+public:
+ virtual void onProtectedLayerStart(int disp);
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* PREPARE_LISTENER_H */
diff --git a/merrifield/ips/common/RotationBufferProvider.cpp b/merrifield/ips/common/RotationBufferProvider.cpp
new file mode 100644
index 0000000..65a4db8
--- /dev/null
+++ b/merrifield/ips/common/RotationBufferProvider.cpp
@@ -0,0 +1,637 @@
+/*
+// 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 <HwcTrace.h>
+#include <common/RotationBufferProvider.h>
+
+namespace android {
+namespace intel {
+
+#define CHECK_VA_STATUS_RETURN(FUNC) \
+if (vaStatus != VA_STATUS_SUCCESS) {\
+ ETRACE(FUNC" failed. vaStatus = %#x", vaStatus);\
+ return false;\
+}
+
+#define CHECK_VA_STATUS_BREAK(FUNC) \
+if (vaStatus != VA_STATUS_SUCCESS) {\
+ ETRACE(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))
+ WTRACE("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;
+}
+
+buffer_handle_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) {
+ ETRACE("failed to allocate TTM buffer");
+ return 0;
+ }
+
+ return (buffer_handle_t) 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 + 0x1f) & ~0x1f;
+ stride = payload->luma_stride; /* NV12 srouce buffer */
+ }
+
+ if (!stride) {
+ ETRACE("invalid stride value");
+ return false;
+ }
+
+ mBobDeinterlace = payload->bob_deinterlace;
+ // 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) {
+ buffer_handle_t khandle = createWsbmBuffer(stride, bufferHeight, &mDrmBuf[mTargetIndex]);
+ if (khandle == 0) {
+ ETRACE("failed to create buffer by wsbm");
+ return false;
+ }
+
+ mKhandles[mTargetIndex] = khandle;
+ vaSurfaceAttrib->buffers[0] = (uintptr_t) khandle;
+ mRotatedStride = stride;
+ surface = &mRotatedSurfaces[mTargetIndex];
+ } else {
+ vaSurfaceAttrib->buffers[0] = (uintptr_t) 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 {
+ VTRACE("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) {
+ ETRACE("vaCreateSurfacesWithAttribute returns %d", vaStatus);
+ ETRACE("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) {
+ ETRACE("failed to get VADisplay");
+ return false;
+ }
+
+ vaStatus = vaInitialize(mVaDpy, &majorVer, &minorVer);
+ CHECK_VA_STATUS_RETURN("vaInitialize");
+
+ numEntryPoints = vaMaxNumEntrypoints(mVaDpy);
+
+ if (numEntryPoints <= 0) {
+ ETRACE("numEntryPoints value is invalid");
+ return false;
+ }
+
+ entryPoint = (VAEntrypoint*)malloc(sizeof(VAEntrypoint) * numEntryPoints);
+ if (NULL == entryPoint) {
+ ETRACE("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) {
+ ETRACE("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) {
+ ETRACE("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) {
+ ETRACE("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)))) {
+ ETRACE("VA_ROTATION_xxx: 0x%08x is not supported by the filter",
+ transFromHalToVa(transform));
+ return false;
+ }
+
+ 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) {
+ WTRACE("payload data is not correct: format %#x, width %d, height %d",
+ payload->format, payload->width, payload->height);
+ return ret;
+ }
+
+ if (payload->width > 1280 && payload->width <= 2048) {
+ payload->tiling = 1;
+ }
+
+ do {
+ if (isContextChanged(payload->width, payload->height, transform)) {
+ DTRACE("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) {
+ ETRACE("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) {
+ ETRACE("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;
+ pipelineParam->surface_region = NULL;
+ pipelineParam->output_region = NULL;
+ pipelineParam->num_forward_references = 0;
+ pipelineParam->num_backward_references = 0;
+ 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
+ ITRACE("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
+ ITRACE("time spent %dms for setupRotationBuffer",
+ getMilliseconds() - setup_Begin);
+#endif
+
+ if (mSourceSurface > 0) {
+ vaStatus = vaDestroySurfaces(mVaDpy, &mSourceSurface, 1);
+ if (vaStatus != VA_STATUS_SUCCESS)
+ WTRACE("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) {
+ WTRACE("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->coded_width = ((w + 0xf) & ~0xf);
+ payload->coded_height = ((h + 0xf) & ~0xf);
+ 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;
+ payload->bob_deinterlace = 0;
+
+ chroma_offset = stride * h;
+ size = stride * h + stride * h / 2;
+
+ ssize_t index;
+ index = mTTMWrappers.indexOfKey((uint64_t)user_pt);
+ if (index < 0) {
+ VTRACE("wrapped userPt as wsbm buffer");
+ bool ret = mWsbm->allocateTTMBufferUB(size, 0, &buf, user_pt);
+ if (ret == false) {
+ ETRACE("failed to allocate TTM buffer");
+ return ret;
+ }
+
+ if (mTTMWrappers.size() >= TTM_WRAPPER_COUNT) {
+ WTRACE("mTTMWrappers is unexpectedly full. Invalidate caches");
+ invalidateCaches();
+ }
+
+ index = mTTMWrappers.add((uint64_t)user_pt, buf);
+ } else {
+ VTRACE("got wsbmBuffer in saved caches");
+ buf = mTTMWrappers.valueAt(index);
+ }
+
+ payload->khandle = (buffer_handle_t) 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)
+ WTRACE("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)
+ WTRACE("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;
+
+ for (int i = 0; i < MAX_SURFACE_NUM; i++) {
+ mKhandles[i] = 0;
+ mRotatedSurfaces[i] = 0;
+ mDrmBuf[i] = NULL;
+ }
+ // 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;
+ mBobDeinterlace = 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/merrifield/ips/common/RotationBufferProvider.h b/merrifield/ips/common/RotationBufferProvider.h
new file mode 100644
index 0000000..edf4fa7
--- /dev/null
+++ b/merrifield/ips/common/RotationBufferProvider.h
@@ -0,0 +1,102 @@
+/*
+// 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 <common/Wsbm.h>
+#include <utils/Timers.h>
+#include <utils/KeyedVector.h>
+#include <va/va_android.h>
+#include <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);
+ buffer_handle_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;
+ buffer_handle_t 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/merrifield/ips/common/SpritePlaneBase.cpp b/merrifield/ips/common/SpritePlaneBase.cpp
new file mode 100644
index 0000000..890aec8
--- /dev/null
+++ b/merrifield/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 <HwcTrace.h>
+#include <common/SpritePlaneBase.h>
+#include <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/merrifield/ips/common/SpritePlaneBase.h b/merrifield/ips/common/SpritePlaneBase.h
new file mode 100644
index 0000000..78bbd6e
--- /dev/null
+++ b/merrifield/ips/common/SpritePlaneBase.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 SPRITE_PLANE_BASE_H
+#define SPRITE_PLANE_BASE_H
+
+#include <utils/KeyedVector.h>
+#include <hal_public.h>
+#include <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/merrifield/ips/common/TTMBufferMapper.cpp b/merrifield/ips/common/TTMBufferMapper.cpp
new file mode 100644
index 0000000..7c3ed0d
--- /dev/null
+++ b/merrifield/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 <HwcTrace.h>
+#include <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;
+ buffer_handle_t handle;
+ void *virtAddr;
+ uint32_t gttOffsetInPage;
+
+ CTRACE();
+
+ handle = getHandle();
+
+ bool ret = mWsbm.wrapTTMBuffer((int64_t)handle, &wsbmBufferObject);
+ if (ret == false) {
+ ETRACE("failed to map TTM buffer");
+ return false;
+ }
+
+ // TODO: review this later
+ ret = mWsbm.waitIdleTTMBuffer(wsbmBufferObject);
+ if (ret == false) {
+ ETRACE("failed to wait ttm buffer idle");
+ return false;
+ }
+
+ virtAddr = mWsbm.getCPUAddress(wsbmBufferObject);
+ gttOffsetInPage = mWsbm.getGttOffset(wsbmBufferObject);
+
+ if (!gttOffsetInPage || !virtAddr) {
+ WTRACE("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/merrifield/ips/common/TTMBufferMapper.h b/merrifield/ips/common/TTMBufferMapper.h
new file mode 100644
index 0000000..46ed26e
--- /dev/null
+++ b/merrifield/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 <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;
+ }
+ buffer_handle_t getKHandle(int subIndex) {
+ return 0;
+ }
+ buffer_handle_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/merrifield/ips/common/VideoPayloadBuffer.h b/merrifield/ips/common/VideoPayloadBuffer.h
new file mode 100644
index 0000000..1faf84a
--- /dev/null
+++ b/merrifield/ips/common/VideoPayloadBuffer.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 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;
+ buffer_handle_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;
+ buffer_handle_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;
+ buffer_handle_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;
+ uint32_t csc_mode;
+ uint32_t video_range;
+ uint32_t initialized;
+};
+
+
+// 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/merrifield/ips/common/VideoPayloadManager.cpp b/merrifield/ips/common/VideoPayloadManager.cpp
new file mode 100644
index 0000000..33e2afb
--- /dev/null
+++ b/merrifield/ips/common/VideoPayloadManager.cpp
@@ -0,0 +1,123 @@
+/*
+// 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 <HwcTrace.h>
+#include <BufferMapper.h>
+#include <common/GrallocSubBuffer.h>
+#include <common/VideoPayloadManager.h>
+#include <common/VideoPayloadBuffer.h>
+
+namespace android {
+namespace intel {
+
+VideoPayloadManager::VideoPayloadManager()
+ : IVideoPayloadManager()
+{
+}
+
+VideoPayloadManager::~VideoPayloadManager()
+{
+}
+
+bool VideoPayloadManager::getMetaData(BufferMapper *mapper, MetaData *metadata)
+{
+ if (!mapper || !metadata) {
+ ETRACE("Null input params");
+ return false;
+ }
+
+ VideoPayloadBuffer *p = (VideoPayloadBuffer*) mapper->getCpuAddress(SUB_BUFFER1);
+ if (!p) {
+ ETRACE("Got null payload from display buffer");
+ return false;
+ }
+
+ metadata->format = p->format;
+ metadata->transform = p->metadata_transform;
+ metadata->timestamp = p->timestamp;
+
+ metadata->normalBuffer.khandle = p->khandle;
+ metadata->normalBuffer.width = p->crop_width;
+ metadata->normalBuffer.height = p->crop_height;
+ metadata->normalBuffer.bufWidth = p->width;
+ metadata->normalBuffer.bufHeight = p->height;
+ metadata->normalBuffer.lumaStride = p->luma_stride;
+ metadata->normalBuffer.chromaUStride = p->chroma_u_stride;
+ metadata->normalBuffer.chromaVStride = p->chroma_v_stride;
+ metadata->normalBuffer.offsetX = 0;
+ metadata->normalBuffer.offsetY = 0;
+ metadata->normalBuffer.tiled = (p->width > 1280);
+
+ metadata->scalingBuffer.khandle = p->scaling_khandle;
+ metadata->scalingBuffer.width = p->scaling_width;
+ metadata->scalingBuffer.height = p->scaling_height;
+ metadata->scalingBuffer.bufWidth = align_to(p->scaling_width, 32);
+ metadata->scalingBuffer.bufHeight = align_to(p->scaling_height, 32);
+ metadata->scalingBuffer.lumaStride = p->scaling_luma_stride;
+ metadata->scalingBuffer.chromaUStride = p->scaling_chroma_u_stride;
+ metadata->scalingBuffer.chromaVStride = p->scaling_chroma_v_stride;
+ metadata->scalingBuffer.offsetX = 0;
+ metadata->scalingBuffer.offsetY = 0;
+ metadata->scalingBuffer.tiled = false;
+
+ metadata->rotationBuffer.khandle = p->rotated_buffer_handle;
+ uint16_t rotSrcWidth;
+ uint16_t rotSrcHeight;
+ if (metadata->scalingBuffer.khandle) {
+ rotSrcWidth = metadata->scalingBuffer.width;
+ rotSrcHeight = metadata->scalingBuffer.height;
+ } else {
+ rotSrcWidth = metadata->normalBuffer.width;
+ rotSrcHeight = metadata->normalBuffer.height;
+ }
+ if (metadata->transform == 0 || metadata->transform == HAL_TRANSFORM_ROT_180) {
+ metadata->rotationBuffer.width = rotSrcWidth;
+ metadata->rotationBuffer.height = rotSrcHeight;
+ } else {
+ metadata->rotationBuffer.width = rotSrcHeight;
+ metadata->rotationBuffer.height = rotSrcWidth;
+ }
+ metadata->rotationBuffer.bufWidth = p->rotated_width;
+ metadata->rotationBuffer.bufHeight = p->rotated_height;
+ metadata->rotationBuffer.lumaStride = p->rotate_luma_stride;
+ metadata->rotationBuffer.chromaUStride = p->rotate_chroma_u_stride;
+ metadata->rotationBuffer.chromaVStride = p->rotate_chroma_v_stride;
+ metadata->rotationBuffer.offsetX = (-metadata->rotationBuffer.width) & 0xf;
+ metadata->rotationBuffer.offsetY = (-metadata->rotationBuffer.height) & 0xf;
+ metadata->rotationBuffer.tiled = metadata->normalBuffer.tiled;
+
+ return true;
+}
+
+bool VideoPayloadManager::setRenderStatus(BufferMapper *mapper, bool renderStatus)
+{
+ if (!mapper) {
+ ETRACE("Null mapper param");
+ return false;
+ }
+
+ VideoPayloadBuffer* p = (VideoPayloadBuffer*) mapper->getCpuAddress(SUB_BUFFER1);
+ if (!p) {
+ ETRACE("Got null payload from display buffer");
+ return false;
+ }
+
+ p->renderStatus = renderStatus ? 1 : 0;
+ return true;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/common/VideoPayloadManager.h b/merrifield/ips/common/VideoPayloadManager.h
new file mode 100644
index 0000000..563003d
--- /dev/null
+++ b/merrifield/ips/common/VideoPayloadManager.h
@@ -0,0 +1,42 @@
+/*
+// 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_MANAGER_H
+#define VIDEO_PAYLOAD_MANAGER_H
+
+#include <IVideoPayloadManager.h>
+
+namespace android {
+namespace intel {
+
+class BufferMapper;
+
+class VideoPayloadManager : public IVideoPayloadManager {
+
+public:
+ VideoPayloadManager();
+ virtual ~VideoPayloadManager();
+
+ // IVideoPayloadManager
+public:
+ virtual bool getMetaData(BufferMapper *mapper, MetaData *metadata);
+ virtual bool setRenderStatus(BufferMapper *mapper, bool renderStatus);
+
+}; // class VideoPayloadManager
+
+} // namespace intel
+} // namespace android
+
+#endif /* VIDEO_PAYLOAD_MANAGER_H */
diff --git a/merrifield/ips/common/VsyncControl.cpp b/merrifield/ips/common/VsyncControl.cpp
new file mode 100644
index 0000000..9e576fd
--- /dev/null
+++ b/merrifield/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 <HwcTrace.h>
+#include <Drm.h>
+#include <Hwcomposer.h>
+#include <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)
+{
+ ATRACE("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)
+{
+ ATRACE("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/merrifield/ips/common/VsyncControl.h b/merrifield/ips/common/VsyncControl.h
new file mode 100644
index 0000000..d5ffa11
--- /dev/null
+++ b/merrifield/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/merrifield/ips/common/Wsbm.cpp b/merrifield/ips/common/Wsbm.cpp
new file mode 100644
index 0000000..ab92b1b
--- /dev/null
+++ b/merrifield/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 <HwcTrace.h>
+#include <common/Wsbm.h>
+
+Wsbm::Wsbm(int drmFD)
+ : mInitialized(false)
+{
+ CTRACE();
+ mDrmFD = drmFD;
+}
+
+Wsbm::~Wsbm()
+{
+ WARN_IF_NOT_DEINIT();
+}
+
+bool Wsbm::initialize()
+{
+ if (mInitialized) {
+ WTRACE("object is initialized");
+ return true;
+ }
+
+ int ret = psbWsbmInitialize(mDrmFD);
+ if (ret) {
+ ETRACE("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) {
+ ETRACE("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) {
+ ETRACE("failed to allocate UB buffer");
+ return false;
+ }
+
+ return true;
+}
+
+bool Wsbm::destroyTTMBuffer(void * buf)
+{
+ int ret = psbWsbmDestroyTTMBuffer(buf);
+ if (ret) {
+ ETRACE("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(int64_t handle, void **buf)
+{
+ int ret = psbWsbmWrapTTMBuffer(handle, buf);
+ if (ret) {
+ ETRACE("failed to wrap buffer");
+ return false;
+ }
+
+ return true;
+}
+
+bool Wsbm::unreferenceTTMBuffer(void *buf)
+{
+ int ret = psbWsbmUnReference(buf);
+ if (ret) {
+ ETRACE("failed to unreference buffer");
+ return false;
+ }
+
+ return true;
+}
+
+uint64_t Wsbm::getKBufHandle(void *buf)
+{
+ return psbWsbmGetKBufHandle(buf);
+}
+
+bool Wsbm::waitIdleTTMBuffer(void *buf)
+{
+ int ret = psbWsbmWaitIdle(buf);
+ if (ret) {
+ ETRACE("failed to wait ttm buffer for idle");
+ return false;
+ }
+
+ return true;
+}
diff --git a/merrifield/ips/common/Wsbm.h b/merrifield/ips/common/Wsbm.h
new file mode 100644
index 0000000..9e2b357
--- /dev/null
+++ b/merrifield/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 <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(int64_t handle, void **buf);
+ bool unreferenceTTMBuffer(void *buf);
+ bool waitIdleTTMBuffer(void *buf);
+ uint64_t getKBufHandle(void *buf);
+private:
+ bool mInitialized;
+};
+
+#endif /*__INTEL_WSBM_H__*/
diff --git a/merrifield/ips/common/WsbmWrapper.c b/merrifield/ips/common/WsbmWrapper.c
new file mode 100644
index 0000000..5e4161e
--- /dev/null
+++ b/merrifield/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 <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) {
+ ETRACE("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) {
+ ETRACE("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) {
+ ETRACE("invalid drm fd %d", drmFD);
+ return drmFD;
+ }
+
+ /*init wsbm*/
+ ret = wsbmInit(wsbmNullThreadFuncs(), &vNodeFuncs);
+ if (ret) {
+ ETRACE("failed to initialize Wsbm, error code %d", ret);
+ return ret;
+ }
+
+ VTRACE("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) {
+ ETRACE("failed to get device offset, error code %d", ret);
+ goto out;
+ }
+
+ VTRACE("ioctl offset %#x", arg.rep.driver_ioctl_offset);
+
+ mainPool = wsbmTTMPoolInit(drmFD, arg.rep.driver_ioctl_offset);
+ if(!mainPool) {
+ ETRACE("failed to initialize TTM Pool");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ VTRACE("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;
+
+ ATRACE("size %d", align_to(size, 4096));
+
+ if(!buf || !user_pt) {
+ ETRACE("invalid parameter");
+ return -EINVAL;
+ }
+
+ VTRACE("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) {
+ ETRACE("wsbmGenBuffers failed with error code %d", ret);
+ return ret;
+ }
+
+ ret = wsbmBODataUB(wsbmBuf,
+ align_to(size, 4096), NULL, NULL, 0,
+ user_pt);
+
+ if(ret) {
+ ETRACE("wsbmBOData failed with error code %d", ret);
+ /*FIXME: should I unreference this buffer here?*/
+ return ret;
+ }
+
+ *buf = wsbmBuf;
+
+ VTRACE("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;
+
+ ATRACE("size %d", align_to(size, 4096));
+
+ if(!buf) {
+ ETRACE("invalid parameter");
+ return -EINVAL;
+ }
+
+ VTRACE("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) {
+ ETRACE("wsbmGenBuffers failed with error code %d", ret);
+ return ret;
+ }
+
+ ret = wsbmBOData(wsbmBuf, align_to(size, 4096), NULL, NULL, 0);
+ if(ret) {
+ ETRACE("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;
+
+ VTRACE("ttm buffer allocated. %p", *buf);
+ return 0;
+}
+
+int psbWsbmWrapTTMBuffer(uint64_t handle, void **buf)
+{
+ int ret = 0;
+ struct _WsbmBufferObject *wsbmBuf;
+
+ if (!buf) {
+ ETRACE("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) {
+ ETRACE("wsbmGenBuffers failed with error code %d", ret);
+ return ret;
+ }
+
+ ret = wsbmBOSetReferenced(wsbmBuf, handle);
+ if (ret) {
+ ETRACE("wsbmBOSetReferenced failed with error code %d", ret);
+ return ret;
+ }
+
+ *buf = (void *)wsbmBuf;
+
+ VTRACE("wrap buffer %p for handle %#x", wsbmBuf, handle);
+ return 0;
+}
+
+int psbWsbmWrapTTMBuffer2(uint64_t handle, void **buf)
+{
+ int ret = 0;
+ struct _WsbmBufferObject *wsbmBuf;
+
+ if (!buf) {
+ ETRACE("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) {
+ ETRACE("wsbmGenBuffers failed with error code %d", ret);
+ return ret;
+ }
+
+ *buf = (void *)wsbmBuf;
+
+ VTRACE("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) {
+ ETRACE("invalid parameter");
+ return -EINVAL;
+ }
+
+ wsbmBuf = (struct _WsbmBufferObject *)buf;
+ ret = wsbmBODataUB(wsbmBuf, size, NULL, NULL, 0, vaddr);
+ if (ret) {
+ ETRACE("wsbmBODataUB failed with error code %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int psbWsbmUnReference(void *buf)
+{
+ struct _WsbmBufferObject *wsbmBuf;
+
+ if (!buf) {
+ ETRACE("invalid parameter");
+ return -EINVAL;
+ }
+
+ wsbmBuf = (struct _WsbmBufferObject *)buf;
+
+ wsbmBOUnreference(&wsbmBuf);
+
+ return 0;
+}
+
+int psbWsbmDestroyTTMBuffer(void * buf)
+{
+ CTRACE();
+
+ if(!buf) {
+ ETRACE("invalid ttm buffer");
+ return -EINVAL;
+ }
+
+ /*FIXME: should I unmap this buffer object first?*/
+ wsbmBOUnmap((struct _WsbmBufferObject *)buf);
+
+ wsbmBOUnreference((struct _WsbmBufferObject **)&buf);
+
+ XTRACE();
+
+ return 0;
+}
+
+void * psbWsbmGetCPUAddress(void * buf)
+{
+ if(!buf) {
+ ETRACE("invalid ttm buffer");
+ return NULL;
+ }
+
+ VTRACE("buffer object %p", buf);
+
+ void * address = wsbmBOMap((struct _WsbmBufferObject *)buf,
+ WSBM_ACCESS_READ | WSBM_ACCESS_WRITE);
+ if(!address) {
+ ETRACE("failed to map buffer object");
+ return NULL;
+ }
+
+ VTRACE("mapped successfully. %p, size %ld",
+ address, wsbmBOSize((struct _WsbmBufferObject *)buf));
+
+ return address;
+}
+
+uint32_t psbWsbmGetGttOffset(void * buf)
+{
+ if(!buf) {
+ ETRACE("invalid ttm buffer");
+ return 0;
+ }
+
+ VTRACE("buffer object %p", buf);
+
+ uint32_t offset =
+ wsbmBOOffsetHint((struct _WsbmBufferObject *)buf) - 0x10000000;
+
+ VTRACE("offset %#x", offset >> 12);
+
+ return offset >> 12;
+}
+
+uint32_t psbWsbmGetKBufHandle(void *buf)
+{
+ if (!buf) {
+ ETRACE("invalid ttm buffer");
+ return 0;
+ }
+
+ return (wsbmKBufHandle(wsbmKBuf((struct _WsbmBufferObject *)buf)));
+}
+
+uint32_t psbWsbmWaitIdle(void *buf)
+{
+ if (!buf) {
+ ETRACE("invalid ttm buffer");
+ return -EINVAL;
+ }
+
+ wsbmBOWaitIdle(buf, 0);
+ return 0;
+}
diff --git a/merrifield/ips/common/WsbmWrapper.h b/merrifield/ips/common/WsbmWrapper.h
new file mode 100644
index 0000000..1dad5fd
--- /dev/null
+++ b/merrifield/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(uint64_t handle, void **buf);
+extern int psbWsbmWrapTTMBuffer2(uint64_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/merrifield/ips/penwell/PnwGrallocBuffer.cpp b/merrifield/ips/penwell/PnwGrallocBuffer.cpp
new file mode 100644
index 0000000..a867cb8
--- /dev/null
+++ b/merrifield/ips/penwell/PnwGrallocBuffer.cpp
@@ -0,0 +1,46 @@
+/*
+// 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 <HwcTrace.h>
+#include <penwell/PnwGrallocBuffer.h>
+
+namespace android {
+namespace intel {
+
+PnwGrallocBuffer::PnwGrallocBuffer(uint32_t handle)
+ :GrallocBufferBase(handle)
+{
+ struct PnwIMGGrallocBuffer *grallocHandle =
+ (struct PnwIMGGrallocBuffer*)handle;
+
+ CTRACE();
+
+ if (!grallocHandle) {
+ ETRACE("gralloc handle is null");
+ return;
+ }
+
+ mFormat = grallocHandle->format;
+ mWidth = grallocHandle->width;
+ mHeight = grallocHandle->height;
+ mUsage = grallocHandle->usage;
+ mKey = grallocHandle->stamp;
+ mBpp = grallocHandle->bpp;
+
+ initialize();
+}
+
+}
+}
diff --git a/merrifield/ips/penwell/PnwGrallocBuffer.h b/merrifield/ips/penwell/PnwGrallocBuffer.h
new file mode 100644
index 0000000..ce0414c
--- /dev/null
+++ b/merrifield/ips/penwell/PnwGrallocBuffer.h
@@ -0,0 +1,46 @@
+/*
+// 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 PNW_GRALLOC_BUFFER_H
+#define PNW_GRALLOC_BUFFER_H
+
+#include <common/GrallocSubBuffer.h>
+#include <common/GrallocBufferBase.h>
+
+namespace android {
+namespace intel {
+
+struct PnwIMGGrallocBuffer{
+ native_handle_t base;
+ int fd[SUB_BUFFER_MAX];
+ unsigned long long stamp;
+ int usage;
+ int width;
+ int height;
+ int format;
+ int bpp;
+}__attribute__((aligned(sizeof(int)),packed));
+
+
+class PnwGrallocBuffer : public GrallocBufferBase {
+public:
+ PnwGrallocBuffer(uint32_t handle);
+};
+
+} // namespace intel
+} // namespace android
+
+
+#endif /* PNW_GRALLOC_BUFFER_H */
diff --git a/merrifield/ips/penwell/PnwGrallocBufferMapper.cpp b/merrifield/ips/penwell/PnwGrallocBufferMapper.cpp
new file mode 100644
index 0000000..2550437
--- /dev/null
+++ b/merrifield/ips/penwell/PnwGrallocBufferMapper.cpp
@@ -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.
+*/
+#include <HwcTrace.h>
+#include <Drm.h>
+#include <Hwcomposer.h>
+#include <penwell/PnwGrallocBufferMapper.h>
+
+namespace android {
+namespace intel {
+
+PnwGrallocBufferMapper::PnwGrallocBufferMapper(DataBuffer& buffer)
+ : GrallocBufferMapperBase(buffer)
+{
+ CTRACE();
+}
+
+PnwGrallocBufferMapper::~PnwGrallocBufferMapper()
+{
+ CTRACE();
+}
+
+bool PnwGrallocBufferMapper::map()
+{
+ // TODO: implement map
+ return false;
+}
+
+bool PnwGrallocBufferMapper::unmap()
+{
+ //TODO: implement unmap
+ return false;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/penwell/PnwGrallocBufferMapper.h b/merrifield/ips/penwell/PnwGrallocBufferMapper.h
new file mode 100644
index 0000000..743d498
--- /dev/null
+++ b/merrifield/ips/penwell/PnwGrallocBufferMapper.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 PNW_GRALLOC_BUFFER_MAPPER_H
+#define PNW_GRALLOC_BUFFER_MAPPER_H
+
+#include <BufferMapper.h>
+#include <hal_public.h>
+#include <common/GrallocBufferMapperBase.h>
+
+namespace android {
+namespace intel {
+
+class PnwGrallocBufferMapper : public GrallocBufferMapperBase {
+public:
+ PnwGrallocBufferMapper(DataBuffer& buffer);
+ ~PnwGrallocBufferMapper();
+public:
+ bool map();
+ bool unmap();
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* TNG_GRALLOC_BUFFER_MAPPER_H */
diff --git a/merrifield/ips/penwell/PnwOverlayPlane.cpp b/merrifield/ips/penwell/PnwOverlayPlane.cpp
new file mode 100644
index 0000000..f2328fa
--- /dev/null
+++ b/merrifield/ips/penwell/PnwOverlayPlane.cpp
@@ -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.
+*/
+#include <math.h>
+#include <HwcTrace.h>
+#include <Drm.h>
+#include <Hwcomposer.h>
+#include <penwell/PnwOverlayPlane.h>
+#include <penwell/PnwGrallocBuffer.h>
+
+namespace android {
+namespace intel {
+
+PnwOverlayPlane::PnwOverlayPlane(int index, int disp)
+ : OverlayPlaneBase(index, disp)
+{
+ CTRACE();
+}
+
+PnwOverlayPlane::~PnwOverlayPlane()
+{
+ CTRACE();
+}
+
+bool PnwOverlayPlane::flip()
+{
+ //TODO: implement flip
+ return false;
+}
+
+void* PnwOverlayPlane::getContext() const
+{
+ CTRACE();
+ //TODO: return penwell overlay context
+ return 0;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/penwell/PnwOverlayPlane.h b/merrifield/ips/penwell/PnwOverlayPlane.h
new file mode 100644
index 0000000..0ae3924
--- /dev/null
+++ b/merrifield/ips/penwell/PnwOverlayPlane.h
@@ -0,0 +1,42 @@
+/*
+// 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 PNW_OVERLAY_PLANE_H
+#define PNW_OVERLAY_PLANE_H
+
+#include <utils/KeyedVector.h>
+#include <hal_public.h>
+#include <DisplayPlane.h>
+#include <BufferMapper.h>
+#include <common/Wsbm.h>
+#include <common/OverlayPlaneBase.h>
+
+namespace android {
+namespace intel {
+
+class PnwOverlayPlane : public OverlayPlaneBase {
+
+public:
+ PnwOverlayPlane(int index, int disp);
+ ~PnwOverlayPlane();
+
+ virtual bool flip();
+ virtual void* getContext() const;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* PNW_OVERLAY_PLANE_H */
diff --git a/merrifield/ips/penwell/PnwPrimaryPlane.cpp b/merrifield/ips/penwell/PnwPrimaryPlane.cpp
new file mode 100644
index 0000000..c88d116
--- /dev/null
+++ b/merrifield/ips/penwell/PnwPrimaryPlane.cpp
@@ -0,0 +1,65 @@
+/*
+// 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 <HwcTrace.h>
+#include <Drm.h>
+#include <penwell/PnwPrimaryPlane.h>
+#include <penwell/PnwGrallocBuffer.h>
+#include <common/PixelFormat.h>
+
+namespace android {
+namespace intel {
+
+PnwPrimaryPlane::PnwPrimaryPlane(int index, int disp)
+ : PnwSpritePlane(index, disp)
+{
+ CTRACE();
+ mType = PLANE_PRIMARY;
+}
+
+PnwPrimaryPlane::~PnwPrimaryPlane()
+{
+ CTRACE();
+}
+
+void PnwPrimaryPlane::setFramebufferTarget(DataBuffer& buf)
+{
+ CTRACE();
+ //TODO: implement penwell frame buffer target flip
+}
+
+bool PnwPrimaryPlane::setDataBuffer(uint32_t handle)
+{
+ PnwGrallocBuffer tmpBuf(handle);
+ uint32_t usage;
+
+ ATRACE("handle = %#x", handle);
+
+ usage = tmpBuf.getUsage();
+ if (!handle || (GRALLOC_USAGE_HW_FB & usage)) {
+ setFramebufferTarget(tmpBuf);
+ return true;
+ }
+
+ return DisplayPlane::setDataBuffer(handle);
+}
+
+bool PnwPrimaryPlane::assignToDevice(int disp)
+{
+ return true;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/penwell/PnwPrimaryPlane.h b/merrifield/ips/penwell/PnwPrimaryPlane.h
new file mode 100644
index 0000000..7f8b443
--- /dev/null
+++ b/merrifield/ips/penwell/PnwPrimaryPlane.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 PNW_PRIMARY_PLANE_H
+#define PNW_PRIMARY_PLANE_H
+
+#include <penwell/PnwSpritePlane.h>
+
+namespace android {
+namespace intel {
+
+class PnwPrimaryPlane : public PnwSpritePlane {
+public:
+ PnwPrimaryPlane(int index, int disp);
+ ~PnwPrimaryPlane();
+public:
+ bool setDataBuffer(uint32_t handle);
+ bool assignToDevice(int disp);
+private:
+ void setFramebufferTarget(DataBuffer& buf);
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* TNG_PRIMARY_PLANE_H */
diff --git a/merrifield/ips/penwell/PnwSpritePlane.cpp b/merrifield/ips/penwell/PnwSpritePlane.cpp
new file mode 100644
index 0000000..6799b1a
--- /dev/null
+++ b/merrifield/ips/penwell/PnwSpritePlane.cpp
@@ -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.
+*/
+#include <HwcTrace.h>
+#include <Hwcomposer.h>
+#include <BufferManager.h>
+#include <penwell/PnwSpritePlane.h>
+#include <common/PixelFormat.h>
+
+namespace android {
+namespace intel {
+
+PnwSpritePlane::PnwSpritePlane(int index, int disp)
+ : SpritePlaneBase(index, disp)
+{
+ CTRACE();
+}
+
+PnwSpritePlane::~PnwSpritePlane()
+{
+ CTRACE();
+}
+
+bool PnwSpritePlane::setDataBuffer(BufferMapper& mapper)
+{
+ // TODO: implement setDataBuffer
+ return false;
+}
+
+void* PnwSpritePlane::getContext() const
+{
+ CTRACE();
+ // TODO: return penwell sprite context
+ return 0;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/penwell/PnwSpritePlane.h b/merrifield/ips/penwell/PnwSpritePlane.h
new file mode 100644
index 0000000..189ef1b
--- /dev/null
+++ b/merrifield/ips/penwell/PnwSpritePlane.h
@@ -0,0 +1,42 @@
+/*
+// 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 PNW_SPRITE_PLANE_H
+#define PNW_SPRITE_PLANE_H
+
+#include <utils/KeyedVector.h>
+#include <hal_public.h>
+#include <BufferCache.h>
+#include <DisplayPlane.h>
+
+#include <common/SpritePlaneBase.h>
+
+namespace android {
+namespace intel {
+
+class PnwSpritePlane : public SpritePlaneBase {
+public:
+ PnwSpritePlane(int index, int disp);
+ virtual ~PnwSpritePlane();
+public:
+ virtual void* getContext() const;
+protected:
+ virtual bool setDataBuffer(BufferMapper& mapper);
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* PNW_SPRITE_PLANE_H */
diff --git a/merrifield/ips/tangier/TngCursorPlane.cpp b/merrifield/ips/tangier/TngCursorPlane.cpp
new file mode 100644
index 0000000..8ce5af7
--- /dev/null
+++ b/merrifield/ips/tangier/TngCursorPlane.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 <HwcTrace.h>
+#include <Hwcomposer.h>
+#include <BufferManager.h>
+#include <BufferManager.h>
+#include <tangier/TngCursorPlane.h>
+#include <tangier/TngGrallocBuffer.h>
+#include <hal_public.h>
+
+namespace android {
+namespace intel {
+
+TngCursorPlane::TngCursorPlane(int index, int disp)
+ : DisplayPlane(index, PLANE_CURSOR, disp)
+{
+ CTRACE();
+ memset(&mContext, 0, sizeof(mContext));
+ memset(&mCrop, 0, sizeof(mCrop));
+}
+
+TngCursorPlane::~TngCursorPlane()
+{
+ CTRACE();
+}
+
+bool TngCursorPlane::enable()
+{
+ return enablePlane(true);
+}
+
+bool TngCursorPlane::disable()
+{
+ return enablePlane(false);
+}
+
+void* TngCursorPlane::getContext() const
+{
+ CTRACE();
+ return (void *)&mContext;
+}
+
+void TngCursorPlane::setZOrderConfig(ZOrderConfig& config, void *nativeConfig)
+{
+ (void) config;
+ (void) nativeConfig;
+
+ VTRACE("\n *** need to implement zorder config *** ");
+ CTRACE();
+}
+
+bool TngCursorPlane::setDataBuffer(buffer_handle_t handle)
+{
+ bool ret;
+
+ if (!handle) {
+ ETRACE("handle is NULL");
+ return false;
+ }
+
+ ret = DisplayPlane::setDataBuffer(handle);
+ if (ret == false) {
+ ETRACE("failed to set data buffer");
+ return ret;
+ }
+
+ return true;
+}
+
+bool TngCursorPlane::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;
+
+ 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 {
+ ETRACE("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 | (mIndex << 28);
+ 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 TngCursorPlane::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) {
+ WTRACE("plane enabling (%d) failed with error code %d", enabled, ret);
+ return false;
+ }
+
+ return true;
+}
+
+bool TngCursorPlane::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) {
+ WTRACE("plane state query failed with error code %d", ret);
+ return false;
+ }
+
+ return arg.plane.ctx == PSB_DC_PLANE_DISABLED;
+ //return arg.plane.ctx == 0; //implement this PSB_DC_PLANE_DISABLED similar in imin_legacy
+
+ return true;
+}
+
+void TngCursorPlane::postFlip()
+{
+ // prevent mUpdateMasks from being reset
+ // skipping flip may cause flicking
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/tangier/TngCursorPlane.h b/merrifield/ips/tangier/TngCursorPlane.h
new file mode 100644
index 0000000..85e869a
--- /dev/null
+++ b/merrifield/ips/tangier/TngCursorPlane.h
@@ -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.
+*/
+
+#ifndef TNG_CUR_PLANE_H
+#define TNG_CUR_PLANE_H
+
+#include <utils/KeyedVector.h>
+#include <hal_public.h>
+#include <Hwcomposer.h>
+#include <BufferCache.h>
+#include <DisplayPlane.h>
+
+#include <linux/psb_drm.h>
+
+namespace android {
+namespace intel {
+
+class TngCursorPlane : public DisplayPlane {
+public:
+ TngCursorPlane(int index, int disp);
+ virtual ~TngCursorPlane();
+public:
+ // hardware operations
+ bool enable();
+ bool disable();
+ bool isDisabled();
+ void postFlip();
+
+ void* getContext() const;
+ void setZOrderConfig(ZOrderConfig& config, void *nativeConfig);
+
+ bool setDataBuffer(buffer_handle_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 /* TNG_CUR_PLANE_H */
diff --git a/merrifield/ips/tangier/TngDisplayContext.cpp b/merrifield/ips/tangier/TngDisplayContext.cpp
new file mode 100644
index 0000000..7f94185
--- /dev/null
+++ b/merrifield/ips/tangier/TngDisplayContext.cpp
@@ -0,0 +1,278 @@
+/*
+// 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 <HwcTrace.h>
+#include <Hwcomposer.h>
+#include <Drm.h>
+#include <DisplayPlane.h>
+#include <IDisplayDevice.h>
+#include <HwcLayerList.h>
+#include <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) {
+ ETRACE("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) {
+ ETRACE("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) {
+ ETRACE("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) {
+ ETRACE("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) {
+ VTRACE("failed to flip plane %d", i);
+ continue;
+ }
+
+ IMG_hwc_layer_t *imgLayer = &imgLayerList[mCount++];
+ // update IMG layer
+ imgLayer->psLayer = &display->hwLayers[i];
+ imgLayer->custom = (unsigned long)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));
+ }
+
+ VTRACE("count %p, handle %#x, trans %#x, blending %#x"
+ " sourceCrop %f,%f - %fx%f, dst %d,%d - %dx%d, custom %#x",
+ mCount,
+ 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;
+
+ VTRACE("count = %d", mCount);
+
+ if (mIMGDisplayDevice && mCount) {
+ int err = mIMGDisplayDevice->post(mIMGDisplayDevice,
+ mImgLayers,
+ mCount,
+ &releaseFenceFd);
+ if (err) {
+ ETRACE("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 (unsigned int 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++) {
+ VTRACE("handle %#p, acquiredFD %d, releaseFD %d",
+ displays[i]->hwLayers[j].handle,
+ displays[i]->hwLayers[j].acquireFenceFd,
+ displays[i]->hwLayers[j].releaseFenceFd);
+ }
+
+#ifdef INTEL_WIDI_MERRIFIELD
+ // 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) {
+#endif
+ displays[i]->retireFenceFd =
+ (releaseFenceFd != -1) ? dup(releaseFenceFd) : -1;
+#ifdef INTEL_WIDI_MERRIFIELD
+ }
+#endif
+ }
+
+ // 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)
+{
+ DTRACE("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/merrifield/ips/tangier/TngDisplayContext.h b/merrifield/ips/tangier/TngDisplayContext.h
new file mode 100644
index 0000000..fa526d7
--- /dev/null
+++ b/merrifield/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/merrifield/ips/tangier/TngDisplayQuery.cpp b/merrifield/ips/tangier/TngDisplayQuery.cpp
new file mode 100644
index 0000000..c25aecf
--- /dev/null
+++ b/merrifield/ips/tangier/TngDisplayQuery.cpp
@@ -0,0 +1,63 @@
+/*
+// 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 <HwcTrace.h>
+#include <DisplayPlane.h>
+#include <hal_public.h>
+#include <OMX_IVCommon.h>
+#include <OMX_IntelVideoExt.h>
+#include <DisplayQuery.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;
+}
+
+} // namespace intel
+} // namespace android
+
diff --git a/merrifield/ips/tangier/TngGrallocBuffer.cpp b/merrifield/ips/tangier/TngGrallocBuffer.cpp
new file mode 100644
index 0000000..b66b896
--- /dev/null
+++ b/merrifield/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 <HwcTrace.h>
+#include <tangier/TngGrallocBuffer.h>
+
+namespace android {
+namespace intel {
+
+TngGrallocBuffer::TngGrallocBuffer(buffer_handle_t handle)
+ :GrallocBufferBase(handle)
+{
+ initBuffer(handle);
+}
+
+TngGrallocBuffer::~TngGrallocBuffer()
+{
+}
+
+void TngGrallocBuffer::resetBuffer(buffer_handle_t handle)
+{
+ GrallocBufferBase::resetBuffer(handle);
+ initBuffer(handle);
+}
+
+void TngGrallocBuffer::initBuffer(buffer_handle_t handle)
+{
+ TngIMGGrallocBuffer *grallocHandle = (TngIMGGrallocBuffer *)handle;
+
+ CTRACE();
+
+ if (!grallocHandle) {
+ ETRACE("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/merrifield/ips/tangier/TngGrallocBuffer.h b/merrifield/ips/tangier/TngGrallocBuffer.h
new file mode 100644
index 0000000..b528cf8
--- /dev/null
+++ b/merrifield/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 <common/GrallocSubBuffer.h>
+#include <common/GrallocBufferBase.h>
+
+namespace android {
+namespace intel {
+
+typedef IMG_native_handle_t TngIMGGrallocBuffer;
+
+class TngGrallocBuffer : public GrallocBufferBase {
+public:
+ TngGrallocBuffer(buffer_handle_t handle);
+ virtual ~TngGrallocBuffer();
+
+ void resetBuffer(buffer_handle_t handle);
+
+private:
+ void initBuffer(buffer_handle_t handle);
+};
+
+} // namespace intel
+} // namespace android
+
+
+#endif /* TNG_GRALLOC_BUFFER_H */
diff --git a/merrifield/ips/tangier/TngGrallocBufferMapper.cpp b/merrifield/ips/tangier/TngGrallocBufferMapper.cpp
new file mode 100644
index 0000000..fcf40e7
--- /dev/null
+++ b/merrifield/ips/tangier/TngGrallocBufferMapper.cpp
@@ -0,0 +1,263 @@
+/*
+// 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 <HwcTrace.h>
+#include <Drm.h>
+#include <Hwcomposer.h>
+#include <tangier/TngGrallocBufferMapper.h>
+#include <common/WsbmWrapper.h>
+
+namespace android {
+namespace intel {
+
+TngGrallocBufferMapper::TngGrallocBufferMapper(IMG_gralloc_module_public_t& module,
+ DataBuffer& buffer)
+ : GrallocBufferMapperBase(buffer),
+ mIMGGrallocModule(module),
+ mBufferObject(0)
+{
+ CTRACE();
+
+ const native_handle_t *h = (native_handle_t *)mHandle;
+
+ mClonedHandle = native_handle_create(h->numFds, h->numInts);
+ if (mClonedHandle == 0) {
+ ALOGE("%s:Failed to create handle, out of memory!");
+ return;
+ }
+ for (int i = 0; i < h->numFds; i++)
+ {
+ mClonedHandle->data[i] = (h->data[i] >= 0) ? dup(h->data[i]) : -1;
+ }
+ memcpy(mClonedHandle->data + h->numFds, h->data + h->numFds, h->numInts*sizeof(int));
+}
+
+TngGrallocBufferMapper::~TngGrallocBufferMapper()
+{
+ CTRACE();
+
+ if (mClonedHandle == 0)
+ return;
+ native_handle_close(mClonedHandle);
+ native_handle_delete(mClonedHandle);
+}
+
+bool TngGrallocBufferMapper::gttMap(void *vaddr,
+ uint32_t size,
+ uint32_t gttAlign,
+ int *offset)
+{
+ struct psb_gtt_mapping_arg arg;
+ bool ret;
+
+ ATRACE("vaddr = %p, size = %d", vaddr, size);
+
+ if (!vaddr || !size || !offset) {
+ VTRACE("invalid parameters");
+ return false;
+ }
+
+ arg.type = PSB_GTT_MAP_TYPE_VIRTUAL;
+ arg.page_align = gttAlign;
+ arg.vaddr = (unsigned long)vaddr;
+ arg.size = size;
+
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ ret = drm->writeReadIoctl(DRM_PSB_GTT_MAP, &arg, sizeof(arg));
+ if (ret == false) {
+ ETRACE("gtt mapping failed");
+ return false;
+ }
+
+ VTRACE("offset = %#x", arg.offset_pages);
+ *offset = arg.offset_pages;
+ return true;
+}
+
+bool TngGrallocBufferMapper::gttUnmap(void *vaddr)
+{
+ struct psb_gtt_mapping_arg arg;
+ bool ret;
+
+ ATRACE("vaddr = %p", vaddr);
+
+ if (!vaddr) {
+ ETRACE("invalid parameter");
+ return false;
+ }
+
+ arg.type = PSB_GTT_MAP_TYPE_VIRTUAL;
+ arg.vaddr = (unsigned long)vaddr;
+
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ ret = drm->writeIoctl(DRM_PSB_GTT_UNMAP, &arg, sizeof(arg));
+ if (ret == false) {
+ ETRACE("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)mClonedHandle,
+ vaddr,
+ size);
+ if (err) {
+ ETRACE("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) {
+ VTRACE("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)mClonedHandle);
+ 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)mClonedHandle);
+ if (err) {
+ ETRACE("failed to unmap. err = %d", err);
+ }
+ return err;
+}
+
+buffer_handle_t TngGrallocBufferMapper::getKHandle(int subIndex)
+{
+ buffer_handle_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((uint64_t)mHandle, &wsbmBufferObject);
+ if (ret != 0) {
+ ETRACE("Wrap ttm buffer failed!");
+ return false;
+ }
+
+ ret = psbWsbmCreateFromUB(wsbmBufferObject, mWidth * mHeight, mCpuAddress[0]);
+ if (ret != 0) {
+ ETRACE("Create from UB failed!");
+ return false;
+ }
+
+ mKHandle[0] = (buffer_handle_t)(unsigned long)psbWsbmGetKBufHandle(wsbmBufferObject);
+ psbWsbmUnReference(wsbmBufferObject);
+ return true;
+}
+
+buffer_handle_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)mClonedHandle,
+ vaddr,
+ size);
+ if (err) {
+ ETRACE("failed to map. err = %d", err);
+ return 0;
+ }
+
+ return (buffer_handle_t)vaddr[subIndex];
+}
+
+void TngGrallocBufferMapper::putFbHandle()
+{
+ int err = mIMGGrallocModule.putCpuAddress(&mIMGGrallocModule,
+ (buffer_handle_t)mClonedHandle);
+ if (err) {
+ ETRACE("failed to unmap. err = %d", err);
+ }
+ return;
+
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/tangier/TngGrallocBufferMapper.h b/merrifield/ips/tangier/TngGrallocBufferMapper.h
new file mode 100644
index 0000000..d72005e
--- /dev/null
+++ b/merrifield/ips/tangier/TngGrallocBufferMapper.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 TNG_GRALLOC_BUFFER_MAPPER_H
+#define TNG_GRALLOC_BUFFER_MAPPER_H
+
+#include <BufferMapper.h>
+#include <hal_public.h>
+#include <common/GrallocBufferMapperBase.h>
+#include <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();
+ buffer_handle_t getKHandle(int subIndex);
+ buffer_handle_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;
+ native_handle_t* mClonedHandle;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* TNG_GRALLOC_BUFFER_MAPPER_H */
diff --git a/merrifield/ips/tangier/TngOverlayPlane.cpp b/merrifield/ips/tangier/TngOverlayPlane.cpp
new file mode 100644
index 0000000..d837015
--- /dev/null
+++ b/merrifield/ips/tangier/TngOverlayPlane.cpp
@@ -0,0 +1,218 @@
+/*
+// 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 <HwcTrace.h>
+#include <Drm.h>
+#include <Hwcomposer.h>
+#include <tangier/TngOverlayPlane.h>
+#include <tangier/TngGrallocBuffer.h>
+
+namespace android {
+namespace intel {
+
+TngOverlayPlane::TngOverlayPlane(int index, int disp)
+ : OverlayPlaneBase(index, disp),
+ mRotationBufProvider(NULL)
+{
+ CTRACE();
+
+ memset(&mContext, 0, sizeof(mContext));
+}
+
+TngOverlayPlane::~TngOverlayPlane()
+{
+ CTRACE();
+}
+
+bool TngOverlayPlane::flip(void *ctx)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ if (!DisplayPlane::flip(ctx))
+ return false;
+
+ mContext.type = DC_OVERLAY_PLANE;
+ mContext.ctx.ov_ctx.ovadd = 0x0;
+ mContext.ctx.ov_ctx.ovadd = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
+ mContext.ctx.ov_ctx.index = mIndex;
+ mContext.ctx.ov_ctx.pipe = mDevice;
+ mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
+ mContext.ctx.ov_ctx.ovadd |= 0x1;
+
+ // move to next back buffer
+ //mCurrent = (mCurrent + 1) % OVERLAY_BACK_BUFFER_COUNT;
+
+ VTRACE("ovadd = %#x, index = %d, device = %d",
+ mContext.ctx.ov_ctx.ovadd,
+ mIndex,
+ mDevice);
+
+ return true;
+}
+
+bool TngOverlayPlane::reset()
+{
+ OverlayPlaneBase::reset();
+ if (mRotationBufProvider)
+ mRotationBufProvider->reset();
+ return true;
+}
+
+void* TngOverlayPlane::getContext() const
+{
+ CTRACE();
+ return (void *)&mContext;
+}
+
+bool TngOverlayPlane::setDataBuffer(BufferMapper& mapper)
+{
+ if (OverlayPlaneBase::setDataBuffer(mapper) == false) {
+ return false;
+ }
+
+ 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;
+ }
+
+ mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0);
+ return true;
+}
+
+bool TngOverlayPlane::initialize(uint32_t bufferCount)
+{
+ if (!OverlayPlaneBase::initialize(bufferCount)) {
+ ETRACE("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 TngOverlayPlane::deinitialize()
+{
+ DEINIT_AND_DELETE_OBJ(mRotationBufProvider);
+ OverlayPlaneBase::deinitialize();
+}
+
+bool TngOverlayPlane::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper)
+{
+ struct VideoPayloadBuffer *payload;
+ VideoPayloadBuffer buffer_info;
+ uint32_t format;
+ // only NV12_VED has rotated buffer
+ format = mapper.getFormat();
+
+ if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
+ format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled &&
+ format != HAL_PIXEL_FORMAT_NV12) {
+ ETRACE("Invalid video format %#x", format);
+ return false;
+ }
+
+ payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
+
+ if (payload == NULL && format == HAL_PIXEL_FORMAT_NV12) {
+ // need to populate buffer_info
+ void *p = mapper.getCpuAddress(SUB_BUFFER0);
+ if (!p) {
+ ETRACE("failed to get buffer user pointer");
+ return false;
+ }
+
+ bool ret = mRotationBufProvider->prepareBufferInfo(mapper.getWidth(),
+ mapper.getHeight(),
+ mapper.getStride().yuv.yStride,
+ &buffer_info, p);
+ if (ret == false) {
+ ETRACE("failed to prepare buffer info");
+ return false;
+ }
+ payload = &buffer_info;
+ }
+
+ // check payload
+ if (!payload) {
+ ETRACE("no payload found");
+ return false;
+ }
+
+ if (payload->force_output_method == FORCE_OUTPUT_GPU) {
+ ETRACE("Output method is not supported!");
+ return false;
+ }
+
+ if (payload->client_transform != mTransform ||
+ mBobDeinterlace) {
+ payload->hwc_timestamp = systemTime();
+ payload->layer_transform = mTransform;
+ if (!mRotationBufProvider->setupRotationBuffer(payload, mTransform)) {
+ ETRACE("failed to setup rotation buffer");
+ return false;
+ }
+ }
+
+ rotatedMapper = getTTMMapper(mapper, payload);
+
+ return true;
+}
+
+bool TngOverlayPlane::flush(uint32_t flags)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+ ATRACE("flags = %#x, type = %d, index = %d", flags, mType, mIndex);
+
+ if (!(flags & PLANE_ENABLE) && !(flags & PLANE_DISABLE))
+ 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 = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
+ // pipe select
+ arg.plane.ctx |= mPipeConfig;
+
+ if (flags & PLANE_DISABLE) {
+ DTRACE("disabling overlay %d on device %d", mIndex, mDevice);
+ }
+
+ // issue ioctl
+ Drm *drm = Hwcomposer::getInstance().getDrm();
+ bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
+ if (ret == false) {
+ WTRACE("overlay update failed with error code %d", ret);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/tangier/TngOverlayPlane.h b/merrifield/ips/tangier/TngOverlayPlane.h
new file mode 100644
index 0000000..9129965
--- /dev/null
+++ b/merrifield/ips/tangier/TngOverlayPlane.h
@@ -0,0 +1,55 @@
+/*
+// 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_OVERLAY_PLANE_H
+#define TNG_OVERLAY_PLANE_H
+
+#include <utils/KeyedVector.h>
+#include <hal_public.h>
+#include <DisplayPlane.h>
+#include <BufferMapper.h>
+#include <common/Wsbm.h>
+#include <common/OverlayPlaneBase.h>
+#include <common/RotationBufferProvider.h>
+
+namespace android {
+namespace intel {
+
+class TngOverlayPlane : public OverlayPlaneBase {
+
+public:
+ TngOverlayPlane(int index, int disp);
+ virtual ~TngOverlayPlane();
+
+ virtual bool flip(void *ctx);
+ virtual bool reset();
+ virtual void* getContext() const;
+
+ virtual bool initialize(uint32_t bufferCount);
+ virtual void deinitialize();
+ virtual bool rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper);
+protected:
+ virtual bool setDataBuffer(BufferMapper& mapper);
+ virtual bool flush(uint32_t flags);
+
+protected:
+ struct intel_dc_plane_ctx mContext;
+ RotationBufferProvider *mRotationBufProvider;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* TNG_OVERLAY_PLANE_H */
diff --git a/merrifield/ips/tangier/TngPlaneManager.cpp b/merrifield/ips/tangier/TngPlaneManager.cpp
new file mode 100644
index 0000000..d973aa9
--- /dev/null
+++ b/merrifield/ips/tangier/TngPlaneManager.cpp
@@ -0,0 +1,196 @@
+/*
+// 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 <HwcTrace.h>
+#include <tangier/TngPlaneManager.h>
+#include <tangier/TngPrimaryPlane.h>
+#include <tangier/TngSpritePlane.h>
+#include <tangier/TngOverlayPlane.h>
+#include <tangier/TngCursorPlane.h>
+
+namespace android {
+namespace intel {
+
+TngPlaneManager::TngPlaneManager()
+ : DisplayPlaneManager()
+{
+ memset(&mZorder, 0, sizeof(mZorder));
+}
+
+TngPlaneManager::~TngPlaneManager()
+{
+}
+
+bool TngPlaneManager::initialize()
+{
+ mSpritePlaneCount = 1; // Sprite D
+ mOverlayPlaneCount = 2; // Overlay A & C
+ mPrimaryPlaneCount = 3; // Primary A, B, C
+ mCursorPlaneCount = 3;
+
+ return DisplayPlaneManager::initialize();
+}
+
+void TngPlaneManager::deinitialize()
+{
+ DisplayPlaneManager::deinitialize();
+}
+
+DisplayPlane* TngPlaneManager::allocPlane(int index, int type)
+{
+ DisplayPlane *plane = 0;
+
+ switch (type) {
+ case DisplayPlane::PLANE_PRIMARY:
+ plane = new TngPrimaryPlane(index, index);
+ break;
+ case DisplayPlane::PLANE_SPRITE:
+ plane = new TngSpritePlane(index, 0);
+ break;
+ case DisplayPlane::PLANE_OVERLAY:
+ plane = new TngOverlayPlane(index, 0);
+ break;
+ case DisplayPlane::PLANE_CURSOR:
+ plane = new TngCursorPlane(index, index /*disp */);
+ break;
+ default:
+ ETRACE("unsupported type %d", type);
+ break;
+ }
+ if (plane && !plane->initialize(DisplayPlane::MIN_DATA_BUFFER_COUNT)) {
+ ETRACE("failed to initialize plane.");
+ DEINIT_AND_DELETE_OBJ(plane);
+ }
+
+ return plane;
+}
+
+bool TngPlaneManager::isValidZOrder(int dsp, ZOrderConfig& config)
+{
+ // check whether it's a supported z order config
+ int firstRGB = -1;
+ int lastRGB = -1;
+ int firstOverlay = -1;
+ int lastOverlay = -1;
+
+ for (int i = 0; i < (int)config.size(); i++) {
+ const ZOrderLayer *layer = config[i];
+ switch (layer->planeType) {
+ case DisplayPlane::PLANE_PRIMARY:
+ case DisplayPlane::PLANE_SPRITE:
+ if (firstRGB == -1) {
+ firstRGB = i;
+ lastRGB = i;
+ } else {
+ lastRGB = i;
+ }
+ break;
+ case DisplayPlane::PLANE_OVERLAY:
+ case DisplayPlane::PLANE_CURSOR:
+ if (firstOverlay == -1) {
+ firstOverlay = i;
+ lastOverlay = i;
+ } else {
+ lastOverlay = i;
+ }
+ break;
+ }
+ }
+
+ if ((lastRGB < firstOverlay) || (firstRGB > lastOverlay)) {
+ return true;
+ } else {
+ VTRACE("invalid z order config. rgb (%d, %d) yuv (%d, %d)",
+ firstRGB, lastRGB, firstOverlay, lastOverlay);
+ return false;
+ }
+}
+
+bool TngPlaneManager::assignPlanes(int dsp, ZOrderConfig& config)
+{
+ // probe if plane is available
+ int size = (int)config.size();
+ for (int i = 0; i < size; i++) {
+ const ZOrderLayer *layer = config.itemAt(i);
+ if (!getFreePlanes(dsp, layer->planeType)) {
+ DTRACE("no plane available for dsp %d, type %d", dsp, layer->planeType);
+ return false;
+ }
+ }
+
+ if (config.size() == 1 && config[0]->planeType == DisplayPlane::PLANE_SPRITE) {
+ config[0]->planeType == DisplayPlane::PLANE_PRIMARY;
+ }
+
+ // allocate planes
+ for (int i = 0; i < size; i++) {
+ ZOrderLayer *layer = config.itemAt(i);
+ layer->plane = getPlaneHelper(dsp, layer->planeType);
+ if (layer->plane == NULL) {
+ // should never happen!!
+ ETRACE("failed to assign plane for type %d", layer->planeType);
+ return false;
+ }
+ // sequence !!!!! enabling plane before setting zorder
+ // see TngSpritePlane::enablePlane implementation!!!!
+ layer->plane->enable();
+ }
+
+ // setup Z order
+ for (int i = 0; i < size; i++) {
+ ZOrderLayer *layer = config.itemAt(i);
+ layer->plane->setZOrderConfig(config, &mZorder);
+ }
+
+ return true;
+}
+
+void* TngPlaneManager::getZOrderConfig() const
+{
+ return (void*)&mZorder;
+}
+
+DisplayPlane* TngPlaneManager::getPlaneHelper(int dsp, int type)
+{
+ RETURN_NULL_IF_NOT_INIT();
+
+ if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
+ ETRACE("Invalid display device %d", dsp);
+ return 0;
+ }
+
+ int index = dsp == IDisplayDevice::DEVICE_PRIMARY ? 0 : 1;
+
+ if (type == DisplayPlane::PLANE_PRIMARY ||
+ type == DisplayPlane::PLANE_CURSOR) {
+ return getPlane(type, index);
+ } else if (type == DisplayPlane::PLANE_SPRITE) {
+ return getAnyPlane(type);
+ } else if (type == DisplayPlane::PLANE_OVERLAY) {
+ // use overlay A for pipe A and overlay C for pipe B if possible
+ DisplayPlane *plane = getPlane(type, index);
+ if (plane == NULL) {
+ plane = getPlane(type, !index);
+ }
+ return plane;
+ } else {
+ ETRACE("invalid plane type %d", type);
+ return 0;
+ }
+}
+
+} // namespace intel
+} // namespace android
+
diff --git a/merrifield/ips/tangier/TngPlaneManager.h b/merrifield/ips/tangier/TngPlaneManager.h
new file mode 100644
index 0000000..e6717bb
--- /dev/null
+++ b/merrifield/ips/tangier/TngPlaneManager.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_PLANE_MANAGER_H
+#define TNG_PLANE_MANAGER_H
+
+#include <DisplayPlaneManager.h>
+#include <linux/psb_drm.h>
+
+namespace android {
+namespace intel {
+
+class TngPlaneManager : public DisplayPlaneManager {
+public:
+ TngPlaneManager();
+ virtual ~TngPlaneManager();
+
+public:
+ virtual bool initialize();
+ virtual void deinitialize();
+ virtual bool isValidZOrder(int dsp, ZOrderConfig& config);
+ virtual bool assignPlanes(int dsp, ZOrderConfig& config);
+ // TODO: remove this API
+ virtual void* getZOrderConfig() const;
+
+protected:
+ DisplayPlane* allocPlane(int index, int type);
+ DisplayPlane* getPlaneHelper(int dsp, int type);
+
+private:
+ struct intel_dc_plane_zorder mZorder;
+};
+
+} // namespace intel
+} // namespace android
+
+
+#endif /* TNG_PLANE_MANAGER_H */
diff --git a/merrifield/ips/tangier/TngPrimaryPlane.cpp b/merrifield/ips/tangier/TngPrimaryPlane.cpp
new file mode 100644
index 0000000..7d72f0f
--- /dev/null
+++ b/merrifield/ips/tangier/TngPrimaryPlane.cpp
@@ -0,0 +1,167 @@
+/*
+// 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 <HwcTrace.h>
+#include <Drm.h>
+#include <tangier/TngPrimaryPlane.h>
+#include <tangier/TngGrallocBuffer.h>
+#include <common/PixelFormat.h>
+
+namespace android {
+namespace intel {
+
+TngPrimaryPlane::TngPrimaryPlane(int index, int disp)
+ : TngSpritePlane(index, disp)
+{
+ CTRACE();
+ mType = PLANE_PRIMARY;
+ mForceBottom = true;
+ mAbovePrimary = false;
+}
+
+TngPrimaryPlane::~TngPrimaryPlane()
+{
+ CTRACE();
+}
+
+void TngPrimaryPlane::setFramebufferTarget(buffer_handle_t handle)
+{
+ 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
+ mContext.type = DC_PRIMARY_PLANE;
+ mContext.ctx.prim_ctx.update_mask = SPRITE_UPDATE_ALL;
+ mContext.ctx.prim_ctx.index = mIndex;
+ mContext.ctx.prim_ctx.pipe = mDevice;
+ mContext.ctx.prim_ctx.linoff = 0;
+ mContext.ctx.prim_ctx.stride = align_to((4 * align_to(mPosition.w, 32)), 64);
+ 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 = 0;
+
+ mContext.ctx.prim_ctx.cntr = PixelFormat::PLANE_PIXEL_FORMAT_BGRA8888;
+ mContext.ctx.prim_ctx.cntr |= 0x80000000;
+
+ mCurrentDataBuffer = handle;
+}
+
+bool TngPrimaryPlane::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_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) {
+ WTRACE("primary enabling (%d) failed with error code %d", enabled, ret);
+ return false;
+ }
+
+ return true;
+
+}
+
+bool TngPrimaryPlane::setDataBuffer(buffer_handle_t handle)
+{
+ if (!handle) {
+ setFramebufferTarget(handle);
+ return true;
+ }
+
+ TngGrallocBuffer tmpBuf(handle);
+ uint32_t usage;
+ bool ret;
+
+ ATRACE("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) {
+ ETRACE("failed to set data buffer");
+ return ret;
+ }
+
+ mContext.type = DC_PRIMARY_PLANE;
+ return true;
+}
+
+void TngPrimaryPlane::setZOrderConfig(ZOrderConfig& zorderConfig,
+ void *nativeConfig)
+{
+ if (!nativeConfig) {
+ ETRACE("Invalid parameter, no native config");
+ return;
+ }
+
+ mForceBottom = false;
+
+ int primaryIndex = -1;
+ int overlayIndex = -1;
+ // only consider force bottom when overlay is active
+ for (size_t i = 0; i < zorderConfig.size(); i++) {
+ DisplayPlane *plane = zorderConfig[i]->plane;
+ if (plane->getType() == DisplayPlane::PLANE_PRIMARY)
+ primaryIndex = i;
+ if (plane->getType() == DisplayPlane::PLANE_OVERLAY) {
+ overlayIndex = i;
+ }
+ }
+
+ // if has overlay plane which is below primary plane
+ if (overlayIndex > primaryIndex) {
+ mForceBottom = true;
+ }
+
+ struct intel_dc_plane_zorder *zorder =
+ (struct intel_dc_plane_zorder *)nativeConfig;
+ zorder->forceBottom[mIndex] = mForceBottom ? 1 : 0;
+}
+
+bool TngPrimaryPlane::assignToDevice(int disp)
+{
+ return true;
+}
+
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/tangier/TngPrimaryPlane.h b/merrifield/ips/tangier/TngPrimaryPlane.h
new file mode 100644
index 0000000..22dbbd3
--- /dev/null
+++ b/merrifield/ips/tangier/TngPrimaryPlane.h
@@ -0,0 +1,40 @@
+/*
+// 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_PRIMARY_PLANE_H
+#define TNG_PRIMARY_PLANE_H
+
+#include <tangier/TngSpritePlane.h>
+
+namespace android {
+namespace intel {
+
+class TngPrimaryPlane : public TngSpritePlane {
+public:
+ TngPrimaryPlane(int index, int disp);
+ virtual ~TngPrimaryPlane();
+public:
+ bool setDataBuffer(buffer_handle_t handle);
+ void setZOrderConfig(ZOrderConfig& config, void *nativeConfig);
+ bool assignToDevice(int disp);
+private:
+ void setFramebufferTarget(buffer_handle_t handle);
+ bool enablePlane(bool enabled);
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* TNG_PRIMARY_PLANE_H */
diff --git a/merrifield/ips/tangier/TngSpritePlane.cpp b/merrifield/ips/tangier/TngSpritePlane.cpp
new file mode 100644
index 0000000..c4e7e2c
--- /dev/null
+++ b/merrifield/ips/tangier/TngSpritePlane.cpp
@@ -0,0 +1,215 @@
+/*
+// 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 <HwcTrace.h>
+#include <Hwcomposer.h>
+#include <BufferManager.h>
+#include <tangier/TngSpritePlane.h>
+#include <common/PixelFormat.h>
+
+namespace android {
+namespace intel {
+
+TngSpritePlane::TngSpritePlane(int index, int disp)
+ : SpritePlaneBase(index, disp)
+{
+ CTRACE();
+ memset(&mContext, 0, sizeof(mContext));
+}
+
+TngSpritePlane::~TngSpritePlane()
+{
+ CTRACE();
+}
+
+bool TngSpritePlane::setDataBuffer(BufferMapper& mapper)
+{
+ int bpp;
+ int srcX, srcY;
+ int dstX, dstY, dstW, dstH;
+ uint32_t spriteFormat;
+ uint32_t stride;
+ uint32_t linoff;
+ uint32_t planeAlpha;
+
+ 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)) {
+ ETRACE("unsupported format %#x", mapper.getFormat());
+ return false;
+ }
+
+ // setup stride and source buffer crop
+ srcX = mapper.getCrop().x;
+ srcY = mapper.getCrop().y;
+ stride = mapper.getStride().rgb.stride;
+ linoff = srcY * stride + srcX * bpp;
+
+ // setup plane alpha
+ if ((mBlending == HWC_BLENDING_PREMULT) && (mPlaneAlpha == 0)) {
+ planeAlpha = mPlaneAlpha | 0x80000000;
+ } else {
+ // disable plane alpha to offload HW
+ planeAlpha = 0;
+ }
+
+ // unlikely happen, but still we need make sure linoff is valid
+ if (linoff > (stride * mapper.getHeight())) {
+ ETRACE("invalid source crop");
+ return false;
+ }
+
+ // update context
+ mContext.type = DC_SPRITE_PLANE;
+ mContext.ctx.sp_ctx.index = mIndex;
+ mContext.ctx.sp_ctx.pipe = mDevice;
+ // none blending and BRGA format layer,set format to BGRX8888
+ if (mBlending == HWC_BLENDING_NONE && spriteFormat == PixelFormat::PLANE_PIXEL_FORMAT_BGRA8888)
+ mContext.ctx.sp_ctx.cntr = PixelFormat::PLANE_PIXEL_FORMAT_BGRX8888
+ | 0x80000000;
+ else
+ mContext.ctx.sp_ctx.cntr = spriteFormat | 0x80000000;
+ mContext.ctx.sp_ctx.linoff = linoff;
+ mContext.ctx.sp_ctx.stride = stride;
+ mContext.ctx.sp_ctx.surf = mapper.getGttOffsetInPage(0) << 12;
+ 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;
+ mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0);
+
+ VTRACE("cntr = %#x, linoff = %#x, stride = %#x,"
+ "surf = %#x, pos = %#x, size = %#x, contalpa = %#x",
+ 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;
+}
+
+void* TngSpritePlane::getContext() const
+{
+ CTRACE();
+ return (void *)&mContext;
+}
+
+bool TngSpritePlane::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_SPRITE_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) {
+ WTRACE("sprite enabling (%d) failed with error code %d", enabled, ret);
+ return false;
+ }
+
+ Hwcomposer& hwc = Hwcomposer::getInstance();
+ DisplayPlaneManager *pm = hwc.getPlaneManager();
+ void *config = pm->getZOrderConfig();
+ if (config != NULL) {
+ struct intel_dc_plane_zorder *zorder = (struct intel_dc_plane_zorder *)config;
+ zorder->abovePrimary = 0;
+ }
+
+ return true;
+
+}
+
+bool TngSpritePlane::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 == DisplayPlane::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) {
+ WTRACE("plane state query failed with error code %d", ret);
+ return false;
+ }
+
+ return arg.plane.ctx == PSB_DC_PLANE_DISABLED;
+}
+
+void TngSpritePlane::setZOrderConfig(ZOrderConfig& zorderConfig,
+ void *nativeConfig)
+{
+ if (!nativeConfig) {
+ ETRACE("Invalid parameter, no native config");
+ return;
+ }
+
+ mAbovePrimary = false;
+
+ int primaryIndex = -1;
+ int spriteIndex = -1;
+ // only consider force bottom when overlay is active
+ for (size_t i = 0; i < zorderConfig.size(); i++) {
+ DisplayPlane *plane = zorderConfig[i]->plane;
+ if (plane->getType() == DisplayPlane::PLANE_PRIMARY)
+ primaryIndex = i;
+ if (plane->getType() == DisplayPlane::PLANE_SPRITE) {
+ spriteIndex = i;
+ }
+ }
+
+ // if has overlay plane which is below primary plane
+ if (spriteIndex > primaryIndex) {
+ mAbovePrimary = true;
+ }
+
+ struct intel_dc_plane_zorder *zorder =
+ (struct intel_dc_plane_zorder *)nativeConfig;
+ zorder->abovePrimary = mAbovePrimary ? 1 : 0;
+}
+} // namespace intel
+} // namespace android
diff --git a/merrifield/ips/tangier/TngSpritePlane.h b/merrifield/ips/tangier/TngSpritePlane.h
new file mode 100644
index 0000000..1c6bcdc
--- /dev/null
+++ b/merrifield/ips/tangier/TngSpritePlane.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 TNG_SPRITE_PLANE_H
+#define TNG_SPRITE_PLANE_H
+
+#include <utils/KeyedVector.h>
+#include <hal_public.h>
+#include <Hwcomposer.h>
+#include <BufferCache.h>
+#include <DisplayPlane.h>
+
+#include <common/SpritePlaneBase.h>
+
+namespace android {
+namespace intel {
+
+class TngSpritePlane : public SpritePlaneBase {
+public:
+ TngSpritePlane(int index, int disp);
+ virtual ~TngSpritePlane();
+public:
+ virtual void* getContext() const;
+ virtual void setZOrderConfig(ZOrderConfig& config, void *nativeConfig);
+ virtual bool isDisabled();
+protected:
+ virtual bool setDataBuffer(BufferMapper& mapper);
+ virtual bool enablePlane(bool enabled);
+protected:
+ struct intel_dc_plane_ctx mContext;
+};
+
+} // namespace intel
+} // namespace android
+
+#endif /* TNG_SPRITE_PLANE_H */