liboverlay: Add support for MDSS Rotator.

Acked-by: Sushil Chauhan <sushilchauhan@codeaurora.org>

Change-Id: I60a2b0ce2b491d03b2b1a04966113e253b7f3dd8
diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk
index bb83111..3c1057d 100644
--- a/liboverlay/Android.mk
+++ b/liboverlay/Android.mk
@@ -5,7 +5,7 @@
 LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libmemalloc
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libmemalloc
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"overlay\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES := \
@@ -13,6 +13,8 @@
       overlayCtrl.cpp \
       overlayUtils.cpp \
       overlayMdp.cpp \
-      overlayRotator.cpp
+      overlayRotator.cpp \
+      mdpRotator.cpp \
+      mdssRotator.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/liboverlay/mdpRotator.cpp b/liboverlay/mdpRotator.cpp
new file mode 100755
index 0000000..18d1bec
--- /dev/null
+++ b/liboverlay/mdpRotator.cpp
@@ -0,0 +1,210 @@
+/*
+* Copyright (C) 2008 The Android Open Source Project
+* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+*
+* 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 "overlayUtils.h"
+#include "overlayRotator.h"
+
+namespace ovutils = overlay::utils;
+
+namespace overlay {
+
+bool MdpRot::init()
+{
+    if(!mFd.open(Res::rotPath, O_RDWR)){
+        ALOGE("MdpRot failed to init %s", Res::rotPath);
+        return false;
+    }
+    return true;
+}
+
+void MdpRot::setSource(const overlay::utils::Whf& awhf) {
+    utils::Whf whf(awhf);
+
+    mRotImgInfo.src.format = whf.format;
+    if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
+        whf.format == MDP_Y_CBCR_H2V2_TILE) {
+        whf.w =  utils::alignup(awhf.w, 64);
+        whf.h = utils::alignup(awhf.h, 32);
+    }
+
+    mRotImgInfo.src.width = whf.w;
+    mRotImgInfo.src.height = whf.h;
+
+    mRotImgInfo.src_rect.w = whf.w;
+    mRotImgInfo.src_rect.h = whf.h;
+
+    mRotImgInfo.dst.width = whf.w;
+    mRotImgInfo.dst.height = whf.h;
+
+    mBufSize = awhf.size;
+}
+
+void MdpRot::setFlags(const utils::eMdpFlags& flags) {
+    mRotImgInfo.secure = 0;
+    if(flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
+        mRotImgInfo.secure = 1;
+}
+
+void MdpRot::setTransform(const utils::eTransform& rot, const bool& rotUsed)
+{
+    int r = utils::getMdpOrient(rot);
+    setRotations(r);
+    //getMdpOrient will switch the flips if the source is 90 rotated.
+    //Clients in Android dont factor in 90 rotation while deciding the flip.
+    mOrientation = static_cast<utils::eTransform>(r);
+    ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r);
+
+    setDisable();
+    if(rotUsed) {
+        setEnable();
+    }
+}
+
+void MdpRot::doTransform() {
+    if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90)
+        utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height);
+}
+
+bool MdpRot::commit() {
+    doTransform();
+    if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) {
+        ALOGE("MdpRot commit failed");
+        dump();
+        return false;
+    }
+    mRotDataInfo.session_id = mRotImgInfo.session_id;
+    return true;
+}
+
+bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz)
+{
+    OvMem mem;
+
+    OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
+
+    if(!mem.open(numbufs, bufsz, mRotImgInfo.secure)){
+        ALOGE("%s: Failed to open", __func__);
+        mem.close();
+        return false;
+    }
+
+    OVASSERT(MAP_FAILED != mem.addr(), "MAP failed");
+    OVASSERT(mem.getFD() != -1, "getFd is -1");
+
+    mRotDataInfo.dst.memory_id = mem.getFD();
+    mRotDataInfo.dst.offset = 0;
+    mMem.curr().m = mem;
+    return true;
+}
+
+bool MdpRot::close() {
+    bool success = true;
+    if(mFd.valid() && (getSessId() > 0)) {
+        if(!mdp_wrapper::endRotator(mFd.getFD(), getSessId())) {
+            ALOGE("Mdp Rot error endRotator, fd=%d sessId=%d",
+                    mFd.getFD(), getSessId());
+            success = false;
+        }
+    }
+    if (!mFd.close()) {
+        ALOGE("Mdp Rot error closing fd");
+        success = false;
+    }
+    if (!mMem.close()) {
+        ALOGE("Mdp Rot error closing mem");
+        success = false;
+    }
+    reset();
+    return success;
+}
+
+bool MdpRot::remap(uint32_t numbufs) {
+    // if current size changed, remap
+    if(mBufSize == mMem.curr().size()) {
+        ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, mBufSize);
+        return true;
+    }
+
+    ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
+    OVASSERT(!mMem.prev().valid(), "Prev should not be valid");
+
+    // ++mMem will make curr to be prev, and prev will be curr
+    ++mMem;
+    if(!open_i(numbufs, mBufSize)) {
+        ALOGE("%s Error could not open", __FUNCTION__);
+        return false;
+    }
+    for (uint32_t i = 0; i < numbufs; ++i) {
+        mMem.curr().mRotOffset[i] = i * mBufSize;
+    }
+    return true;
+}
+
+void MdpRot::reset() {
+    ovutils::memset0(mRotImgInfo);
+    ovutils::memset0(mRotDataInfo);
+    ovutils::memset0(mMem.curr().mRotOffset);
+    ovutils::memset0(mMem.prev().mRotOffset);
+    mMem.curr().mCurrOffset = 0;
+    mMem.prev().mCurrOffset = 0;
+    mBufSize = 0;
+    mOrientation = utils::OVERLAY_TRANSFORM_0;
+}
+
+bool MdpRot::queueBuffer(int fd, uint32_t offset) {
+    if(enabled()) {
+        mRotDataInfo.src.memory_id = fd;
+        mRotDataInfo.src.offset = offset;
+
+        remap(RotMem::Mem::ROT_NUM_BUFS);
+        OVASSERT(mMem.curr().m.numBufs(),
+                "queueBuffer numbufs is 0");
+        mRotDataInfo.dst.offset =
+                mMem.curr().mRotOffset[mMem.curr().mCurrOffset];
+        mMem.curr().mCurrOffset =
+                (mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs();
+
+        if(!overlay::mdp_wrapper::rotate(mFd.getFD(), mRotDataInfo)) {
+            ALOGE("MdpRot failed rotate");
+            dump();
+            return false;
+        }
+
+        // if the prev mem is valid, we need to close
+        if(mMem.prev().valid()) {
+            // FIXME if no wait for vsync the above
+            // play will return immediatly and might cause
+            // tearing when prev.close is called.
+            if(!mMem.prev().close()) {
+                ALOGE("%s error in closing prev rot mem", __FUNCTION__);
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+void MdpRot::dump() const {
+    ALOGE("== Dump MdpRot start ==");
+    mFd.dump();
+    mMem.curr().m.dump();
+    mdp_wrapper::dump("mRotImgInfo", mRotImgInfo);
+    mdp_wrapper::dump("mRotDataInfo", mRotDataInfo);
+    ALOGE("== Dump MdpRot end ==");
+}
+
+} // namespace overlay
diff --git a/liboverlay/mdssRotator.cpp b/liboverlay/mdssRotator.cpp
new file mode 100755
index 0000000..16b866a
--- /dev/null
+++ b/liboverlay/mdssRotator.cpp
@@ -0,0 +1,211 @@
+/*
+* Copyright (C) 2008 The Android Open Source Project
+* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+*
+* 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 "overlayUtils.h"
+#include "overlayRotator.h"
+
+namespace ovutils = overlay::utils;
+
+namespace overlay {
+
+bool MdssRot::init() {
+    if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) {
+        ALOGE("MdssRot failed to init fb0");
+        return false;
+    }
+    return true;
+}
+
+void MdssRot::setSource(const overlay::utils::Whf& awhf) {
+    utils::Whf whf(awhf);
+
+    mRotInfo.src.format = whf.format;
+    if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
+        whf.format == MDP_Y_CBCR_H2V2_TILE) {
+        whf.w =  utils::alignup(awhf.w, 64);
+        whf.h = utils::alignup(awhf.h, 32);
+    }
+
+    mRotInfo.src.width = whf.w;
+    mRotInfo.src.height = whf.h;
+
+    mRotInfo.src_rect.w = whf.w;
+    mRotInfo.src_rect.h = whf.h;
+
+    mRotInfo.dst_rect.w = whf.w;
+    mRotInfo.dst_rect.h = whf.h;
+
+    mBufSize = awhf.size;
+}
+
+void MdssRot::setFlags(const utils::eMdpFlags& flags) {
+    // TODO
+}
+
+void MdssRot::setTransform(const utils::eTransform& rot, const bool& rotUsed)
+{
+    int flags = utils::getMdpOrient(rot);
+    if (flags != -1)
+        setRotations(flags);
+    //getMdpOrient will switch the flips if the source is 90 rotated.
+    //Clients in Android dont factor in 90 rotation while deciding the flip.
+    mOrientation = static_cast<utils::eTransform>(flags);
+    ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags);
+
+    setDisable();
+    if(rotUsed) {
+        setEnable();
+    }
+}
+
+void MdssRot::doTransform() {
+    if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90)
+        utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h);
+}
+
+bool MdssRot::commit() {
+    doTransform();
+    mRotInfo.flags |= MDSS_MDP_ROT_ONLY;
+    if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) {
+        ALOGE("MdssRot commit failed!");
+        dump();
+        return false;
+    }
+    mRotData.id = mRotInfo.id;
+    return true;
+}
+
+bool MdssRot::queueBuffer(int fd, uint32_t offset) {
+    if(enabled()) {
+        mRotData.data.memory_id = fd;
+        mRotData.data.offset = offset;
+
+        remap(RotMem::Mem::ROT_NUM_BUFS);
+        OVASSERT(mMem.curr().m.numBufs(), "queueBuffer numbufs is 0");
+
+        mRotData.dst_data.offset =
+                mMem.curr().mRotOffset[mMem.curr().mCurrOffset];
+        mMem.curr().mCurrOffset =
+                (mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs();
+
+        if(!overlay::mdp_wrapper::play(mFd.getFD(), mRotData)) {
+            ALOGE("MdssRot play failed!");
+            dump();
+            return false;
+        }
+
+        // if the prev mem is valid, we need to close
+        if(mMem.prev().valid()) {
+            // FIXME if no wait for vsync the above
+            // play will return immediatly and might cause
+            // tearing when prev.close is called.
+            if(!mMem.prev().close()) {
+                ALOGE("%s error in closing prev rot mem", __FUNCTION__);
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+bool MdssRot::open_i(uint32_t numbufs, uint32_t bufsz)
+{
+    OvMem mem;
+    OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
+
+    if(!mem.open(numbufs, bufsz, false)){ // TODO: secure for badger
+        ALOGE("%s: Failed to open", __func__);
+        mem.close();
+        return false;
+    }
+
+    OVASSERT(MAP_FAILED != mem.addr(), "MAP failed");
+    OVASSERT(mem.getFD() != -1, "getFd is -1");
+
+    mRotData.dst_data.memory_id = mem.getFD();
+    mRotData.dst_data.offset = 0;
+    mMem.curr().m = mem;
+    return true;
+}
+
+bool MdssRot::remap(uint32_t numbufs) {
+    // if current size changed, remap
+    if(mBufSize == mMem.curr().size()) {
+        ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, mBufSize);
+        return true;
+    }
+
+    ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
+    OVASSERT(!mMem.prev().valid(), "Prev should not be valid");
+
+    // ++mMem will make curr to be prev, and prev will be curr
+    ++mMem;
+    if(!open_i(numbufs, mBufSize)) {
+        ALOGE("%s Error could not open", __FUNCTION__);
+        return false;
+    }
+    for (uint32_t i = 0; i < numbufs; ++i) {
+        mMem.curr().mRotOffset[i] = i * mBufSize;
+    }
+    return true;
+}
+
+bool MdssRot::close() {
+    bool success = true;
+    if(mFd.valid() && (getSessId() > 0)) {
+        if(!mdp_wrapper::unsetOverlay(mFd.getFD(), getSessId())) {
+            ALOGE("MdssRot::close unsetOverlay failed, fd=%d sessId=%d",
+                  mFd.getFD(), getSessId());
+		    success = false;
+	}
+    }
+
+    if (!mFd.close()) {
+        ALOGE("Mdss Rot error closing fd");
+        success = false;
+    }
+    if (!mMem.close()) {
+        ALOGE("Mdss Rot error closing mem");
+        success = false;
+    }
+    reset();
+    return success;
+}
+
+void MdssRot::reset() {
+    ovutils::memset0(mRotInfo);
+    ovutils::memset0(mRotData);
+    mRotData.data.memory_id = -1;
+    mRotInfo.id = MSMFB_NEW_REQUEST;
+    ovutils::memset0(mMem.curr().mRotOffset);
+    ovutils::memset0(mMem.prev().mRotOffset);
+    mMem.curr().mCurrOffset = 0;
+    mMem.prev().mCurrOffset = 0;
+    mBufSize = 0;
+    mOrientation = utils::OVERLAY_TRANSFORM_0;
+}
+
+void MdssRot::dump() const {
+    ALOGE("== Dump MdssRot start ==");
+    mFd.dump();
+    mMem.curr().m.dump();
+    mdp_wrapper::dump("mRotInfo", mRotInfo);
+    mdp_wrapper::dump("mRotData", mRotData);
+    ALOGE("== Dump MdssRot end ==");
+}
+
+} // namespace overlay
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
index 695657b..4128068 100644
--- a/liboverlay/overlayMdp.h
+++ b/liboverlay/overlayMdp.h
@@ -233,13 +233,6 @@
 };
 
 //--------------Inlines---------------------------------
-namespace utils {
-inline bool openDev(OvFD& fd, int fbnum,
-        const char* const devpath,
-        int flags) {
-    return overlay::open(fd, fbnum, devpath, flags);
-}
-}
 namespace {
 // just a helper func for common operations x-(y+z)
 int compute(uint32_t x, uint32_t y, uint32_t z) {
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
old mode 100644
new mode 100755
index 5bf7dbc..377265f
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -17,13 +17,16 @@
 
 #include "overlayRotator.h"
 #include "overlayUtils.h"
+#include "mdp_version.h"
 
 namespace ovutils = overlay::utils;
 
 namespace overlay {
 
 int IRotatorHw::getRotatorHwType() {
-    //TODO figure out based on ioctl
+    int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
+    if (mdpVersion == qdutils::MDSS_V5)
+        return TYPE_MDSS;
     return TYPE_MDP;
 }
 
@@ -41,196 +44,4 @@
     return ret;
 }
 
-bool MdpRot::init()
-{
-    if(!mFd.open(Res::rotPath, O_RDWR)){
-        ALOGE("MdpRot failed to init %s", Res::rotPath);
-        return false;
-    }
-    return true;
-}
-
-void MdpRot::setSource(const overlay::utils::Whf& awhf) {
-    utils::Whf whf(awhf);
-
-    mRotImgInfo.src.format = whf.format;
-    if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
-        whf.format == MDP_Y_CBCR_H2V2_TILE) {
-        whf.w =  utils::alignup(awhf.w, 64);
-        whf.h = utils::alignup(awhf.h, 32);
-    }
-
-    mRotImgInfo.src.width = whf.w;
-    mRotImgInfo.src.height = whf.h;
-
-    mRotImgInfo.src_rect.w = whf.w;
-    mRotImgInfo.src_rect.h = whf.h;
-
-    mRotImgInfo.dst.width = whf.w;
-    mRotImgInfo.dst.height = whf.h;
-
-    mBufSize = awhf.size;
-}
-
-void MdpRot::setFlags(const utils::eMdpFlags& flags) {
-    mRotImgInfo.secure = 0;
-    if(flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
-        mRotImgInfo.secure = 1;
-}
-
-void MdpRot::setTransform(const utils::eTransform& rot, const bool& rotUsed)
-{
-    int r = utils::getMdpOrient(rot);
-    setRotations(r);
-    //getMdpOrient will switch the flips if the source is 90 rotated.
-    //Clients in Android dont factor in 90 rotation while deciding the flip.
-    mOrientation = static_cast<utils::eTransform>(r);
-    ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r);
-
-    setDisable();
-    if(rotUsed) {
-        setEnable();
-    }
-}
-
-void MdpRot::doTransform() {
-    switch(mOrientation) {
-        case utils::OVERLAY_TRANSFORM_ROT_90:
-        case utils::OVERLAY_TRANSFORM_ROT_90_FLIP_H:
-        case utils::OVERLAY_TRANSFORM_ROT_90_FLIP_V:
-        case utils::OVERLAY_TRANSFORM_ROT_270:
-            utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height);
-            break;
-        default:
-            break;
-    }
-}
-
-bool MdpRot::commit() {
-    doTransform();
-    if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) {
-        ALOGE("MdpRot commit failed");
-        dump();
-        return false;
-    }
-    mRotDataInfo.session_id = mRotImgInfo.session_id;
-    return true;
-}
-
-bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz)
-{
-    OvMem mem;
-
-    OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
-
-    if(!mem.open(numbufs, bufsz, mRotImgInfo.secure)){
-        ALOGE("%s: Failed to open", __func__);
-        mem.close();
-        return false;
-    }
-
-    OVASSERT(MAP_FAILED != mem.addr(), "MAP failed");
-    OVASSERT(mem.getFD() != -1, "getFd is -1");
-
-    mRotDataInfo.dst.memory_id = mem.getFD();
-    mRotDataInfo.dst.offset = 0;
-    mMem.curr().m = mem;
-    return true;
-}
-
-bool MdpRot::close() {
-    bool success = true;
-    if(mFd.valid() && (getSessId() > 0)) {
-        if(!mdp_wrapper::endRotator(mFd.getFD(), getSessId())) {
-            ALOGE("Mdp Rot error endRotator, fd=%d sessId=%d",
-                    mFd.getFD(), getSessId());
-            success = false;
-        }
-    }
-    if (!mFd.close()) {
-        ALOGE("Mdp Rot error closing fd");
-        success = false;
-    }
-    if (!mMem.close()) {
-        ALOGE("Mdp Rot error closing mem");
-        success = false;
-    }
-    reset();
-    return success;
-}
-
-bool MdpRot::remap(uint32_t numbufs) {
-    // if current size changed, remap
-    if(mBufSize == mMem.curr().size()) {
-        ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, mBufSize);
-        return true;
-    }
-
-    ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
-    OVASSERT(!mMem.prev().valid(), "Prev should not be valid");
-
-    // ++mMem will make curr to be prev, and prev will be curr
-    ++mMem;
-    if(!open_i(numbufs, mBufSize)) {
-        ALOGE("%s Error could not open", __FUNCTION__);
-        return false;
-    }
-    for (uint32_t i = 0; i < numbufs; ++i) {
-        mMem.curr().mRotOffset[i] = i * mBufSize;
-    }
-    return true;
-}
-
-void MdpRot::reset() {
-    ovutils::memset0(mRotImgInfo);
-    ovutils::memset0(mRotDataInfo);
-    ovutils::memset0(mMem.curr().mRotOffset);
-    ovutils::memset0(mMem.prev().mRotOffset);
-    mMem.curr().mCurrOffset = 0;
-    mMem.prev().mCurrOffset = 0;
-    mBufSize = 0;
-    mOrientation = utils::OVERLAY_TRANSFORM_0;
-}
-
-bool MdpRot::queueBuffer(int fd, uint32_t offset) {
-    if(enabled()) {
-        mRotDataInfo.src.memory_id = fd;
-        mRotDataInfo.src.offset = offset;
-
-        remap(RotMem::Mem::ROT_NUM_BUFS);
-        OVASSERT(mMem.curr().m.numBufs(),
-                "queueBuffer numbufs is 0");
-        mRotDataInfo.dst.offset =
-                mMem.curr().mRotOffset[mMem.curr().mCurrOffset];
-        mMem.curr().mCurrOffset =
-                (mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs();
-
-        if(!overlay::mdp_wrapper::rotate(mFd.getFD(), mRotDataInfo)) {
-            ALOGE("MdpRot failed rotate");
-            dump();
-            return false;
-        }
-
-        // if the prev mem is valid, we need to close
-        if(mMem.prev().valid()) {
-            // FIXME if no wait for vsync the above
-            // play will return immediatly and might cause
-            // tearing when prev.close is called.
-            if(!mMem.prev().close()) {
-                ALOGE("%s error in closing prev rot mem", __FUNCTION__);
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-void MdpRot::dump() const {
-    ALOGE("== Dump MdpRot start ==");
-    mFd.dump();
-    mMem.curr().m.dump();
-    mdp_wrapper::dump("mRotImgInfo", mRotImgInfo);
-    mdp_wrapper::dump("mRotDataInfo", mRotDataInfo);
-    ALOGE("== Dump MdpRot end ==");
-}
 }
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 153fb2c..d92bf16 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -254,6 +254,56 @@
     uint32_t mBufSize;
 };
 
+/*
++* MDSS Rot holds MDSS's rotation related structures.
++*
++* */
+class MdssRot : public IRotatorHw {
+public:
+    explicit MdssRot();
+    ~MdssRot();
+    bool init();
+    bool close();
+    void setSource(const utils::Whf& whf);
+    virtual void setFlags(const utils::eMdpFlags& flags);
+    void setTransform(const utils::eTransform& rot,
+            const bool& rotUsed);
+    bool commit();
+    bool queueBuffer(int fd, uint32_t offset);
+    void setEnable();
+    void setDisable();
+    void setRotations(uint32_t r);
+    void setSrcFB();
+    bool enabled() const;
+    int getSessId() const;
+    int getDstMemId() const;
+    uint32_t getDstOffset() const;
+    void dump() const;
+
+private:
+    /* remap rot buffers */
+    bool remap(uint32_t numbufs);
+    bool open_i(uint32_t numbufs, uint32_t bufsz);
+    /* Deferred transform calculations */
+    void doTransform();
+    /* reset underlying data, basically memset 0 */
+    void reset();
+
+    /* MdssRot info structure */
+    mdp_overlay   mRotInfo;
+    /* MdssRot data structure */
+    msmfb_overlay_data mRotData;
+    /* Orientation */
+    utils::eTransform mOrientation;
+    /* rotator fd */
+    OvFD mFd;
+    /* Rotator memory manager */
+    RotMem mMem;
+    /* Single Rotator buffer size */
+    uint32_t mBufSize;
+    /* Enable/Disable Mdss Rot*/
+    bool mEnabled;
+};
 
 //--------------inlines------------------------------------
 
@@ -263,7 +313,7 @@
     if(type == IRotatorHw::TYPE_MDP) {
         mRot = new MdpRot(); //will do reset
     } else if(type == IRotatorHw::TYPE_MDSS) {
-        //TODO create mdss specific rotator
+        mRot = new MdssRot();
     } else {
         ALOGE("%s Unknown h/w type %d", __FUNCTION__, type);
     }
@@ -362,6 +412,25 @@
     mRotDataInfo.src.flags |= MDP_MEMORY_ID_TYPE_FB;
 }
 
+
+//// MdssRot ////
+inline MdssRot::MdssRot() { reset(); }
+inline MdssRot::~MdssRot() { close(); }
+inline void MdssRot::setEnable() { mEnabled = true; }
+inline void MdssRot::setDisable() { mEnabled = false; }
+inline bool MdssRot::enabled() const { return mEnabled; }
+inline void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; }
+inline int MdssRot::getDstMemId() const {
+    return mRotData.dst_data.memory_id;
+}
+inline uint32_t MdssRot::getDstOffset() const {
+    return mRotData.dst_data.offset;
+}
+inline int MdssRot::getSessId() const { return mRotInfo.id; }
+inline void MdssRot::setSrcFB() {
+    mRotData.data.flags |= MDP_MEMORY_ID_TYPE_FB;
+}
+
 } // overlay
 
 #endif // OVERlAY_ROTATOR_H
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index 66c5df7..0648c85 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -66,6 +66,11 @@
 
 // fwd
 class Overlay;
+class OvFD;
+
+/* helper function to open by using fbnum */
+bool open(OvFD& fd, uint32_t fbnum, const char* const dev,
+    int flags = O_RDWR);
 
 namespace utils {
 struct Whf;
@@ -790,6 +795,11 @@
             s, mFBWidth, mFBHeight, mFBbpp, mFBystride);
 }
 
+inline bool openDev(OvFD& fd, int fbnum,
+    const char* const devpath, int flags) {
+    return overlay::open(fd, fbnum, devpath, flags);
+}
+
 } // namespace utils ends
 
 //--------------------Class Res stuff (namespace overlay only) -----------
@@ -811,12 +821,6 @@
 
 //--------------------Class OvFD stuff (namespace overlay only) -----------
 
-class OvFD;
-
-/* helper function to open by using fbnum */
-bool open(OvFD& fd, uint32_t fbnum, const char* const dev,
-    int flags = O_RDWR);
-
 /*
 * Holds one FD
 * Dtor will NOT close the underlying FD.