Reconcile with jb-mr1-factory-release jb-mr1-release - do not merge

Change-Id: I088f7356b684381f971b7e9f6773ba24f7f9b62a
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 0000000..461cf26
--- /dev/null
+++ b/CleanSpec.mk
@@ -0,0 +1,50 @@
+# Copyright (C) 2007 The Android Open Source Project
+#
+# 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libMcClient_intermediates)
diff --git a/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Basecomponent.c b/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Basecomponent.c
index e5694a4..f9769ef 100644
--- a/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Basecomponent.c
+++ b/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Basecomponent.c
@@ -343,6 +343,11 @@
                 } else {
                     if (CHECK_PORT_ENABLED(pExynosPort)) {
                         Exynos_OSAL_SemaphoreWait(pExynosComponent->pExynosPort[i].loadedResource);
+                        if (pExynosComponent->abendState == OMX_TRUE) {
+                            Exynos_OSAL_SignalSet(pExynosComponent->abendStateEvent);
+                            ret = Exynos_OMX_Release_Resource(pOMXComponent);
+                            goto EXIT;
+                        }
                         pExynosPort->portDefinition.bPopulated = OMX_TRUE;
                     }
                 }
@@ -1495,6 +1500,12 @@
         Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__);
         goto EXIT;
     }
+    ret = Exynos_OSAL_SignalCreate(&pExynosComponent->abendStateEvent);
+    if (ret != OMX_ErrorNone) {
+        ret = OMX_ErrorInsufficientResources;
+        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__);
+        goto EXIT;
+    }
 
     pExynosComponent->bExitMessageHandlerThread = OMX_FALSE;
     Exynos_OSAL_QueueCreate(&pExynosComponent->messageQ, MAX_QUEUE_ELEMENTS);
@@ -1555,6 +1566,8 @@
     Exynos_OSAL_ThreadTerminate(pExynosComponent->hMessageHandler);
     pExynosComponent->hMessageHandler = NULL;
 
+    Exynos_OSAL_SignalTerminate(pExynosComponent->abendStateEvent);
+    pExynosComponent->abendStateEvent = NULL;
     Exynos_OSAL_MutexTerminate(pExynosComponent->compMutex);
     pExynosComponent->compMutex = NULL;
     Exynos_OSAL_SemaphoreTerminate(pExynosComponent->msgSemaphoreHandle);
diff --git a/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Basecomponent.h b/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Basecomponent.h
index 1b2abde..9f9ed3d 100644
--- a/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Basecomponent.h
+++ b/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Basecomponent.h
@@ -58,6 +58,8 @@
 
     OMX_STATETYPE               currentState;
     EXYNOS_OMX_TRANS_STATETYPE  transientState;
+    OMX_BOOL                    abendState;
+    OMX_HANDLETYPE              abendStateEvent;
 
     EXYNOS_CODEC_TYPE           codecType;
     EXYNOS_OMX_PRIORITYMGMTTYPE compPriority;
diff --git a/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Baseport.c b/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Baseport.c
index f4f0066..9c0c42d 100644
--- a/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Baseport.c
+++ b/exynos_omx/openmax/exynos_omx/component/common/Exynos_OMX_Baseport.c
@@ -774,15 +774,16 @@
 
 OMX_ERRORTYPE Exynos_OMX_Port_Destructor(OMX_HANDLETYPE hComponent)
 {
-    OMX_ERRORTYPE          ret = OMX_ErrorNone;
-    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
+    OMX_ERRORTYPE             ret = OMX_ErrorNone;
+    OMX_COMPONENTTYPE        *pOMXComponent = NULL;
     EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
     EXYNOS_OMX_BASEPORT      *pExynosPort = NULL;
 
-    FunctionIn();
-
+    OMX_S32 countValue = 0;
     int i = 0;
 
+    FunctionIn();
+
     if (hComponent == NULL) {
         ret = OMX_ErrorBadParameter;
         goto EXIT;
@@ -797,6 +798,17 @@
         goto EXIT;
     }
     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
+
+    if (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle) {
+        pExynosComponent->abendState = OMX_TRUE;
+        for (i = 0; i < ALL_PORT_NUM; i++) {
+            pExynosPort = &pExynosComponent->pExynosPort[i];
+            Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource);
+        }
+        Exynos_OSAL_SignalWait(pExynosComponent->abendStateEvent, DEF_MAX_WAIT_TIME);
+        Exynos_OSAL_SignalReset(pExynosComponent->abendStateEvent);
+    }
+
     for (i = 0; i < ALL_PORT_NUM; i++) {
         pExynosPort = &pExynosComponent->pExynosPort[i];
 
diff --git a/exynos_omx/openmax/exynos_omx/component/video/enc/Exynos_OMX_Venc.c b/exynos_omx/openmax/exynos_omx/component/video/enc/Exynos_OMX_Venc.c
index 8f2e926..b3b2eb9 100644
--- a/exynos_omx/openmax/exynos_omx/component/video/enc/Exynos_OMX_Venc.c
+++ b/exynos_omx/openmax/exynos_omx/component/video/enc/Exynos_OMX_Venc.c
@@ -662,7 +662,8 @@
                 (!CHECK_PORT_BEING_FLUSHED(exynosInputPort))) {
                 ret = Exynos_InputBufferGetQueue(pExynosComponent);
 #ifdef USE_METADATABUFFERTYPE
-                if (pVideoEnc->bFirstInput == OMX_TRUE) {
+                if ((pVideoEnc->bFirstInput == OMX_TRUE) &&
+                    (!CHECK_PORT_BEING_FLUSHED(exynosInputPort))) {
                     Exynos_OMX_ExtensionSetup(hComponent);
                     pVideoEnc->bFirstInput = OMX_FALSE;
                 }
diff --git a/gralloc/gralloc.cpp b/gralloc/gralloc.cpp
index d10dc27..f3610f3 100644
--- a/gralloc/gralloc.cpp
+++ b/gralloc/gralloc.cpp
@@ -193,16 +193,17 @@
     switch (format) {
         case HAL_PIXEL_FORMAT_YV12:
             *stride = ALIGN(w, 16);
+            size = (*stride * h) + (ALIGN(*stride / 2, 16) * h);
             break;
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
             *stride = w;
+            size = *stride * h * 3 / 2;
             break;
         default:
             ALOGE("invalid yuv format %d\n", format);
             return -EINVAL;
     }
 
-    size = *stride * h * 3 / 2;
     err = ion_alloc_fd(ionfd, size, 0, 1 << ION_HEAP_TYPE_SYSTEM,
                        ion_flags, &fd);
     if (err)
diff --git a/include/exynos_gscaler.h b/include/exynos_gscaler.h
index dfaf61e..401bc3f 100644
--- a/include/exynos_gscaler.h
+++ b/include/exynos_gscaler.h
@@ -77,6 +77,7 @@
     uint32_t rot;
     uint32_t cacheable;
     uint32_t drmMode;
+    uint32_t narrowRgb;
     int      acquireFenceFd;
     int      releaseFenceFd;
 } exynos_gsc_img;
@@ -212,6 +213,9 @@
  * \param mode_drm
  *   mode_drm[in]
  *
+ * \param narrowRgb
+ *   narrow RGB range[in]
+ *
  * \return
  *   error code
  */
@@ -225,7 +229,8 @@
     unsigned int crop_height,
     unsigned int v4l2_colorformat,
     unsigned int cacheable,
-    unsigned int mode_drm);
+    unsigned int mode_drm,
+    unsigned int narrowRgb);
 
 /*!
  * Set rotation.
diff --git a/include/videodev2_exynos_media.h b/include/videodev2_exynos_media.h
index 0cb5876..31dbb3c 100644
--- a/include/videodev2_exynos_media.h
+++ b/include/videodev2_exynos_media.h
@@ -64,6 +64,8 @@
 #define V4L2_CID_TV_ENABLE_HDMI_AUDIO (V4L2_CID_EXYNOS_BASE + 61)
 #define V4L2_CID_TV_SET_NUM_CHANNELS (V4L2_CID_EXYNOS_BASE + 62)
 #define V4L2_CID_TV_UPDATE (V4L2_CID_EXYNOS_BASE + 63)
+#define V4L2_CID_TV_SET_COLOR_RANGE (V4L2_CID_EXYNOS_BASE + 64)
+#define V4L2_CID_TV_HDCP_ENABLE (V4L2_CID_EXYNOS_BASE + 65)
 #define V4L2_CID_CSC_EQ_MODE (V4L2_CID_EXYNOS_BASE + 100)
 #define V4L2_CID_CSC_EQ (V4L2_CID_EXYNOS_BASE + 101)
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libcamera2/ExynosCamera2.cpp b/libcamera2/ExynosCamera2.cpp
index d7ecb60..100f0a8 100644
--- a/libcamera2/ExynosCamera2.cpp
+++ b/libcamera2/ExynosCamera2.cpp
@@ -595,7 +595,7 @@
             sizeof(exposureCompensationRange)/sizeof(int32_t));
 
     static const int32_t availableTargetFpsRanges[] = {
-            15, 30, 30, 30
+            15, 15, 24, 24, 25, 25, 15, 30, 30, 30
     };
     ADD_OR_SIZE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
             availableTargetFpsRanges,
diff --git a/libcamera2/ExynosCameraHWInterface2.cpp b/libcamera2/ExynosCameraHWInterface2.cpp
index da4bf27..ea90d05 100644
--- a/libcamera2/ExynosCameraHWInterface2.cpp
+++ b/libcamera2/ExynosCameraHWInterface2.cpp
@@ -338,7 +338,7 @@
         return false;
 }
 
-void RequestManager::RegisterRequest(camera_metadata_t * new_request)
+void RequestManager::RegisterRequest(camera_metadata_t * new_request, int * afMode, uint32_t * afRegion)
 {
     ALOGV("DEBUG(%s):", __FUNCTION__);
 
@@ -346,7 +346,7 @@
 
     request_manager_entry * newEntry = NULL;
     int newInsertionIndex = GetNextIndex(m_entryInsertionIndex);
-    ALOGV("DEBUG(%s): got lock, new insertIndex(%d), cnt before reg(%d)", __FUNCTION__,newInsertionIndex,m_numOfEntries );
+    ALOGV("DEBUG(%s): got lock, new insertIndex(%d), cnt before reg(%d)", __FUNCTION__,newInsertionIndex, m_numOfEntries );
 
 
     newEntry = &(entries[newInsertionIndex]);
@@ -370,6 +370,11 @@
     m_entryInsertionIndex = newInsertionIndex;
 
 
+    *afMode = (int)(newEntry->internal_shot.shot.ctl.aa.afMode);
+    afRegion[0] = newEntry->internal_shot.shot.ctl.aa.afRegions[0];
+    afRegion[1] = newEntry->internal_shot.shot.ctl.aa.afRegions[1];
+    afRegion[2] = newEntry->internal_shot.shot.ctl.aa.afRegions[2];
+    afRegion[3] = newEntry->internal_shot.shot.ctl.aa.afRegions[3];
     ALOGV("## RegisterReq DONE num(%d), insert(%d), processing(%d), frame(%d), (frameCnt(%d))",
     m_numOfEntries,m_entryInsertionIndex,m_entryProcessingIndex, m_entryFrameOutputIndex, newEntry->internal_shot.shot.ctl.request.frameCount);
 }
@@ -440,7 +445,7 @@
     return true;
 }
 
-int RequestManager::MarkProcessingRequest(ExynosBuffer* buf, int *afMode)
+int RequestManager::MarkProcessingRequest(ExynosBuffer* buf)
 {
     struct camera2_shot_ext * shot_ext;
     struct camera2_shot_ext * request_shot;
@@ -466,7 +471,6 @@
 
     newEntry = &(entries[newProcessingIndex]);
     request_shot = &(newEntry->internal_shot);
-    *afMode = (int)(newEntry->internal_shot.shot.ctl.aa.afMode);
     if (newEntry->status != REGISTERED) {
         CAM_LOGD("DEBUG(%s)(%d): Circular buffer abnormal, numOfEntries(%d), status(%d)", __FUNCTION__, newProcessingIndex, m_numOfEntries, newEntry->status);
         for (int i = 0; i < NUM_MAX_REQUEST_MGR_ENTRY; i++) {
@@ -668,6 +672,8 @@
     if (request_shot->shot.ctl.aa.aeMode >= AA_AEMODE_ON) {
         if (request_shot->shot.ctl.aa.captureIntent == AA_CAPTURE_INTENT_PREVIEW)
             ctl_info->flash.i_flashMode = request_shot->shot.ctl.aa.aeMode;
+        else if (request_shot->shot.ctl.aa.captureIntent == AA_CAPTURE_INTENT_VIDEO_RECORD)
+            ctl_info->flash.i_flashMode = request_shot->shot.ctl.aa.aeMode;
         request_shot->shot.ctl.aa.aeMode = AA_AEMODE_ON;
     }
 
@@ -729,13 +735,8 @@
     if (shot_ext->shot.ctl.stats.faceDetectMode != FACEDETECT_MODE_OFF)
         shot_ext->fd_bypass = 0;
 
-    if (targetStreamIndex & STREAM_MASK_RECORD) {
-        shot_ext->shot.ctl.aa.aeTargetFpsRange[0] = 30;
-        shot_ext->shot.ctl.aa.aeTargetFpsRange[1] = 30;
-    } else {
-        shot_ext->shot.ctl.aa.aeTargetFpsRange[0] = request_shot->shot.ctl.aa.aeTargetFpsRange[0];
-        shot_ext->shot.ctl.aa.aeTargetFpsRange[1] = request_shot->shot.ctl.aa.aeTargetFpsRange[1];
-    }
+    shot_ext->shot.ctl.aa.aeTargetFpsRange[0] = request_shot->shot.ctl.aa.aeTargetFpsRange[0];
+    shot_ext->shot.ctl.aa.aeTargetFpsRange[1] = request_shot->shot.ctl.aa.aeTargetFpsRange[1];
 
     ALOGV("(%s): applied aa(%d) aemode(%d) expComp(%d), awb(%d) afmode(%d), ", __FUNCTION__,
     (int)(shot_ext->shot.ctl.aa.mode), (int)(shot_ext->shot.ctl.aa.aeMode),
@@ -2176,7 +2177,7 @@
                     ion_unmap(targetStream->m_parameters.svcBuffers[i].virt.extP[j],
                                     targetStream->m_parameters.svcBuffers[i].size.extS[j]);
                     ALOGV("(%s) ummap stream buffer[%d], plane(%d), fd %d vaddr %x", __FUNCTION__, i, j,
-                                  targetStream->m_parameters.svcBuffers[i].fd.extFd[j], targetStream->m_parameters.svcBuffers[i].virt.extP[j]);
+                                  targetStream->m_parameters.svcBuffers[i].fd.extFd[j], (unsigned int)(targetStream->m_parameters.svcBuffers[i].virt.extP[j]));
                 }
             }
         }
@@ -2248,7 +2249,7 @@
                     ion_unmap(targetStream->m_parameters.svcBuffers[i].virt.extP[j],
                                     targetStream->m_parameters.svcBuffers[i].size.extS[j]);
                     ALOGV("(%s) ummap stream buffer[%d], plane(%d), fd %d vaddr %x", __FUNCTION__, i, j,
-                                  targetStream->m_parameters.svcBuffers[i].fd.extFd[j], targetStream->m_parameters.svcBuffers[i].virt.extP[j]);
+                                  targetStream->m_parameters.svcBuffers[i].fd.extFd[j], (unsigned int)(targetStream->m_parameters.svcBuffers[i].virt.extP[j]));
                 }
             }
         }
@@ -2344,12 +2345,13 @@
 
 int ExynosCameraHWInterface2::triggerAction(uint32_t trigger_id, int ext1, int ext2)
 {
+    Mutex::Autolock lock(m_afModeTriggerLock);
     ALOGV("DEBUG(%s): id(%x), %d, %d", __FUNCTION__, trigger_id, ext1, ext2);
 
     switch (trigger_id) {
     case CAMERA2_TRIGGER_AUTOFOCUS:
         ALOGV("DEBUG(%s):TRIGGER_AUTOFOCUS id(%d)", __FUNCTION__, ext1);
-        OnAfTriggerStart(ext1);
+        OnAfTrigger(ext1);
         break;
 
     case CAMERA2_TRIGGER_CANCEL_AUTOFOCUS:
@@ -2715,6 +2717,8 @@
     int res = 0;
 
     int ret;
+    int afMode;
+    uint32_t afRegion[4];
 
     ALOGV("DEBUG(%s): m_mainThreadFunc (%x)", __FUNCTION__, currentSignal);
 
@@ -2729,6 +2733,7 @@
     if (currentSignal & SIGNAL_MAIN_REQ_Q_NOT_EMPTY) {
         ALOGV("DEBUG(%s): MainThread processing SIGNAL_MAIN_REQ_Q_NOT_EMPTY", __FUNCTION__);
         if (m_requestManager->IsRequestQueueFull()==false) {
+            Mutex::Autolock lock(m_afModeTriggerLock);
             m_requestQueueOps->dequeue_request(m_requestQueueOps, &currentRequest);
             if (NULL == currentRequest) {
                 ALOGD("DEBUG(%s)(0x%x): No more service requests left in the queue ", __FUNCTION__, currentSignal);
@@ -2737,7 +2742,10 @@
                     m_vdisBubbleCnt = 1;
             }
             else {
-                m_requestManager->RegisterRequest(currentRequest);
+                m_requestManager->RegisterRequest(currentRequest, &afMode, afRegion);
+
+                SetAfMode((enum aa_afmode)afMode);
+                SetAfRegion(afRegion);
 
                 m_numOfRemainingReqInSvc = m_requestQueueOps->request_count(m_requestQueueOps);
                 ALOGV("DEBUG(%s): remaining req cnt (%d)", __FUNCTION__, m_numOfRemainingReqInSvc);
@@ -3005,33 +3013,18 @@
 
 void ExynosCameraHWInterface2::m_updateAfRegion(struct camera2_shot_ext * shot_ext)
 {
-    if (0 == shot_ext->shot.ctl.aa.afRegions[0] && 0 == shot_ext->shot.ctl.aa.afRegions[1]
-            && 0 == shot_ext->shot.ctl.aa.afRegions[2] && 0 == shot_ext->shot.ctl.aa.afRegions[3]) {
-        ALOGV("(%s): AF region resetting", __FUNCTION__);
-        lastAfRegion[0] = 0;
-        lastAfRegion[1] = 0;
-        lastAfRegion[2] = 0;
-        lastAfRegion[3] = 0;
-    } else {
-        // clear region infos in case of CAF mode
-        if (m_afMode == AA_AFMODE_CONTINUOUS_VIDEO || m_afMode == AA_AFMODE_CONTINUOUS_PICTURE) {
-            shot_ext->shot.ctl.aa.afRegions[0] = shot_ext->shot.ctl.aa.aeRegions[0] = lastAfRegion[0] = 0;
-            shot_ext->shot.ctl.aa.afRegions[1] = shot_ext->shot.ctl.aa.aeRegions[1] = lastAfRegion[1] = 0;
-            shot_ext->shot.ctl.aa.afRegions[2] = shot_ext->shot.ctl.aa.aeRegions[2] = lastAfRegion[2] = 0;
-            shot_ext->shot.ctl.aa.afRegions[3] = shot_ext->shot.ctl.aa.aeRegions[3] = lastAfRegion[3] = 0;
-        } else if (!(lastAfRegion[0] == shot_ext->shot.ctl.aa.afRegions[0] && lastAfRegion[1] == shot_ext->shot.ctl.aa.afRegions[1]
-                && lastAfRegion[2] == shot_ext->shot.ctl.aa.afRegions[2] && lastAfRegion[3] == shot_ext->shot.ctl.aa.afRegions[3])) {
-            ALOGD("(%s): AF region changed : triggering (%d)", __FUNCTION__, m_afMode);
-            shot_ext->shot.ctl.aa.afTrigger = 1;
-            shot_ext->shot.ctl.aa.afMode = m_afMode;
-            m_afState = HAL_AFSTATE_STARTED;
-            lastAfRegion[0] = shot_ext->shot.ctl.aa.afRegions[0];
-            lastAfRegion[1] = shot_ext->shot.ctl.aa.afRegions[1];
-            lastAfRegion[2] = shot_ext->shot.ctl.aa.afRegions[2];
-            lastAfRegion[3] = shot_ext->shot.ctl.aa.afRegions[3];
-            m_IsAfTriggerRequired = false;
-        }
-    }
+    shot_ext->shot.ctl.aa.afRegions[0] = currentAfRegion[0];
+    shot_ext->shot.ctl.aa.afRegions[1] = currentAfRegion[1];
+    shot_ext->shot.ctl.aa.afRegions[2] = currentAfRegion[2];
+    shot_ext->shot.ctl.aa.afRegions[3] = currentAfRegion[3];
+}
+
+void ExynosCameraHWInterface2::SetAfRegion(uint32_t * afRegion)
+{
+    currentAfRegion[0] = afRegion[0];
+    currentAfRegion[1] = afRegion[1];
+    currentAfRegion[2] = afRegion[2];
+    currentAfRegion[3] = afRegion[3];
 }
 
 void ExynosCameraHWInterface2::m_afTrigger(struct camera2_shot_ext * shot_ext, int mode)
@@ -3102,7 +3095,6 @@
         struct camera2_shot_ext *shot_ext;
         struct camera2_shot_ext *shot_ext_capture;
         bool triggered = false;
-        int afMode;
 
         /* dqbuf from sensor */
         ALOGV("Sensor DQbuf start");
@@ -3139,14 +3131,6 @@
                 m_ctlInfo.scene.prevSceneMode = shot_ext->shot.ctl.aa.sceneMode;
             }
 
-            if (m_afModeWaitingCnt != 0) {
-                ALOGV("### Af Trigger pulled, waiting for mode change cnt(%d) ", m_afModeWaitingCnt);
-                m_afModeWaitingCnt --;
-                if (m_afModeWaitingCnt == 1) {
-                    m_afModeWaitingCnt = 0;
-                    OnAfTrigger(m_afPendingTriggerId);
-                }
-            }
             m_zoomRatio = (float)m_camera2->getSensorW() / (float)shot_ext->shot.ctl.scaler.cropRegion[2];
             float zoomLeft, zoomTop, zoomWidth, zoomHeight;
             int crop_x = 0, crop_y = 0, crop_w = 0, crop_h = 0;
@@ -3179,7 +3163,7 @@
             shot_ext->shot.ctl.scaler.cropRegion[1] = new_cropRegion[1];
             shot_ext->shot.ctl.scaler.cropRegion[2] = new_cropRegion[2];
             if (m_IsAfModeUpdateRequired && (m_ctlInfo.flash.m_precaptureTriggerId == 0)) {
-                ALOGD("### AF Mode change(Mode %d) ", m_afMode);
+                ALOGD("### Applying AF Mode change(Mode %d) ", m_afMode);
                 shot_ext->shot.ctl.aa.afMode = m_afMode;
                 if (m_afMode == AA_AFMODE_CONTINUOUS_VIDEO || m_afMode == AA_AFMODE_CONTINUOUS_PICTURE) {
                     ALOGD("### With Automatic triger for continuous modes");
@@ -3229,22 +3213,12 @@
                             // Flash is enabled and start AF
                             m_afTrigger(shot_ext, 1);
                         } else {
-                            if (m_ctlInfo.af.m_afTriggerTimeOut == 0)
-                                m_afTrigger(shot_ext, 0);
-                            else
-                                m_ctlInfo.af.m_afTriggerTimeOut--;
+                            m_afTrigger(shot_ext, 0);
                         }
                     }
                 } else {
                     // non-flash case
-                    if ((m_afMode != AA_AFMODE_AUTO) && (m_afMode != AA_AFMODE_MACRO)) {
-                        m_afTrigger(shot_ext, 0);
-                    } else {
-                        if (m_ctlInfo.af.m_afTriggerTimeOut == 0)
-                            m_afTrigger(shot_ext, 0);
-                        else
-                            m_ctlInfo.af.m_afTriggerTimeOut--;
-                    }
+                    m_afTrigger(shot_ext, 0);
                 }
             } else {
                 shot_ext->shot.ctl.aa.afTrigger = 0;
@@ -3252,8 +3226,6 @@
 
             if (m_wideAspect) {
                 shot_ext->setfile = ISS_SUB_SCENARIO_VIDEO;
-                shot_ext->shot.ctl.aa.aeTargetFpsRange[0] = 30;
-                shot_ext->shot.ctl.aa.aeTargetFpsRange[1] = 30;
             } else {
                 shot_ext->setfile = ISS_SUB_SCENARIO_STILL;
             }
@@ -3320,6 +3292,26 @@
                 shot_ext->request_scc = 0;
             }
 
+            switch (shot_ext->shot.ctl.aa.aeTargetFpsRange[1]) {
+            case 15:
+                shot_ext->shot.ctl.sensor.frameDuration = (66666 * 1000);
+                break;
+
+            case 24:
+                shot_ext->shot.ctl.sensor.frameDuration = (41666 * 1000);
+                break;
+
+            case 25:
+                shot_ext->shot.ctl.sensor.frameDuration = (40000 * 1000);
+                break;
+
+            case 30:
+            default:
+                shot_ext->shot.ctl.sensor.frameDuration = (33333 * 1000);
+                break;
+            }
+            shot_ext->shot.ctl.aa.aeTargetFpsRange[1] = 30;
+
             // Flash mode
             // Keep and Skip request_scc = 1 at flash enable mode to operate flash sequence
             if ((m_ctlInfo.flash.i_flashMode >= AA_AEMODE_ON_AUTO_FLASH)
@@ -3348,18 +3340,12 @@
                 m_ctlInfo.flash.m_flashDecisionResult = false;
             }
 
-            // TODO : set torch mode for video recording. need to find proper position.
-            // m_wideAspect is will be changed to recording hint
-            if ((shot_ext->shot.ctl.flash.flashMode == CAM2_FLASH_MODE_SINGLE) && m_wideAspect) {
-                shot_ext->shot.ctl.flash.flashMode = CAM2_FLASH_MODE_TORCH;
-                shot_ext->shot.ctl.flash.firingPower = 10;
-                m_ctlInfo.flash.m_flashTorchMode = true;
-            } else if (m_wideAspect){
-                shot_ext->shot.ctl.flash.flashMode = CAM2_FLASH_MODE_OFF;
-                shot_ext->shot.ctl.flash.firingPower = 0;
-                m_ctlInfo.flash.m_flashTorchMode = false;
+            if (shot_ext->shot.ctl.flash.flashMode == CAM2_FLASH_MODE_TORCH) {
+                if (m_ctlInfo.flash.m_flashTorchMode == false) {
+                    m_ctlInfo.flash.m_flashTorchMode = true;
+                }
             } else {
-                if (m_ctlInfo.flash.m_flashTorchMode) {
+                if (m_ctlInfo.flash.m_flashTorchMode == true) {
                     shot_ext->shot.ctl.flash.flashMode = CAM2_FLASH_MODE_OFF;
                     shot_ext->shot.ctl.flash.firingPower = 0;
                     m_ctlInfo.flash.m_flashTorchMode = false;
@@ -3520,8 +3506,6 @@
             shot_ext->request_scp = 0;
             if (m_wideAspect) {
                 shot_ext->setfile = ISS_SUB_SCENARIO_VIDEO;
-                shot_ext->shot.ctl.aa.aeTargetFpsRange[0] = 30;
-                shot_ext->shot.ctl.aa.aeTargetFpsRange[1] = 30;
             } else {
                 shot_ext->setfile = ISS_SUB_SCENARIO_STILL;
             }
@@ -3556,11 +3540,7 @@
             return;
         }
 
-        processingReqIndex = m_requestManager->MarkProcessingRequest(&(m_camera_info.sensor.buffer[index]), &afMode);
-        if (processingReqIndex != -1)
-            SetAfMode((enum aa_afmode)afMode);
-
-
+        processingReqIndex = m_requestManager->MarkProcessingRequest(&(m_camera_info.sensor.buffer[index]));
         shot_ext = (struct camera2_shot_ext *)(m_camera_info.sensor.buffer[index].virt.extP[1]);
         if (m_scp_closing || m_scp_closed) {
             ALOGD("(%s): SCP_CLOSING(%d) SCP_CLOSED(%d)", __FUNCTION__, m_scp_closing, m_scp_closed);
@@ -3905,7 +3885,7 @@
                             &(selfStreamParms->svcBufHandle[selfStreamParms->bufIndex]));
                 }
                 else if ((currentOutputStreams & STREAM_MASK_ZSL) && selfThread->m_index == 1) {
-                    ALOGV("** SCC output (frameCnt:%d), last(%d)", frame->rcount);
+                    ALOGV("** SCC output (frameCnt:%d)", frame->rcount);
                     res = selfStreamParms->streamOps->enqueue_buffer(selfStreamParms->streamOps,
                                 frameTimeStamp,
                                 &(selfStreamParms->svcBufHandle[selfStreamParms->bufIndex]));
@@ -4771,11 +4751,6 @@
     ALOGV("[PreCap] OnPrecaptureMeteringTriggerStart (ID %d) (flag : %d) (cnt : %d)", id, m_ctlInfo.flash.m_flashEnableFlg, m_ctlInfo.flash.m_flashCnt);
     OnPrecaptureMeteringNotificationSensor();
 }
-void ExynosCameraHWInterface2::OnAfTriggerStart(int id)
-{
-    m_afPendingTriggerId = id;
-    m_afModeWaitingCnt = 6;
-}
 
 void ExynosCameraHWInterface2::OnAfTrigger(int id)
 {
@@ -4784,7 +4759,7 @@
     switch (m_afMode) {
     case AA_AFMODE_AUTO:
     case AA_AFMODE_MACRO:
-    case AA_AFMODE_OFF:
+    case AA_AFMODE_MANUAL:
         ALOGV("[AF] OnAfTrigger - AUTO,MACRO,OFF (Mode %d) ", m_afMode);
         // If flash is enable, Flash operation is executed before triggering AF
         if ((m_ctlInfo.flash.i_flashMode >= AA_AEMODE_ON_AUTO_FLASH)
@@ -4807,6 +4782,7 @@
         OnAfTriggerCAFPicture(id);
         break;
 
+    case AA_AFMODE_OFF:
     default:
         break;
     }
@@ -4822,7 +4798,6 @@
     case HAL_AFSTATE_SCANNING:
         nextState = HAL_AFSTATE_NEEDS_COMMAND;
         m_IsAfTriggerRequired = true;
-        m_ctlInfo.af.m_afTriggerTimeOut = 4;
         break;
     case HAL_AFSTATE_NEEDS_COMMAND:
         nextState = NO_TRANSITION;
@@ -4837,7 +4812,6 @@
     case HAL_AFSTATE_FAILED:
         nextState = HAL_AFSTATE_NEEDS_COMMAND;
         m_IsAfTriggerRequired = true;
-        m_ctlInfo.af.m_afTriggerTimeOut = 4;
         break;
     default:
         break;
@@ -5542,6 +5516,7 @@
     case AA_AFMODE_AUTO:
     case AA_AFMODE_MACRO:
     case AA_AFMODE_OFF:
+    case AA_AFMODE_MANUAL:
         OnAfCancelAutoMacro(id);
         break;
     case AA_AFMODE_CONTINUOUS_VIDEO:
@@ -5558,7 +5533,6 @@
 void ExynosCameraHWInterface2::OnAfCancelAutoMacro(int id)
 {
     int nextState = NO_TRANSITION;
-    m_afTriggerId = id;
 
     if (m_ctlInfo.flash.m_flashEnableFlg  && m_ctlInfo.flash.m_afFlashDoneFlg) {
         m_ctlInfo.flash.m_flashCnt = IS_FLASH_STATE_AUTO_OFF;
@@ -5588,7 +5562,6 @@
 void ExynosCameraHWInterface2::OnAfCancelCAFPicture(int id)
 {
     int nextState = NO_TRANSITION;
-    m_afTriggerId = id;
 
     switch (m_afState) {
     case HAL_AFSTATE_INACTIVE:
@@ -5617,7 +5590,6 @@
 void ExynosCameraHWInterface2::OnAfCancelCAFVideo(int id)
 {
     int nextState = NO_TRANSITION;
-    m_afTriggerId = id;
 
     switch (m_afState) {
     case HAL_AFSTATE_INACTIVE:
@@ -5658,7 +5630,7 @@
 void ExynosCameraHWInterface2::SetAfMode(enum aa_afmode afMode)
 {
     if (m_afMode != afMode) {
-        if (m_IsAfModeUpdateRequired) {
+        if (m_IsAfModeUpdateRequired && m_afMode != AA_AFMODE_OFF) {
             m_afMode2 = afMode;
             ALOGV("(%s): pending(%d) and new(%d)", __FUNCTION__, m_afMode, afMode);
         }
@@ -5666,11 +5638,8 @@
             ALOGV("(%s): current(%d) new(%d)", __FUNCTION__, m_afMode, afMode);
             m_IsAfModeUpdateRequired = true;
             m_afMode = afMode;
-            if (m_afModeWaitingCnt != 0) {
-                m_afModeWaitingCnt = 0;
-                m_afState = HAL_AFSTATE_INACTIVE;
-                OnAfTrigger(m_afPendingTriggerId);
-            }
+            SetAfStateForService(ANDROID_CONTROL_AF_STATE_INACTIVE);
+            m_afState = HAL_AFSTATE_INACTIVE;
         }
     }
 }
diff --git a/libcamera2/ExynosCameraHWInterface2.h b/libcamera2/ExynosCameraHWInterface2.h
index 59a808c..027322f 100644
--- a/libcamera2/ExynosCameraHWInterface2.h
+++ b/libcamera2/ExynosCameraHWInterface2.h
@@ -282,11 +282,11 @@
     int     GetNumEntries();
     bool    IsRequestQueueFull();
 
-    void    RegisterRequest(camera_metadata_t *new_request);
+    void    RegisterRequest(camera_metadata_t *new_request, int * afMode, uint32_t * afRegion);
     void    DeregisterRequest(camera_metadata_t **deregistered_request);
     bool    PrepareFrame(size_t *num_entries, size_t *frame_size,
                 camera_metadata_t **prepared_frame, int afState);
-    int     MarkProcessingRequest(ExynosBuffer * buf, int *afMode);
+    int     MarkProcessingRequest(ExynosBuffer * buf);
     void    NotifyStreamOutput(int frameCnt);
     void    ApplyDynamicMetadata(struct camera2_shot_ext *shot_ext);
     void    CheckCompleted(int index);
@@ -585,7 +585,7 @@
     void            StartSCCThread(bool threadExists);
     int             GetAfState();
     void            SetAfMode(enum aa_afmode afMode);
-    void            OnAfTriggerStart(int id);
+    void            SetAfRegion(uint32_t * afRegion);
     void            OnAfTrigger(int id);
     void            OnAfTriggerAutoMacro(int id);
     void            OnAfTriggerCAFPicture(int id);
@@ -653,7 +653,7 @@
     bool                                m_scp_closing;
     bool                                m_scp_closed;
     bool                                m_wideAspect;
-    uint32_t                            lastAfRegion[4];
+    uint32_t                            currentAfRegion[4];
     float                               m_zoomRatio;
 
     int                                 m_vdisBubbleCnt;
@@ -662,6 +662,7 @@
     mutable Mutex                       m_qbufLock;
     mutable Mutex                       m_jpegEncoderLock;
     int                                 m_jpegEncodingCount;
+    mutable Mutex                       m_afModeTriggerLock;
 
     bool                                m_scpForceSuspended;
     int                                 m_afState;
diff --git a/libcamera2/MetadataConverter.cpp b/libcamera2/MetadataConverter.cpp
index 11d1b3a..d3dd2b3 100644
--- a/libcamera2/MetadataConverter.cpp
+++ b/libcamera2/MetadataConverter.cpp
@@ -154,7 +154,7 @@
             case ANDROID_FLASH_MODE:
                 if (NO_ERROR != CheckEntryTypeMismatch(&curr_entry, TYPE_BYTE, 1))
                     break;
-                dst->ctl.flash.flashMode = (enum flash_mode)curr_entry.data.u8[0];
+                dst->ctl.flash.flashMode = (enum flash_mode)(curr_entry.data.u8[0] + 1);
                 break;
 
             case ANDROID_FLASH_FIRING_POWER:
@@ -588,7 +588,11 @@
     for (int i = 0; i < CAMERA2_MAX_FACES; i++) {
         if (metadata->dm.stats.faceIds[i] > 0) {
             mataFaceIds[tempFaceCount] = metadata->dm.stats.faceIds[i];
-            metaFaceScores[tempFaceCount] = metadata->dm.stats.faceScores[i];
+            // clipping fd score because the max face score of android is 100
+            if (metadata->dm.stats.faceScores[i] > 100)
+                metaFaceScores[tempFaceCount] = 100;
+            else
+                metaFaceScores[tempFaceCount] = metadata->dm.stats.faceScores[i];
 
             memcpy(&mataFaceLandmarks[tempFaceCount][0], &metadata->dm.stats.faceLandmarks[i][0], 6*sizeof(uint32_t));
             memcpy(&metaFaceRectangles[tempFaceCount][0], &metadata->dm.stats.faceRectangles[i][0], 4*sizeof(uint32_t));
diff --git a/libcsc/csc.c b/libcsc/csc.c
index c3a8191..4f2aac6 100644
--- a/libcsc/csc.c
+++ b/libcsc/csc.c
@@ -411,7 +411,8 @@
                 csc_handle->dst_format.crop_height,
                 HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->dst_format.color_format),
                 csc_handle->dst_format.cacheable,
-                csc_handle->hw_property.mode_drm);
+                csc_handle->hw_property.mode_drm,
+                0);
             break;
 #endif
         default:
diff --git a/libgscaler/exynos_gsc_utils.h b/libgscaler/exynos_gsc_utils.h
index 0cf4ac1..d49152d 100644
--- a/libgscaler/exynos_gsc_utils.h
+++ b/libgscaler/exynos_gsc_utils.h
@@ -100,6 +100,7 @@
     int                rotation;
     int                flip_horizontal;
     int                flip_vertical;
+    bool               csc_range;
     bool               dirty;
 
     void              *addr[NUM_OF_GSC_PLANES];
diff --git a/libgscaler/exynos_gscaler.c b/libgscaler/exynos_gscaler.c
index 6460baf..360812b 100644
--- a/libgscaler/exynos_gscaler.c
+++ b/libgscaler/exynos_gscaler.c
@@ -619,6 +619,11 @@
         ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_HFLIP) fail", __func__);
         return false;
     }
+
+    if (exynos_v4l2_s_ctrl(fd, V4L2_CID_CSC_RANGE, info->csc_range) < 0) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE) fail", __func__);
+        return false;
+    }
     info->format.type = info->buf_type;
     info->format.fmt.pix_mp.width       = info->width;
     info->format.fmt.pix_mp.height      = info->height;
@@ -1083,7 +1088,8 @@
     unsigned int crop_height,
     unsigned int v4l2_colorformat,
     unsigned int cacheable,
-    unsigned int mode_drm)
+    unsigned int mode_drm,
+    unsigned int narrowRgb)
 {
     Exynos_gsc_In();
 
@@ -1107,6 +1113,7 @@
     gsc_handle->dst.cacheable        = cacheable;
     gsc_handle->dst.mode_drm         = mode_drm;
     gsc_handle->dst.dirty            = true;
+    gsc_handle->dst.csc_range        = !narrowRgb;
 
     exynos_mutex_unlock(gsc_handle->op_mutex);
 
@@ -1356,7 +1363,8 @@
 
     ret = exynos_gsc_set_dst_format(gsc_handle, dst_img->fw, dst_img->fh,
                                   dst_img->x, dst_img->y, dst_img->w, dst_img->h,
-                                  dst_color_space, dst_img->cacheable, dst_img->drmMode);
+                                  dst_color_space, dst_img->cacheable, dst_img->drmMode,
+                                  dst_img->narrowRgb);
     if (ret < 0) {
         ALOGE("%s: fail: exynos_gsc_set_dst_format [fw %d fh %d x %d y %d w %d h %d f %x rot %d]",
             __func__, dst_img->fw, dst_img->fh, dst_img->x, dst_img->y, dst_img->w, dst_img->h,
@@ -1385,6 +1393,7 @@
     unsigned int vflip;
     unsigned int plane_size[NUM_OF_GSC_PLANES];
     bool rgb;
+    int csc_range = !dst_img->narrowRgb;
 
     struct v4l2_rect dst_rect;
     int32_t      src_color_space;
@@ -1562,6 +1571,13 @@
         return -1;
     }
 
+    if (exynos_v4l2_s_ctrl(gsc_handle->gsc_vd_entity->fd, V4L2_CID_CSC_RANGE,
+            csc_range)) {
+        ALOGE("%s::exynos_v4l2_s_ctrl(V4L2_CID_CSC_RANGE: %d) fail", __func__,
+                csc_range);
+        return -1;
+    }
+
       /* set src format  :GSC video dev*/
     fmt.type  = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
     fmt.fmt.pix_mp.width            = gsc_handle->src_img.fw;
diff --git a/libhwc/hwc.cpp b/libhwc/hwc.cpp
index d9c8166..c23e6f0 100644
--- a/libhwc/hwc.cpp
+++ b/libhwc/hwc.cpp
@@ -15,6 +15,7 @@
  */
 #include <errno.h>
 #include <fcntl.h>
+#include <math.h>
 #include <poll.h>
 #include <pthread.h>
 #include <stdio.h>
@@ -55,6 +56,7 @@
 const size_t MAX_PIXELS = 2560 * 1600 * 2;
 const size_t GSC_W_ALIGNMENT = 16;
 const size_t GSC_H_ALIGNMENT = 16;
+const size_t GSC_DST_CROP_W_ALIGNMENT_RGB888 = 32;
 const size_t GSC_DST_W_ALIGNMENT_RGB888 = 32;
 const size_t GSC_DST_H_ALIGNMENT_RGB888 = 1;
 const size_t FIMD_GSC_IDX = 0;
@@ -88,6 +90,7 @@
     exynos_gsc_img  src_cfg;
     exynos_gsc_img  dst_cfg;
     buffer_handle_t dst_buf[NUM_GSC_DST_BUFS];
+    int             dst_buf_fence[NUM_GSC_DST_BUFS];
     size_t          current_buf;
 };
 
@@ -195,6 +198,22 @@
 template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
 template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
 
+template<typename T> void align_crop_and_center(T &w, T &h,
+        hwc_rect_t *crop, size_t alignment)
+{
+    double aspect = 1.0 * h / w;
+    T w_orig = w, h_orig = h;
+
+    w = ALIGN(w, alignment);
+    h = round(aspect * w);
+    if (crop) {
+        crop->left = (w - w_orig) / 2;
+        crop->top = (h - h_orig) / 2;
+        crop->right = crop->left + w_orig;
+        crop->bottom = crop->top + h_orig;
+    }
+}
+
 static bool is_transformed(const hwc_layer_1_t &layer)
 {
     return layer.transform != 0;
@@ -328,15 +347,12 @@
             (layer.displayFrame.right % pixel_alignment) == 0;
 }
 
-static bool dst_crop_w_aligned(const hwc_layer_1_t &layer, int format)
+static bool dst_crop_w_aligned(int dest_w)
 {
-    int dest_w;
     int dst_crop_w_alignement;
 
-    dest_w = WIDTH(layer.displayFrame);
-
    /* GSC's dst crop size should be aligned 128Bytes */
-    dst_crop_w_alignement = 32;
+    dst_crop_w_alignement = GSC_DST_CROP_W_ALIGNMENT_RGB888;
 
     return (dest_w % dst_crop_w_alignement) == 0;
 }
@@ -362,11 +378,16 @@
         dest_w = WIDTH(layer.displayFrame);
         dest_h = HEIGHT(layer.displayFrame);
     }
+
+    if (handle->flags & GRALLOC_USAGE_PROTECTED)
+        align_crop_and_center(dest_w, dest_h, NULL,
+                GSC_DST_CROP_W_ALIGNMENT_RGB888);
+
     int max_downscale = local_path ? 4 : 16;
     const int max_upscale = 8;
 
     return exynos5_format_is_supported_by_gscaler(format) &&
-            dst_crop_w_aligned(layer,format) &&
+            dst_crop_w_aligned(dest_w) &&
             handle->stride <= max_w &&
             handle->stride % GSC_W_ALIGNMENT == 0 &&
             src_w <= dest_w * max_downscale &&
@@ -559,6 +580,22 @@
         return -1;
     }
 
+    char value[PROPERTY_VALUE_MAX];
+    property_get("persist.hdmi.hdcp_enabled", value, "1");
+    int hdcp_enabled = atoi(value);
+
+    if (exynos_v4l2_s_ctrl(dev->hdmi_layers[1].fd, V4L2_CID_TV_HDCP_ENABLE,
+                           hdcp_enabled) < 0)
+        ALOGE("%s: s_ctrl(CID_TV_HDCP_ENABLE) failed %d", __func__, errno);
+
+    /* "3" is RGB709_16_235 */
+    property_get("persist.hdmi.color_range", value, "3");
+    int color_range = atoi(value);
+
+    if (exynos_v4l2_s_ctrl(dev->hdmi_layers[1].fd, V4L2_CID_TV_SET_COLOR_RANGE,
+                           color_range) < 0)
+        ALOGE("%s: s_ctrl(CID_TV_COLOR_RANGE) failed %d", __func__, errno);
+
     hdmi_enable_layer(dev, dev->hdmi_layers[1]);
 
     dev->hdmi_enabled = true;
@@ -599,7 +636,7 @@
         struct v4l2_format fmt;
         memset(&fmt, 0, sizeof(fmt));
         fmt.type  = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-        fmt.fmt.pix_mp.width       = cfg.w;
+        fmt.fmt.pix_mp.width       = h->stride;
         fmt.fmt.pix_mp.height      = cfg.h;
         fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_BGR32;
         fmt.fmt.pix_mp.field       = V4L2_FIELD_ANY;
@@ -729,6 +766,10 @@
         return false;
     }
 
+    if (exynos5_visible_width(layer, handle->format, pdev) < BURSTLEN_BYTES) {
+        ALOGV("\tlayer %u: visible area is too narrow", i);
+        return false;
+    }
     if (exynos5_requires_gscaler(layer, handle->format)) {
         if (!exynos5_supports_gscaler(layer, handle->format, false)) {
             ALOGV("\tlayer %u: gscaler required but not supported", i);
@@ -748,10 +789,6 @@
         ALOGW("\tlayer %u: off-screen", i);
         return false;
     }
-    if (exynos5_visible_width(layer, handle->format, pdev) < BURSTLEN_BYTES) {
-        ALOGV("\tlayer %u: visible area is too narrow", i);
-        return false;
-    }
 
     return true;
 }
@@ -1040,7 +1077,7 @@
 
 static int exynos5_config_gsc_m2m(hwc_layer_1_t &layer,
         alloc_device_t* alloc_device, exynos5_gsc_data_t *gsc_data,
-        int gsc_idx, int dst_format)
+        int gsc_idx, int dst_format, hwc_rect_t *sourceCrop)
 {
     ALOGV("configuring gscaler %u for memory-to-memory", AVAILABLE_GSC_UNITS[gsc_idx]);
 
@@ -1053,6 +1090,10 @@
     memset(&src_cfg, 0, sizeof(src_cfg));
     memset(&dst_cfg, 0, sizeof(dst_cfg));
 
+    hwc_rect_t sourceCropTemp;
+    if (!sourceCrop)
+        sourceCrop = &sourceCropTemp;
+
     src_cfg.x = layer.sourceCrop.left;
     src_cfg.y = layer.sourceCrop.top;
     src_cfg.w = WIDTH(layer.sourceCrop);
@@ -1079,7 +1120,10 @@
     dst_cfg.rot = layer.transform;
     dst_cfg.drmMode = src_cfg.drmMode;
     dst_cfg.format = dst_format;
-    dst_cfg.acquireFenceFd = -1;
+    dst_cfg.narrowRgb = !exynos5_format_is_rgb(src_handle->format);
+    if (dst_cfg.drmMode)
+        align_crop_and_center(dst_cfg.w, dst_cfg.h, sourceCrop,
+                GSC_DST_CROP_W_ALIGNMENT_RGB888);
 
     ALOGV("source configuration:");
     dump_gsc_img(src_cfg);
@@ -1095,8 +1139,8 @@
         if (src_handle->flags & GRALLOC_USAGE_PROTECTED)
             usage |= GRALLOC_USAGE_PROTECTED;
 
-        int w = ALIGN(WIDTH(layer.displayFrame), GSC_DST_W_ALIGNMENT_RGB888);
-        int h = ALIGN(HEIGHT(layer.displayFrame), GSC_DST_H_ALIGNMENT_RGB888);
+        int w = ALIGN(dst_cfg.w, GSC_DST_W_ALIGNMENT_RGB888);
+        int h = ALIGN(dst_cfg.h, GSC_DST_H_ALIGNMENT_RGB888);
 
         for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) {
             if (gsc_data->dst_buf[i]) {
@@ -1104,6 +1148,11 @@
                 gsc_data->dst_buf[i] = NULL;
             }
 
+            if (gsc_data->dst_buf_fence[i] >= 0) {
+                close(gsc_data->dst_buf_fence[i]);
+                gsc_data->dst_buf_fence[i] = -1;
+            }
+
             int ret = alloc_device->alloc(alloc_device, w, h,
                     HAL_PIXEL_FORMAT_RGBX_8888, usage, &gsc_data->dst_buf[i],
                     &dst_stride);
@@ -1123,10 +1172,18 @@
     dst_cfg.fw = dst_handle->stride;
     dst_cfg.fh = dst_handle->vstride;
     dst_cfg.yaddr = dst_handle->fd;
+    dst_cfg.acquireFenceFd = gsc_data->dst_buf_fence[gsc_data->current_buf];
+    gsc_data->dst_buf_fence[gsc_data->current_buf] = -1;
 
     ALOGV("destination configuration:");
     dump_gsc_img(dst_cfg);
 
+    if ((int)dst_cfg.w != WIDTH(layer.displayFrame))
+        ALOGV("padding %u x %u output to %u x %u and cropping to {%u,%u,%u,%u}",
+                WIDTH(layer.displayFrame), HEIGHT(layer.displayFrame),
+                dst_cfg.w, dst_cfg.h, sourceCrop->left, sourceCrop->top,
+                sourceCrop->right, sourceCrop->bottom);
+
     if (gsc_data->gsc) {
         ALOGV("reusing open gscaler %u", AVAILABLE_GSC_UNITS[gsc_idx]);
     } else {
@@ -1174,10 +1231,14 @@
     if (src_cfg.acquireFenceFd >= 0)
         close(src_cfg.acquireFenceFd);
     for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) {
-        if (gsc_data->dst_buf[i]) {
+       if (gsc_data->dst_buf[i]) {
            alloc_device->free(alloc_device, gsc_data->dst_buf[i]);
            gsc_data->dst_buf[i] = NULL;
        }
+       if (gsc_data->dst_buf_fence[i] >= 0) {
+           close(gsc_data->dst_buf_fence[i]);
+           gsc_data->dst_buf_fence[i] = -1;
+       }
     }
     memset(&gsc_data->src_cfg, 0, sizeof(gsc_data->src_cfg));
     memset(&gsc_data->dst_cfg, 0, sizeof(gsc_data->dst_cfg));
@@ -1196,11 +1257,16 @@
 
     exynos_gsc_stop_exclusive(gsc_data.gsc);
     exynos_gsc_destroy(gsc_data.gsc);
-    for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++)
+    for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) {
         if (gsc_data.dst_buf[i])
             pdev->alloc_device->free(pdev->alloc_device, gsc_data.dst_buf[i]);
+        if (gsc_data.dst_buf_fence[i] >= 0)
+            close(gsc_data.dst_buf_fence[i]);
+    }
 
     memset(&gsc_data, 0, sizeof(gsc_data));
+    for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++)
+        gsc_data.dst_buf_fence[i] = -1;
 }
 
 static void exynos5_config_handle(private_handle_t *handle,
@@ -1311,20 +1377,20 @@
                                 handle->format != HAL_PIXEL_FORMAT_RGB_565)
                     dst_format = HAL_PIXEL_FORMAT_RGBX_8888;
 
+                hwc_rect_t sourceCrop = { 0, 0,
+                        WIDTH(layer.displayFrame), HEIGHT(layer.displayFrame) };
                 int err = exynos5_config_gsc_m2m(layer, pdev->alloc_device, &gsc,
-                        gsc_idx, dst_format);
+                        gsc_idx, dst_format, &sourceCrop);
                 if (err < 0) {
                     ALOGE("failed to configure gscaler %u for layer %u",
                             gsc_idx, i);
+                    pdata->gsc_map[i].mode = exynos5_gsc_map_t::GSC_NONE;
                     continue;
                 }
 
                 buffer_handle_t dst_buf = gsc.dst_buf[gsc.current_buf];
-                gsc.current_buf = (gsc.current_buf + 1) % NUM_GSC_DST_BUFS;
                 private_handle_t *dst_handle =
                         private_handle_t::dynamicCast(dst_buf);
-                hwc_rect_t sourceCrop = { 0, 0,
-                        WIDTH(layer.displayFrame), HEIGHT(layer.displayFrame) };
                 int fence = gsc.dst_cfg.releaseFenceFd;
                 exynos5_config_handle(dst_handle, sourceCrop,
                         layer.displayFrame, layer.blending, fence, config[i],
@@ -1418,14 +1484,20 @@
         fence = exynos5_clear_fimd(pdev);
 
     for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
-        if (pdev->bufs.overlay_map[i] != -1 &&
-                        pdev->bufs.gsc_map[i].mode != exynos5_gsc_map_t::GSC_M2M) {
+        if (pdev->bufs.overlay_map[i] != -1) {
             hwc_layer_1_t &layer =
                     contents->hwLayers[pdev->bufs.overlay_map[i]];
             int dup_fd = dup(fence);
             if (dup_fd < 0)
                 ALOGW("release fence dup failed: %s", strerror(errno));
-            layer.releaseFenceFd = dup_fd;
+            if (pdev->bufs.gsc_map[i].mode == exynos5_gsc_map_t::GSC_M2M) {
+                int gsc_idx = pdev->bufs.gsc_map[i].idx;
+                exynos5_gsc_data_t &gsc = pdev->gsc[gsc_idx];
+                gsc.dst_buf_fence[gsc.current_buf] = dup_fd;
+                gsc.current_buf = (gsc.current_buf + 1) % NUM_GSC_DST_BUFS;
+            } else {
+                layer.releaseFenceFd = dup_fd;
+            }
         }
     }
     close(fence);
@@ -1467,20 +1539,24 @@
 
             exynos5_gsc_data_t &gsc = pdev->gsc[HDMI_GSC_IDX];
             int ret = exynos5_config_gsc_m2m(layer, pdev->alloc_device, &gsc, 1,
-                                             HAL_PIXEL_FORMAT_RGBX_8888);
+                                             HAL_PIXEL_FORMAT_RGBX_8888, NULL);
             if (ret < 0) {
                 ALOGE("failed to configure gscaler for video layer");
                 continue;
             }
 
             buffer_handle_t dst_buf = gsc.dst_buf[gsc.current_buf];
-            gsc.current_buf = (gsc.current_buf + 1) % NUM_GSC_DST_BUFS;
             private_handle_t *h = private_handle_t::dynamicCast(dst_buf);
 
             int acquireFenceFd = gsc.dst_cfg.releaseFenceFd;
+            int releaseFenceFd = -1;
 
-            hdmi_output(pdev, pdev->hdmi_layers[0], layer, h, acquireFenceFd, NULL);
+            hdmi_output(pdev, pdev->hdmi_layers[0], layer, h, acquireFenceFd,
+                                                             &releaseFenceFd);
             video_layer = &layer;
+
+            gsc.dst_buf_fence[gsc.current_buf] = releaseFenceFd;
+            gsc.current_buf = (gsc.current_buf + 1) % NUM_GSC_DST_BUFS;
         }
 
         if (layer.compositionType == HWC_FRAMEBUFFER_TARGET) {
@@ -1954,6 +2030,10 @@
           dev->xres, dev->yres, info.width, dev->xdpi / 1000.0,
           info.height, dev->ydpi / 1000.0, refreshRate);
 
+    for (size_t i = 0; i < NUM_GSC_UNITS; i++)
+        for (size_t j = 0; j < NUM_GSC_DST_BUFS; j++)
+            dev->gsc[i].dst_buf_fence[j] = -1;
+
     dev->hdmi_mixer0 = open("/dev/v4l-subdev7", O_RDWR);
     if (dev->hdmi_mixer0 < 0) {
         ALOGE("failed to open hdmi mixer0 subdev");
diff --git a/mobicore/common/LogWrapper/Android.mk b/mobicore/common/LogWrapper/Android.mk
index b869c2b..45d7117 100644
--- a/mobicore/common/LogWrapper/Android.mk
+++ b/mobicore/common/LogWrapper/Android.mk
@@ -12,4 +12,4 @@
 # Enable logging to logcat per default
 LOCAL_CFLAGS += -DLOG_ANDROID
 
-LOCAL_C_INCLUDES += $(call my-dir)
\ No newline at end of file
+LOCAL_C_INCLUDES += hardware/samsung_slsi/exynos5/mobicore/common/LogWrapper
diff --git a/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp b/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp
index 962d2cc..5855bed 100644
--- a/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp
+++ b/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp
@@ -273,9 +273,8 @@
 uint32_t TrustZoneDevice::getMobicoreStatus(void)
 {
     uint32_t status;
-    //IMPROVEMENT-2012-03-07-maneaval Can fcInfo ever fail? Before it threw an
-    //exception but the handler depended on the context.
-    pMcKMod->fcInfo(0, &status, NULL);
+
+    pMcKMod->fcInfo(1, &status, NULL);
 
     return status;
 }
diff --git a/original-kernel-headers/linux/videodev2_exynos_media.h b/original-kernel-headers/linux/videodev2_exynos_media.h
index cbb3942..e15812b 100644
--- a/original-kernel-headers/linux/videodev2_exynos_media.h
+++ b/original-kernel-headers/linux/videodev2_exynos_media.h
@@ -85,6 +85,8 @@
 #define V4L2_CID_TV_ENABLE_HDMI_AUDIO	(V4L2_CID_EXYNOS_BASE + 61)
 #define V4L2_CID_TV_SET_NUM_CHANNELS	(V4L2_CID_EXYNOS_BASE + 62)
 #define V4L2_CID_TV_UPDATE		(V4L2_CID_EXYNOS_BASE + 63)
+#define V4L2_CID_TV_SET_COLOR_RANGE	(V4L2_CID_EXYNOS_BASE + 64)
+#define V4L2_CID_TV_HDCP_ENABLE		(V4L2_CID_EXYNOS_BASE + 65)
 
 /* for color space conversion equation selection */
 #define V4L2_CID_CSC_EQ_MODE		(V4L2_CID_EXYNOS_BASE + 100)