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