Merge "liboverlay: Fix pipe priority mismatch on new allocations"
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
old mode 100755
new mode 100644
index bdeb8a3..1e99d1a
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -207,6 +207,19 @@
   */
   virtual DisplayError Commit(LayerStack *layer_stack) = 0;
 
+  /*! @brief Method to flush any pending buffers/fences submitted previously via Commit() call.
+
+    @details Client shall call this method to request the Display Engine to release all buffers and
+    respective fences currently in use. This operation may result in a blank display on the panel
+    until a new frame is submitted for composition.
+
+    @return \link DisplayError \endlink
+
+    @sa Prepare
+    @sa Commit
+  */
+  virtual DisplayError Flush() = 0;
+
   /*! @brief Method to get current state of the display device.
 
     @param[out] state \link DisplayState \endlink
@@ -285,6 +298,14 @@
   */
   virtual DisplayError SetVSyncState(bool enable) = 0;
 
+  /*! @brief Method to set idle timeout value. Idle fallback is disabled with timeout value 0.
+
+    @param[in] timeout value in milliseconds.
+
+    @return \link void \endlink
+  */
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms) = 0;
+
  protected:
   virtual ~DisplayInterface() { }
 };
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
old mode 100755
new mode 100644
index 99d3968..7983c84
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -50,6 +50,7 @@
   static inline bool IsVirtualDriver() { return debug_.virtual_driver_; }
   static uint32_t GetSimulationFlag();
   static uint32_t GetHDMIResolution();
+  static uint32_t GetIdleTimeoutMs();
 
  private:
   Debug();
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index 40191e5..c35a4db 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -161,6 +161,10 @@
   if (display_comp_ctx->remaining_strategies != display_comp_ctx->max_strategies) {
     constraints->safe_mode = true;
   }
+
+  if (display_comp_ctx->idle_fallback) {
+    constraints->safe_mode = true;
+  }
 }
 
 void CompManager::PrePrepare(Handle display_ctx, HWLayers *hw_layers) {
@@ -170,6 +174,13 @@
   display_comp_ctx->strategy_intf->Start(&hw_layers->info,
                                          &display_comp_ctx->max_strategies);
   display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
+
+  // Avoid idle fallback, if there is only one app layer.
+  // TODO(user): App layer count will change for hybrid composition
+  uint32_t app_layer_count = hw_layers->info.stack->layer_count - 1;
+  if (!display_comp_ctx->idle_fallback && app_layer_count > 1) {
+    display_comp_ctx->handle_idle_timeout = true;
+  }
 }
 
 DisplayError CompManager::Prepare(Handle display_ctx, HWLayers *hw_layers) {
@@ -230,6 +241,8 @@
   }
 
   res_mgr_.PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
+
+  display_comp_ctx->idle_fallback = false;
 }
 
 void CompManager::Purge(Handle display_ctx) {
@@ -241,6 +254,32 @@
   res_mgr_.Purge(display_comp_ctx->display_resource_ctx);
 }
 
+bool CompManager::ProcessIdleTimeout(Handle display_ctx) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (!display_comp_ctx) {
+    return false;
+  }
+
+  // 1. handle_idle_timeout flag is set to true on start of every draw call, if the current
+  //    composition is not due to idle fallback.
+  // 2. idle_fallback flag will be set only if handle_idle_timeout flag is true and there is no
+  //    update to the screen for specified amount of time.
+  // 3. handle_idle_timeout flag helps us handle the very first idle timeout event and
+  //    ignore the next idle timeout event on consecutive two idle timeout events.
+  if (display_comp_ctx->handle_idle_timeout) {
+    display_comp_ctx->idle_fallback = true;
+    display_comp_ctx->handle_idle_timeout = false;
+
+    return true;
+  }
+
+  return false;
+}
+
 void CompManager::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
 }
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index aed357b..674f0d0 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -46,6 +46,7 @@
   void PostPrepare(Handle display_ctx, HWLayers *hw_layers);
   void PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
+  bool ProcessIdleTimeout(Handle display_ctx);
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
@@ -60,6 +61,12 @@
     DisplayType display_type;
     uint32_t max_strategies;
     uint32_t remaining_strategies;
+    bool idle_fallback;
+    bool handle_idle_timeout;
+
+    DisplayCompositionContext()
+      : display_resource_ctx(NULL), display_type(kPrimary), max_strategies(0),
+        remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true) { }
   };
 
   Locker locker_;
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 080deb7..95e15d5 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -49,6 +49,9 @@
     return error;
   }
 
+  // Set the idle timeout value to driver through sysfs node
+  hw_intf_->SetIdleTimeoutMs(hw_device_, Debug::GetIdleTimeoutMs());
+
   error = hw_intf_->GetNumDisplayAttributes(hw_device_, &num_modes_);
   if (error != kErrorNone) {
     goto CleanupOnError;
@@ -135,6 +138,8 @@
       }
     }
     comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+  } else {
+    return kErrorNotSupported;
   }
 
   return error;
@@ -149,18 +154,19 @@
     return kErrorParameters;
   }
 
-  if (!pending_commit_) {
-    DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
-    return kErrorUndefined;
-  }
-
   if (state_ == kStateOn) {
+    if (!pending_commit_) {
+      DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
+      return kErrorUndefined;
+    }
     error = hw_intf_->Commit(hw_device_, &hw_layers_);
     if (error == kErrorNone) {
       comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
     } else {
       DLOGE("Unexpected error. Commit failed on driver.");
     }
+  } else {
+    return kErrorNotSupported;
   }
 
   pending_commit_ = false;
@@ -168,6 +174,27 @@
   return kErrorNone;
 }
 
+DisplayError DisplayBase::Flush() {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+
+  if (state_ != kStateOn) {
+    return kErrorNone;
+  }
+
+  hw_layers_.info.count = 0;
+  error = hw_intf_->Flush(hw_device_);
+  if (error == kErrorNone) {
+    comp_manager_->Purge(display_comp_ctx_);
+    pending_commit_ = false;
+  } else {
+    DLOGV("Failed to flush device.");
+  }
+
+  return error;
+}
+
 DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
   SCOPE_LOCK(locker_);
 
@@ -307,6 +334,10 @@
   return error;
 }
 
+void DisplayBase::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  hw_intf_->SetIdleTimeoutMs(hw_device_, timeout_ms);
+}
+
 DisplayError DisplayBase::VSync(int64_t timestamp) {
   if (vsync_enable_) {
     DisplayEventVSync vsync;
@@ -321,6 +352,13 @@
   return kErrorNone;
 }
 
+void DisplayBase::IdleTimeout() {
+  bool need_refresh = comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
+  if (need_refresh) {
+    event_handler_->Refresh();
+  }
+}
+
 void DisplayBase::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
 
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 3f0e24f..5ff219b 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -43,6 +43,7 @@
   virtual DisplayError Deinit();
   virtual DisplayError Prepare(LayerStack *layer_stack);
   virtual DisplayError Commit(LayerStack *layer_stack);
+  virtual DisplayError Flush();
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
   virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
@@ -52,10 +53,12 @@
   virtual DisplayError SetDisplayState(DisplayState state);
   virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetVSyncState(bool enable);
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
 
   // Implement the HWEventHandlers
   virtual DisplayError VSync(int64_t timestamp);
   virtual DisplayError Blank(bool blank);
+  virtual void IdleTimeout();
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index 14a09f1..07bbca0 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -77,5 +77,29 @@
   return best_config_mode;
 }
 
+DisplayError DisplayHDMI::SetDisplayState(DisplayState state) {
+  DisplayError error = kErrorNone;
+
+  DLOGI("Set state = %d", state);
+
+  if (state == kStateOff) {
+    SCOPE_LOCK(locker_);
+    if (state == state_) {
+      DLOGI("Same state transition is requested.");
+      return kErrorNone;
+    }
+    error = hw_intf_->Flush(hw_device_);
+    if (error == kErrorNone) {
+      comp_manager_->Purge(display_comp_ctx_);
+      state_ = state;
+      hw_layers_.info.count = 0;
+    }
+  } else {
+    error = DisplayBase::SetDisplayState(state);
+  }
+
+  return error;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 0bb9dc8..8de7fdf 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -33,6 +33,7 @@
  public:
   DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager);
   virtual int GetBestConfig();
+  virtual DisplayError SetDisplayState(DisplayState state);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index e062e48..57a2b69 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -50,11 +50,10 @@
 extern int virtual_close(int fd);
 extern int virtual_poll(struct pollfd *fds,  nfds_t num, int timeout);
 extern ssize_t virtual_pread(int fd, void *data, size_t count, off_t offset);
+extern ssize_t virtual_pwrite(int fd, const void *data, size_t count, off_t offset);
 extern FILE* virtual_fopen(const char *fname, const char *mode);
 extern int virtual_fclose(FILE* fileptr);
 extern ssize_t virtual_getline(char **lineptr, size_t *linelen, FILE *stream);
-extern ssize_t virtual_read(int fd, void *buf, size_t count);
-extern ssize_t virtual_write(int fd, const void *buf, size_t count);
 
 #endif
 
@@ -69,11 +68,10 @@
   close_ = ::close;
   poll_ = ::poll;
   pread_ = ::pread;
+  pwrite_ = ::pwrite;
   fopen_ = ::fopen;
   fclose_ = ::fclose;
   getline_ = ::getline;
-  read_ = ::read;
-  write_ = ::write;
 
 #ifdef DISPLAY_CORE_VIRTUAL_DRIVER
   // If debug property to use virtual driver is set, point to virtual driver interfaces.
@@ -83,11 +81,10 @@
     close_ = virtual_close;
     poll_ = virtual_poll;
     pread_ = virtual_pread;
+    pwrite_ = virtual_pwrite;
     fopen_ = virtual_fopen;
     fclose_ = virtual_fclose;
     getline_ = virtual_getline;
-    read_ = virtual_read;
-    write_ = virtual_write;
   }
 #endif
   for (int i = 0; i < kDeviceMax; i++) {
@@ -99,7 +96,7 @@
   DisplayError error = kErrorNone;
   char node_path[kMaxStringLength] = {0};
   char data[kMaxStringLength] = {0};
-  const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event"};
+  const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify"};
 
   // Read the fb node index
   PopulateFBNodeIndex();
@@ -129,6 +126,11 @@
       for (int event = 0; event < kNumDisplayEvents; event++) {
         pollfd &poll_fd = poll_fds_[display][event];
 
+        if ((primary_panel_info_.type == kCommandModePanel) && (display == kDevicePrimary) &&
+            (!strncmp(event_name[event], "idle_notify", strlen("idle_notify")))) {
+          continue;
+        }
+
         snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_node_index_[display],
                  event_name[event]);
 
@@ -392,17 +394,19 @@
           break;
         }
       }
+
       if (MapHDMIDisplayTiming(timing_mode, &vscreeninfo) == false) {
         return kErrorParameters;
       }
+
       STRUCT_VAR(msmfb_metadata, metadata);
-      memset(&metadata, 0 , sizeof(metadata));
       metadata.op = metadata_op_vic;
       metadata.data.video_info_code = timing_mode->video_format;
       if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) == -1) {
         IOCTL_LOGE(MSMFB_METADATA_SET, hw_context->type);
         return kErrorHardware;
       }
+
       DLOGI("SetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3] & 0xFF00,
             vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
             vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
@@ -476,19 +480,6 @@
       return kErrorHardware;
     }
     break;
-  case kDeviceHDMI:
-    {
-      hw_context->ResetMDPCommit();
-      mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
-      mdp_commit.input_layer_cnt = 0;
-      mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
-      if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
-        IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
-        return kErrorHardware;
-      }
-    }
-    break;
-  case kDeviceVirtual:
   default:
     break;
   }
@@ -617,7 +608,6 @@
     }
   }
 
-  mdp_commit.flags |= MDP_COMMIT_RETIRE_FENCE;
   mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
   if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
@@ -638,6 +628,22 @@
   return kErrorNone;
 }
 
+DisplayError HWFrameBuffer::Flush(Handle device) {
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+
+  hw_context->ResetMDPCommit();
+  mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
+  mdp_commit.input_layer_cnt = 0;
+  mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+
+  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+    IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
 DisplayError HWFrameBuffer::SetFormat(const LayerBufferFormat &source, uint32_t *target) {
   switch (source) {
   case kFormatARGB8888:                 *target = MDP_ARGB_8888;         break;
@@ -714,7 +720,8 @@
 
   typedef void (HWFrameBuffer::*EventHandler)(int, char *);
   EventHandler event_handler[kNumDisplayEvents] = { &HWFrameBuffer::HandleVSync,
-                                                    &HWFrameBuffer::HandleBlank };
+                                                    &HWFrameBuffer::HandleBlank,
+                                                    &HWFrameBuffer::HandleIdleTimeout };
 
   while (!exit_threads_) {
     int error = poll_(poll_fds_[0], kNumPhysicalDisplays * kNumDisplayEvents, -1);
@@ -759,6 +766,10 @@
   // TODO(user): Need to send blank Event
 }
 
+void HWFrameBuffer::HandleIdleTimeout(int display_id, char *data) {
+  event_handler_[display_id]->IdleTimeout();
+}
+
 void HWFrameBuffer::PopulateFBNodeIndex() {
   char stringbuffer[kMaxStringLength];
   DisplayError error = kErrorNone;
@@ -782,16 +793,16 @@
     // TODO(user): For now, assume primary to be cmd/video/lvds/edp mode panel only
     // Need more concrete info from driver
     if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
-      pri_panel_info_.type = kCommandModePanel;
+      primary_panel_info_.type = kCommandModePanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0))  {
-      pri_panel_info_.type = kVideoModePanel;
+      primary_panel_info_.type = kVideoModePanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
-      pri_panel_info_.type = kLVDSPanel;
+      primary_panel_info_.type = kLVDSPanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
-      pri_panel_info_.type = kEDPPanel;
+      primary_panel_info_.type = kEDPPanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
       fb_node_index_[kDeviceHDMI] = i;
@@ -823,27 +834,27 @@
     char *tokens[max_count] = { NULL };
     if (!ParseLine(line, tokens, max_count, &token_count)) {
       if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
-        pri_panel_info_.partial_update = atoi(tokens[1]);
+        primary_panel_info_.partial_update = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
-        pri_panel_info_.left_align = atoi(tokens[1]);
+        primary_panel_info_.left_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
-        pri_panel_info_.width_align = atoi(tokens[1]);
+        primary_panel_info_.width_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
-        pri_panel_info_.top_align = atoi(tokens[1]);
+        primary_panel_info_.top_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
-        pri_panel_info_.height_align = atoi(tokens[1]);
+        primary_panel_info_.height_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
-        pri_panel_info_.min_roi_width = atoi(tokens[1]);
+        primary_panel_info_.min_roi_width = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
-        pri_panel_info_.min_roi_height = atoi(tokens[1]);
+        primary_panel_info_.min_roi_height = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
-        pri_panel_info_.needs_roi_merge = atoi(tokens[1]);
+        primary_panel_info_.needs_roi_merge = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "dynamic_fps_en", strlen("dyn_fps_en"))) {
-        pri_panel_info_.dynamic_fps = atoi(tokens[1]);
+        primary_panel_info_.dynamic_fps = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
-        pri_panel_info_.min_fps = atoi(tokens[1]);
+        primary_panel_info_.min_fps = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
-        pri_panel_info_.max_fps= atoi(tokens[1]);
+        primary_panel_info_.max_fps= atoi(tokens[1]);
       }
     }
   }
@@ -1003,7 +1014,7 @@
     return kErrorHardware;
   }
   char value = enable ? '1' : '0';
-  ssize_t length = write_(hpdfd, &value, 1);
+  ssize_t length = pwrite_(hpdfd, &value, 1, 0);
   if (length <= 0) {
     DLOGE("Write failed 'hpd' = %d", enable);
     ret_value = false;
@@ -1024,7 +1035,7 @@
     return -1;
   }
 
-  length = read_(edid_file, edid_str, sizeof(edid_str)-1);
+  length = pread_(edid_file, edid_str, sizeof(edid_str)-1, 0);
   if (length <= 0) {
     DLOGE("%s: edid_modes file empty");
     edid_str[0] = '\0';
@@ -1076,4 +1087,46 @@
   return true;
 }
 
+void HWFrameBuffer::SetIdleTimeoutMs(Handle device, uint32_t timeout_ms) {
+  char node_path[kMaxStringLength] = {0};
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+
+  DLOGI("idle timeout = %d ms", timeout_ms);
+
+  switch (hw_context->type) {
+  case kDevicePrimary:
+    {
+      // Idle fallback feature is supported only for video mode panel.
+      if (primary_panel_info_.type == kCommandModePanel) {
+        return;
+      }
+
+      snprintf(node_path, sizeof(node_path), "%s%d/idle_time", fb_path_,
+               fb_node_index_[hw_context->type]);
+
+      // Open a sysfs node to send the timeout value to driver.
+      int fd = open_(node_path, O_WRONLY);
+      if (fd < 0) {
+        DLOGE("Unable to open %s, node %s", node_path, strerror(errno));
+        return;
+      }
+
+      char timeout_string[64];
+      snprintf(timeout_string, sizeof(timeout_string), "%d", timeout_ms);
+
+      // Notify driver about the timeout value
+      ssize_t length = pwrite_(fd, timeout_string, strlen(timeout_string), 0);
+      if (length < -1) {
+        DLOGE("Unable to write into %s, node %s", node_path, strerror(errno));
+      }
+
+      close_(fd);
+    }
+    break;
+  default:
+    break;
+  }
+}
+
 }  // namespace sde
+
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index 2fe5078..54f44a1 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -58,6 +58,8 @@
   virtual DisplayError Standby(Handle device);
   virtual DisplayError Validate(Handle device, HWLayers *hw_layers);
   virtual DisplayError Commit(Handle device, HWLayers *hw_layers);
+  virtual DisplayError Flush(Handle device);
+  virtual void SetIdleTimeoutMs(Handle device, uint32_t timeout_ms);
 
  private:
   struct HWContext {
@@ -115,7 +117,7 @@
 
   static const int kMaxStringLength = 1024;
   static const int kNumPhysicalDisplays = 2;
-  static const int kNumDisplayEvents = 2;
+  static const int kNumDisplayEvents = 3;
   static const int kHWMdssVersion5 = 500;  // MDSS_V5
 
   inline DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
@@ -128,6 +130,7 @@
 
   void HandleVSync(int display_id, char *data);
   void HandleBlank(int display_id, char *data);
+  void HandleIdleTimeout(int display_id, char *data);
 
   // Populates HW FrameBuffer Node Index
   void PopulateFBNodeIndex();
@@ -141,7 +144,6 @@
   bool EnableHotPlugDetection(int enable);
   int GetHDMIModeCount();
   bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode, fb_var_screeninfo *info);
-  void ResetHDMIModes();
 
   // Pointers to system calls which are either mapped to actual system call or virtual driver.
   int (*ioctl_)(int, int, ...);
@@ -149,12 +151,10 @@
   int (*close_)(int);
   int (*poll_)(struct pollfd *, nfds_t, int);
   ssize_t (*pread_)(int, void *, size_t, off_t);
+  ssize_t (*pwrite_)(int, const void *, size_t, off_t);
   FILE* (*fopen_)( const char *fname, const char *mode);
   int (*fclose_)(FILE* fileptr);
   ssize_t (*getline_)(char **lineptr, size_t *linelen, FILE *stream);
-  ssize_t (*read_)(int fd, void *buf, size_t count);
-  ssize_t (*write_)(int fd, const void *buf, size_t count);
-
 
   // Store the Device EventHandlers - used for callback
   HWEventHandler *event_handler_[kNumPhysicalDisplays];
@@ -166,7 +166,7 @@
   HWResourceInfo hw_resource_;
   int fb_node_index_[kDeviceMax];
   const char* fb_path_;
-  PanelInfo pri_panel_info_;
+  PanelInfo primary_panel_info_;
   bool hotplug_enabled_;
   uint32_t hdmi_mode_count_;
   uint32_t hdmi_modes_[256];
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index c8611f9..6e87edd 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -145,7 +145,8 @@
 class HWEventHandler {
  public:
   virtual DisplayError VSync(int64_t timestamp) = 0;
-  virtual DisplayError Blank(bool blank)= 0;
+  virtual DisplayError Blank(bool blank) = 0;
+  virtual void IdleTimeout() = 0;
  protected:
   virtual ~HWEventHandler() {}
 };
@@ -169,6 +170,8 @@
   virtual DisplayError Standby(Handle device) = 0;
   virtual DisplayError Validate(Handle device, HWLayers *hw_layers) = 0;
   virtual DisplayError Commit(Handle device, HWLayers *hw_layers) = 0;
+  virtual DisplayError Flush(Handle device) = 0;
+  virtual void SetIdleTimeoutMs(Handle device, uint32_t timeout_ms) = 0;
 
  protected:
   virtual ~HWInterface() { }
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index 1fc1598..0c8859f 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -47,9 +47,16 @@
   rotate->downscale_ratio_y = scale_y;
 
   // downscale when doing rotation
-  dst_rect.right = src_height / rotate->downscale_ratio_x;
-  dst_rect.bottom = src_width / rotate->downscale_ratio_y;
+  if (IsRotationNeeded(transform.rotation)) {
+    dst_rect.right = src_height / rotate->downscale_ratio_x;
+    dst_rect.bottom = src_width / rotate->downscale_ratio_y;
+  } else {
+    dst_rect.right = src_width / rotate->downscale_ratio_x;
+    dst_rect.bottom = src_height / rotate->downscale_ratio_y;
+  }
 
+  dst_rect.right = floorf(dst_rect.right);
+  dst_rect.bottom = floorf(dst_rect.bottom);
   rotate->src_roi = *src_rect;
   rotate->pipe_id = kPipeIdNeedsAssignment;
   rotate->dst_roi = dst_rect;
@@ -67,8 +74,8 @@
   HWPipeInfo *right_pipe = &layer_config->right_pipe;
   layer_config->is_right_pipe = false;
 
-  if ((src_rect.right - src_rect.left) >= kMaxSourcePipeWidth ||
-      (dst_rect.right - dst_rect.left) >= kMaxInterfaceWidth || hw_res_info_.always_src_split) {
+  if ((src_rect.right - src_rect.left) > kMaxSourcePipeWidth ||
+      (dst_rect.right - dst_rect.left) > kMaxInterfaceWidth || hw_res_info_.always_src_split) {
     SplitRect(transform.flip_horizontal, src_rect, dst_rect, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
     left_pipe->pipe_id = kPipeIdNeedsAssignment;
@@ -107,18 +114,24 @@
   scissor.right = FLOAT(display_attributes.x_pixels);
   scissor.bottom = FLOAT(display_attributes.y_pixels);
   CalculateCropRects(scissor, transform, &crop_right, &dst_right);
-  if ((crop_left.right - crop_left.left) >= kMaxSourcePipeWidth) {
-    if (crop_right.right != crop_right.left)
+  if ((crop_left.right - crop_left.left) > kMaxSourcePipeWidth) {
+    if (crop_right.right != crop_right.left) {
+      DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
+               crop_left.right - crop_left.left, crop_right.right - crop_right.left);
       return kErrorNotSupported;
+    }
     // 2 pipes both are on the left
     SplitRect(transform.flip_horizontal, crop_left, dst_left, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
     left_pipe->pipe_id = kPipeIdNeedsAssignment;
     right_pipe->pipe_id = kPipeIdNeedsAssignment;
     layer_config->is_right_pipe = true;
-  } else if ((crop_right.right - crop_right.left) >= kMaxSourcePipeWidth) {
-    if (crop_left.right != crop_left.left)
+  } else if ((crop_right.right - crop_right.left) > kMaxSourcePipeWidth) {
+    if (crop_left.right != crop_left.left) {
+      DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
+               crop_left.right - crop_left.left, crop_right.right - crop_right.left);
       return kErrorNotSupported;
+    }
     // 2 pipes both are on the right
     SplitRect(transform.flip_horizontal, crop_right, dst_right, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
@@ -168,7 +181,7 @@
     Layer& layer = layer_info.stack->layers[layer_info.index[i]];
     float rot_scale_x = 1.0f, rot_scale_y = 1.0f;
     if (!IsValidDimension(layer.src_rect, layer.dst_rect)) {
-      DLOGE_IF(kTagResources, "Input is invalid");
+      DLOGV_IF(kTagResources, "Input is invalid");
       LogRectVerbose("input layer src_rect", layer.src_rect);
       LogRectVerbose("input layer dst_rect", layer.dst_rect);
       return kErrorNotSupported;
@@ -231,6 +244,12 @@
              i, layer_config->left_pipe.pipe_id);
     LogRectVerbose("input layer src_rect", layer.src_rect);
     LogRectVerbose("input layer dst_rect", layer.dst_rect);
+    for (uint32_t k = 0; k < layer_config->num_rotate; k++) {
+      DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f, scale_y = %.2f",
+               k, rot_scale_x, rot_scale_y);
+      LogRectVerbose("rotate src", layer_config->rotates[k].src_roi);
+      LogRectVerbose("rotate dst", layer_config->rotates[k].dst_roi);
+    }
     LogRectVerbose("cropped src_rect", src_rect);
     LogRectVerbose("cropped dst_rect", dst_rect);
     LogRectVerbose("left pipe src", layer_config->left_pipe.src_roi);
@@ -414,7 +433,7 @@
       src.top - roundf(src.top)       ||
       src.right - roundf(src.right)   ||
       src.bottom - roundf(src.bottom)) {
-    DLOGE_IF(kTagResources, "Input ROI is not integral");
+    DLOGV_IF(kTagResources, "Input ROI is not integral");
     return false;
   }
 
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 12ef5bd..e3fbdda 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -775,13 +775,23 @@
 void ResManager::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
   AppendString(buffer, length, "\nresource manager pipe state");
-  for (uint32_t i = 0; i < num_pipe_; i++) {
+  uint32_t i;
+  for (i = 0; i < num_pipe_; i++) {
     SourcePipe *src_pipe = &src_pipes_[i];
     AppendString(buffer, length,
                  "\nindex = %d, id = %x, reserved = %d, state = %d, hw_block = %d, dedicated = %d",
                  src_pipe->index, src_pipe->mdss_pipe_id, src_pipe->reserved_hw_block,
                  src_pipe->state, src_pipe->hw_block_id, src_pipe->dedicated_hw_block);
   }
+
+  for (i = 0; i < hw_res_info_.num_rotator; i++) {
+    if (rotators_[i].client_bit_mask || rotators_[i].request_bit_mask) {
+      AppendString(buffer, length,
+                   "\nrotator = %d, pipe index = %x, client_bit_mask = %x, request_bit_mask = %x",
+                   i, rotators_[i].pipe_index, rotators_[i].client_bit_mask,
+                   rotators_[i].request_bit_mask);
+    }
+  }
 }
 
 DisplayError ResManager::AcquireRotator(DisplayResourceContext *display_resource_ctx,
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index cf0a55f..1f65c50 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -177,7 +177,7 @@
          { return (UINT32(rotation) == 90 || UINT32(rotation) == 270); }
   void LogRectVerbose(const char *prefix, const LayerRect &roi);
   void RotationConfig(const LayerTransform &transform, const float &scale_x,
-                      const float &scale_y,LayerRect *src_rect,
+                      const float &scale_y, LayerRect *src_rect,
                       struct HWLayerConfig *layer_config, uint32_t *rotate_count);
   DisplayError AcquireRotator(DisplayResourceContext *display_resource_ctx,
                               const uint32_t roate_cnt);
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index d765e04..5294faa 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -35,7 +35,8 @@
 
 HWCDisplay::HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type,
                        int id)
-  : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL) {
+  : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL),
+    flush_(false) {
 }
 
 int HWCDisplay::Init() {
@@ -282,6 +283,7 @@
 
   size_t num_hw_layers = content_list->numHwLayers;
   if (num_hw_layers <= 1) {
+    flush_ = true;
     return 0;
   }
 
@@ -338,9 +340,14 @@
   layer_stack_.flags.geometry_changed = ((content_list->flags & HWC_GEOMETRY_CHANGED) > 0);
 
   DisplayError error = display_intf_->Prepare(&layer_stack_);
-  if (UNLIKELY(error != kErrorNone)) {
+  if (error != kErrorNone) {
     DLOGE("Prepare failed. Error = %d", error);
-    return -EINVAL;
+
+    // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
+    // previous buffer and fences are released, and override the error.
+    flush_ = true;
+
+    return 0;
   }
 
   bool needs_fb_refresh = NeedsFrameBufferRefresh(content_list);
@@ -378,38 +385,39 @@
   int status = 0;
 
   size_t num_hw_layers = content_list->numHwLayers;
-  if (num_hw_layers <= 1) {
-    if (!num_hw_layers) {
-      return 0;
+
+  if (!flush_) {
+    for (size_t i = 0; i < num_hw_layers; i++) {
+      hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+      const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+      LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
+
+      if (pvt_handle) {
+        layer_buffer->planes[0].fd = pvt_handle->fd;
+        layer_buffer->planes[0].offset = pvt_handle->offset;
+        layer_buffer->planes[0].stride = pvt_handle->width;
+      }
+
+      layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
     }
 
-    // TODO(user): handle if only 1 layer(fb target) is received.
-    int &acquireFenceFd = content_list->hwLayers[0].acquireFenceFd;
-    if (acquireFenceFd >= 0) {
-      close(acquireFenceFd);
-    }
+    DisplayError error = display_intf_->Commit(&layer_stack_);
+    if (error != kErrorNone) {
+      DLOGE("Commit failed. Error = %d", error);
 
-    return 0;
+      // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
+      // previous buffer and fences are released, and override the error.
+      flush_ = true;
+    }
   }
 
-  for (size_t i = 0; i < num_hw_layers; i++) {
-    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
-    const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
-    LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
-
-    if (pvt_handle) {
-      layer_buffer->planes[0].fd = pvt_handle->fd;
-      layer_buffer->planes[0].offset = pvt_handle->offset;
-      layer_buffer->planes[0].stride = pvt_handle->width;
+  if (flush_) {
+    DisplayError error = display_intf_->Flush();
+    if (error != kErrorNone) {
+      DLOGE("Flush failed. Error = %d", error);
     }
 
-    layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
-  }
-
-  DisplayError error = display_intf_->Commit(&layer_stack_);
-  if (UNLIKELY(error != kErrorNone)) {
-    DLOGE("Commit failed. Error = %d", error);
-    status = -EINVAL;
+    flush_ = false;
   }
 
   for (size_t i = 0; i < num_hw_layers; i++) {
@@ -551,5 +559,11 @@
   return 0;
 }
 
+void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  if (display_intf_) {
+    display_intf_->SetIdleTimeoutMs(timeout_ms);
+  }
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 8ac4b46..262c719 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -42,6 +42,7 @@
   virtual int GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values);
   virtual int GetActiveConfig();
   virtual int SetActiveConfig(int index);
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
 
  protected:
   // Maximum number of layers supported by display engine.
@@ -97,6 +98,7 @@
   LayerStackMemory layer_stack_memory_;
   LayerStack layer_stack_;
   LayerStackCache layer_stack_cache_;
+  bool flush_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 3f99a23..8fd72b8 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -444,6 +444,12 @@
     hwc_procs_->invalidate(hwc_procs_);
     break;
 
+  case qService::IQService::SET_IDLE_TIMEOUT:
+    if (display_primary_) {
+      uint32_t timeout = (uint32_t)input_parcel->readInt32();
+      display_primary_->SetIdleTimeoutMs(timeout);
+    }
+    break;
   default:
     DLOGW("QService command = %d is not supported", command);
     return -EINVAL;
diff --git a/displayengine/libs/utils/debug_android.cpp b/displayengine/libs/utils/debug_android.cpp
old mode 100755
new mode 100644
index 31bd40b..447a88d
--- a/displayengine/libs/utils/debug_android.cpp
+++ b/displayengine/libs/utils/debug_android.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -56,5 +56,14 @@
   return 0;
 }
 
+uint32_t Debug::GetIdleTimeoutMs() {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
+    return atoi(property);
+  }
+
+  return 0;
+}
+
 }  // namespace sde
 
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index a7c4a9a..fd98154 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -37,6 +37,7 @@
 #include "gr.h"
 #include "comptype.h"
 #include "mdp_version.h"
+#include <qdMetaData.h>
 
 #ifdef VENUS_COLOR_FORMAT
 #include <media/msm_media_info.h>
@@ -623,9 +624,19 @@
 int getYUVPlaneInfo(private_handle_t* hnd, struct android_ycbcr* ycbcr)
 {
     int err = 0;
+    int width = hnd->width;
+    int height = hnd->height;
     unsigned int ystride, cstride;
+
     memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
 
+    // Check metadata if the geometry has been updated.
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+    if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+        AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(metadata->bufferDim.sliceWidth,
+                   metadata->bufferDim.sliceHeight, hnd->format, 0, width, height);
+    }
+
     // Get the chroma offsets from the handle width/height. We take advantage
     // of the fact the width _is_ the stride
     switch (hnd->format) {
@@ -634,10 +645,10 @@
         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
         case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
-            ystride = cstride = hnd->width;
+            ystride = cstride = width;
             ycbcr->y  = (void*)hnd->base;
-            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
-            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
+            ycbcr->cb = (void*)(hnd->base + ystride * height);
+            ycbcr->cr = (void*)(hnd->base + ystride * height + 1);
             ycbcr->ystride = ystride;
             ycbcr->cstride = cstride;
             ycbcr->chroma_step = 2;
@@ -648,10 +659,10 @@
         case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
         case HAL_PIXEL_FORMAT_NV21_ZSL:
         case HAL_PIXEL_FORMAT_RAW_SENSOR:
-            ystride = cstride = hnd->width;
+            ystride = cstride = width;
             ycbcr->y  = (void*)hnd->base;
-            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
-            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
+            ycbcr->cr = (void*)(hnd->base + ystride * height);
+            ycbcr->cb = (void*)(hnd->base + ystride * height + 1);
             ycbcr->ystride = ystride;
             ycbcr->cstride = cstride;
             ycbcr->chroma_step = 2;
@@ -659,16 +670,15 @@
 
         //Planar
         case HAL_PIXEL_FORMAT_YV12:
-            ystride = hnd->width;
-            cstride = ALIGN(hnd->width/2, 16);
+            ystride = width;
+            cstride = ALIGN(width/2, 16);
             ycbcr->y  = (void*)hnd->base;
-            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
-            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
-                    cstride * hnd->height/2);
+            ycbcr->cr = (void*)(hnd->base + ystride * height);
+            ycbcr->cb = (void*)(hnd->base + ystride * height +
+                    cstride * height/2);
             ycbcr->ystride = ystride;
             ycbcr->cstride = cstride;
             ycbcr->chroma_step = 1;
-
         break;
         //Unsupported formats
         case HAL_PIXEL_FORMAT_YCbCr_422_I:
@@ -764,12 +774,15 @@
 
 bool isUBwcEnabled(int format, int usage)
 {
-    if (isUBwcFormat(format) ||
-        ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) && isUBwcSupported(format)))
-    {
-        // Allow UBWC, only if GPU supports it and CPU usage flags are not set
-        if (AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format) &&
-            !(usage & (GRALLOC_USAGE_SW_READ_MASK |
+    // Allow UBWC, if client is using an explicitly defined UBWC pixel format.
+    if (isUBwcFormat(format))
+        return true;
+
+    // Allow UBWC, if client sets UBWC gralloc usage flag & GPU supports format.
+    if ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) && isUBwcSupported(format) &&
+        AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format)) {
+        // Allow UBWC, only if CPU usage flags are not set
+        if (!(usage & (GRALLOC_USAGE_SW_READ_MASK |
                       GRALLOC_USAGE_SW_WRITE_MASK))) {
             return true;
         }
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 9ab9d09..48da09e 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -149,7 +149,8 @@
             flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
         }
 
-        if (isUBwcEnabled(format, usage)) {
+        if (AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format) &&
+            isUBwcEnabled(format, usage)) {
             flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
         }
 
diff --git a/libhdmi/hdmi.cpp b/libhdmi/hdmi.cpp
index 7d709cb..bca7a0b 100644
--- a/libhdmi/hdmi.cpp
+++ b/libhdmi/hdmi.cpp
@@ -21,7 +21,6 @@
 #define DEBUG 0
 #include <fcntl.h>
 #include <linux/msm_mdp.h>
-#include <video/msm_hdmi_modes.h>
 #include <linux/fb.h>
 #include <sys/ioctl.h>
 #include <cutils/properties.h>
@@ -38,62 +37,6 @@
 #define UNKNOWN_STRING                  "unknown"
 #define SPD_NAME_LENGTH                 16
 
-/* The array gEDIDData contains a list of modes currently
- * supported by HDMI and display, and modes that are not
- * supported i.e. interlaced modes.
-
- * In order to add support for a new mode, the mode must be
- * appended to the end of the array.
- *
- * Each new entry must contain the following:
- * -Mode: a video format defined in msm_hdmi_modes.h
- * -Width: x resolution for the mode
- * -Height: y resolution for the mode
- * -FPS: the frame rate for the mode
- * -Mode Order: the priority for the new mode that is used when determining
- *  the best mode when the HDMI display is connected.
- */
-EDIDData gEDIDData [] = {
-    EDIDData(HDMI_VFRMT_1440x480i60_4_3, 1440, 480, 60, 1),
-    EDIDData(HDMI_VFRMT_1440x480i60_16_9, 1440, 480, 60, 2),
-    EDIDData(HDMI_VFRMT_1440x576i50_4_3, 1440, 576, 50, 3),
-    EDIDData(HDMI_VFRMT_1440x576i50_16_9, 1440, 576, 50, 4),
-    EDIDData(HDMI_VFRMT_1920x1080i60_16_9, 1920, 1080, 60, 5),
-    EDIDData(HDMI_VFRMT_640x480p60_4_3, 640, 480, 60, 6),
-    EDIDData(HDMI_VFRMT_720x480p60_4_3, 720, 480, 60, 7),
-    EDIDData(HDMI_VFRMT_720x480p60_16_9, 720, 480, 60, 8),
-    EDIDData(HDMI_VFRMT_720x576p50_4_3, 720, 576, 50, 9),
-    EDIDData(HDMI_VFRMT_720x576p50_16_9, 720, 576, 50, 10),
-    EDIDData(HDMI_VFRMT_800x600p60_4_3, 800, 600, 60, 11),
-    EDIDData(HDMI_VFRMT_848x480p60_16_9, 848, 480, 60, 12),
-    EDIDData(HDMI_VFRMT_1024x768p60_4_3, 1024, 768, 60, 13),
-    EDIDData(HDMI_VFRMT_1280x1024p60_5_4, 1280, 1024, 60, 14),
-    EDIDData(HDMI_VFRMT_1280x720p50_16_9, 1280, 720, 50, 15),
-    EDIDData(HDMI_VFRMT_1280x720p60_16_9, 1280, 720, 60, 16),
-    EDIDData(HDMI_VFRMT_1280x800p60_16_10, 1280, 800, 60, 17),
-    EDIDData(HDMI_VFRMT_1280x960p60_4_3, 1280, 960, 60, 18),
-    EDIDData(HDMI_VFRMT_1360x768p60_16_9, 1360, 768, 60, 19),
-    EDIDData(HDMI_VFRMT_1366x768p60_16_10, 1366, 768, 60, 20),
-    EDIDData(HDMI_VFRMT_1440x900p60_16_10, 1440, 900, 60, 21),
-    EDIDData(HDMI_VFRMT_1400x1050p60_4_3, 1400, 1050, 60, 22),
-    EDIDData(HDMI_VFRMT_1680x1050p60_16_10, 1680, 1050, 60, 23),
-    EDIDData(HDMI_VFRMT_1600x1200p60_4_3, 1600, 1200, 60, 24),
-    EDIDData(HDMI_VFRMT_1920x1080p24_16_9, 1920, 1080, 24, 25),
-    EDIDData(HDMI_VFRMT_1920x1080p25_16_9, 1920, 1080, 25, 26),
-    EDIDData(HDMI_VFRMT_1920x1080p30_16_9, 1920, 1080, 30, 27),
-    EDIDData(HDMI_VFRMT_1920x1080p50_16_9, 1920, 1080, 50, 28),
-    EDIDData(HDMI_VFRMT_1920x1080p60_16_9, 1920, 1080, 60, 29),
-    EDIDData(HDMI_VFRMT_1920x1200p60_16_10, 1920, 1200, 60, 30),
-    EDIDData(HDMI_VFRMT_2560x1600p60_16_9, 2560, 1600, 60, 31),
-    EDIDData(HDMI_VFRMT_3840x2160p24_16_9, 3840, 2160, 24, 32),
-    EDIDData(HDMI_VFRMT_3840x2160p25_16_9, 3840, 2160, 25, 33),
-    EDIDData(HDMI_VFRMT_3840x2160p30_16_9, 3840, 2160, 30, 34),
-    EDIDData(HDMI_VFRMT_4096x2160p24_16_9, 4096, 2160, 24, 35),
-};
-
-// Number of modes in gEDIDData
-const int gEDIDCount = (sizeof(gEDIDData)/sizeof(gEDIDData)[0]);
-
 int HDMIDisplay::configure() {
     if(!openFrameBuffer()) {
         ALOGE("%s: Failed to open FB: %d", __FUNCTION__, mFbNum);
@@ -135,8 +78,8 @@
 }
 
 void HDMIDisplay::getAttributes(uint32_t& width, uint32_t& height) {
-    uint32_t fps = 0;
-    getAttrForMode(width, height, fps);
+    uint32_t refresh = 0, fps = 0;
+    getAttrForConfig(mActiveConfig, width, height, refresh, fps);
 }
 
 int HDMIDisplay::teardown() {
@@ -167,14 +110,7 @@
         writeHPDOption(0);
     }
 
-    // for HDMI - retreive all the modes supported by the driver
     if(mFbNum != -1) {
-        supported_video_mode_lut =
-                        new msm_hdmi_mode_timing_info[HDMI_VFRMT_MAX];
-        // Populate the mode table for supported modes
-        MSM_HDMI_MODES_INIT_TIMINGS(supported_video_mode_lut);
-        MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_mode_lut,
-                                        MSM_HDMI_MODES_ALL);
         // Update the Source Product Information
         // Vendor Name
         setSPDInfo("vendor_name", "ro.product.manufacturer");
@@ -298,7 +234,6 @@
 
 HDMIDisplay::~HDMIDisplay()
 {
-    delete [] supported_video_mode_lut;
     closeFrameBuffer();
 }
 
@@ -356,7 +291,7 @@
 bool HDMIDisplay::readResolution()
 {
     ssize_t len = -1;
-    char edidStr[128] = {'\0'};
+    char edidStr[PAGE_SIZE] = {'\0'};
 
     int hdmiEDIDFile = openDeviceNode("edid_modes", O_RDONLY);
     if (hdmiEDIDFile < 0) {
@@ -383,6 +318,25 @@
         ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__,
                  mModeCount);
     }
+    // Populate the internal data structure with the timing information
+    // for each edid mode read from the driver
+    if (mModeCount > 0) {
+        mDisplayConfigs = new msm_hdmi_mode_timing_info[mModeCount];
+        readConfigs();
+    } else {
+        // If we fail to read from EDID when HDMI is connected, then
+        // mModeCount will be 0 and bestConfigIndex will be invalid.
+        // In this case, we populate the mEDIDModes structure with
+        // a default mode at config index 0.
+        uint32_t defaultConfigIndex = 0;
+        mModeCount = 1;
+        mEDIDModes[defaultConfigIndex] = HDMI_VFRMT_640x480p60_4_3;
+        struct msm_hdmi_mode_timing_info defaultMode =
+                HDMI_VFRMT_640x480p60_4_3_TIMING;
+        mDisplayConfigs = new msm_hdmi_mode_timing_info[mModeCount];
+        mDisplayConfigs[defaultConfigIndex] = defaultMode;
+        ALOGD("%s Defaulting to HDMI_VFRMT_640x480p60_4_3", __FUNCTION__);
+    }
 
     return (len > 0);
 }
@@ -421,30 +375,22 @@
     mYres = 0;
     mVsyncPeriod = 0;
     mMDPScalingMode = false;
+    if (mDisplayConfigs) {
+        delete [] mDisplayConfigs;
+        mDisplayConfigs = 0;
+    }
     // Reset the underscan supported system property
     const char* prop = "0";
     property_set("hw.underscan_supported", prop);
 }
 
-int HDMIDisplay::getModeOrder(int mode)
-{
-    for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
-        if (gEDIDData[dataIndex].mMode == mode) {
-            return gEDIDData[dataIndex].mModeOrder;
-        }
-    }
-    ALOGE("%s Mode not found: %d", __FUNCTION__, mode);
-    return -1;
-}
-
 /// Returns the index of the user mode set(if any) using adb shell
 int HDMIDisplay::getUserConfig() {
     /* Based on the property set the resolution */
     char property_value[PROPERTY_VALUE_MAX];
     property_get("hw.hdmi.resolution", property_value, "-1");
     int mode = atoi(property_value);
-    // We dont support interlaced modes
-    if(isValidMode(mode) && !isInterlacedMode(mode)) {
+    if(isValidMode(mode)) {
         ALOGD_IF(DEBUG, "%s: setting the HDMI mode = %d", __FUNCTION__, mode);
         return getModeIndex(mode);
     }
@@ -453,61 +399,137 @@
 
 // Get the index of the best mode for the current HD TV
 int HDMIDisplay::getBestConfig() {
-    int bestOrder = 0;
-    int bestMode = HDMI_VFRMT_640x480p60_4_3;
-    int bestModeIndex = -1;
-    // for all the edid read, get the best mode
-    for(int i = 0; i < mModeCount; i++) {
-        int mode = mEDIDModes[i];
-        int order = getModeOrder(mode);
-        if (order > bestOrder) {
-            bestOrder = order;
-            bestMode = mode;
-            bestModeIndex = i;
+    int bestConfigIndex = 0;
+    int edidMode = -1;
+    struct msm_hdmi_mode_timing_info currentModeInfo = {0};
+    struct msm_hdmi_mode_timing_info bestModeInfo = {0};
+    bestModeInfo.video_format = 0;
+    bestModeInfo.active_v = 0;
+    bestModeInfo.active_h = 0;
+    bestModeInfo.refresh_rate = 0;
+    bestModeInfo.ar = HDMI_RES_AR_INVALID;
+
+    // for all the timing info read, get the best config
+    for (int configIndex = 0; configIndex < mModeCount; configIndex++) {
+        currentModeInfo = mDisplayConfigs[configIndex];
+
+        if (!currentModeInfo.supported) {
+            ALOGD("%s EDID Mode %d is not supported", __FUNCTION__, edidMode);
+            continue;
+        }
+
+        ALOGD_IF(DEBUG, "%s Best (%d) : (%dx%d) @ %d;"
+                " Current (%d) (%dx%d) @ %d",
+                __FUNCTION__, bestConfigIndex, bestModeInfo.active_h,
+                bestModeInfo.active_v, bestModeInfo.refresh_rate, configIndex,
+                currentModeInfo.active_h, currentModeInfo.active_v,
+                currentModeInfo.refresh_rate);
+
+        // Compare two HDMI modes in order of height, width, refresh rate and
+        // aspect ratio.
+        if (currentModeInfo.active_v > bestModeInfo.active_v) {
+            bestConfigIndex = configIndex;
+        } else if (currentModeInfo.active_v == bestModeInfo.active_v) {
+            if (currentModeInfo.active_h > bestModeInfo.active_h) {
+                bestConfigIndex = configIndex;
+            } else if (currentModeInfo.active_h == bestModeInfo.active_h) {
+                if (currentModeInfo.refresh_rate > bestModeInfo.refresh_rate) {
+                    bestConfigIndex = configIndex;
+                } else if (currentModeInfo.refresh_rate ==
+                        bestModeInfo.refresh_rate) {
+                    if (currentModeInfo.ar > bestModeInfo.ar) {
+                        bestConfigIndex = configIndex;
+                    }
+                }
+            }
+        }
+        if (bestConfigIndex == configIndex) {
+            bestModeInfo = mDisplayConfigs[bestConfigIndex];
         }
     }
-    // If we fail to read from EDID when HDMI is connected, then
-    // mModeCount will be 0 and bestModeIndex will be invalid.
-    // In this case, we populate the mEDIDModes structure with
-    // a default mode at index 0.
-    if (bestModeIndex == -1) {
-        bestModeIndex = 0;
-        mModeCount = 1;
-        mEDIDModes[bestModeIndex] = bestMode;
+    return bestConfigIndex;
+}
+
+// Utility function used to request HDMI driver to write a new page of timing
+// info into res_info node
+void HDMIDisplay::requestNewPage(int pageNumber) {
+    char pageString[PAGE_SIZE];
+    int fd = openDeviceNode("res_info", O_WRONLY);
+    if (fd >= 0) {
+        snprintf(pageString, sizeof(pageString), "%d", pageNumber);
+        ALOGD_IF(DEBUG, "%s: page=%s", __FUNCTION__, pageString);
+        ssize_t err = write(fd, pageString, sizeof(pageString));
+        if (err <= 0) {
+            ALOGE("%s: Write to res_info failed (%d)", __FUNCTION__, errno);
+        }
+        close(fd);
     }
-    return bestModeIndex;
+}
+
+// Reads the contents of res_info node into a buffer if the file is not empty
+bool HDMIDisplay::readResFile(char * configBuffer) {
+    bool fileRead = false;
+    size_t bytesRead = 0;
+    int fd = openDeviceNode("res_info", O_RDONLY);
+    if (fd >= 0 && (bytesRead = read(fd, configBuffer, PAGE_SIZE)) != 0) {
+        fileRead = true;
+    }
+    close(fd);
+    ALOGD_IF(DEBUG, "%s: bytesRead=%d fileRead=%d",
+            __FUNCTION__, bytesRead, fileRead);
+    return fileRead;
+}
+
+// Populates the internal timing info structure with the timing info obtained
+// from the HDMI driver
+void HDMIDisplay::readConfigs() {
+    int configIndex = 0;
+    int pageNumber = MSM_HDMI_INIT_RES_PAGE;
+    long unsigned int size = sizeof(msm_hdmi_mode_timing_info);
+
+    while (true) {
+        char configBuffer[PAGE_SIZE] = {0};
+        msm_hdmi_mode_timing_info *info =
+                (msm_hdmi_mode_timing_info*) configBuffer;
+
+        if (!readResFile(configBuffer))
+            break;
+
+        while (info->video_format && size < PAGE_SIZE) {
+            mDisplayConfigs[configIndex] = *info;
+            size += sizeof(msm_hdmi_mode_timing_info);
+            info++;
+            ALOGD_IF(DEBUG, "%s: Config=%d Mode %d: (%dx%d) @ %d",
+                    __FUNCTION__, configIndex,
+                    mDisplayConfigs[configIndex].video_format,
+                    mDisplayConfigs[configIndex].active_h,
+                    mDisplayConfigs[configIndex].active_v,
+                    mDisplayConfigs[configIndex].refresh_rate);
+            configIndex++;
+        }
+        size = sizeof(msm_hdmi_mode_timing_info);
+        // Request HDMI driver to populate res_info with more
+        // timing information
+        pageNumber++;
+        requestNewPage(pageNumber);
+    }
 }
 
 inline bool HDMIDisplay::isValidMode(int ID)
 {
     bool valid = false;
-    for (int i = 0; i < mModeCount; i++) {
-        if(ID == mEDIDModes[i]) {
-            valid = true;
-            break;
-        }
+    int modeIndex = getModeIndex(ID);
+    if (ID <= 0 || modeIndex < 0 || modeIndex > mModeCount) {
+        return false;
+    }
+    struct msm_hdmi_mode_timing_info* mode = &mDisplayConfigs[modeIndex];
+    // We dont support interlaced modes
+    if (mode->supported && !mode->interlaced) {
+        valid = true;
     }
     return valid;
 }
 
-// returns true if the mode(ID) is interlaced mode format
-bool HDMIDisplay::isInterlacedMode(int ID) {
-    bool interlaced = false;
-    switch(ID) {
-        case HDMI_VFRMT_1440x480i60_4_3:
-        case HDMI_VFRMT_1440x480i60_16_9:
-        case HDMI_VFRMT_1440x576i50_4_3:
-        case HDMI_VFRMT_1440x576i50_16_9:
-        case HDMI_VFRMT_1920x1080i60_16_9:
-            interlaced = true;
-            break;
-        default:
-            interlaced = false;
-            break;
-    }
-    return interlaced;
-}
-
 // Does a put_vscreen info on the HDMI interface which will update
 // the configuration (resolution, timing info) to match mCurrentMode
 void HDMIDisplay::activateDisplay()
@@ -525,16 +547,7 @@
             mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
             mVInfo.pixclock/1000/1000);
 
-    const struct msm_hdmi_mode_timing_info *mode =
-            &supported_video_mode_lut[0];
-    for (unsigned int i = 0; i < HDMI_VFRMT_MAX; ++i) {
-        const struct msm_hdmi_mode_timing_info *cur =
-                &supported_video_mode_lut[i];
-        if (cur->video_format == (uint32_t)mCurrentMode) {
-            mode = cur;
-            break;
-        }
-    }
+    struct msm_hdmi_mode_timing_info *mode = &mDisplayConfigs[mActiveConfig];
     setDisplayTiming(mVInfo, mode);
     ALOGD_IF(DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx %d"
             "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, mCurrentMode,
@@ -585,9 +598,9 @@
 
 
 void HDMIDisplay::setAttributes() {
-    uint32_t fps = 0;
+    uint32_t refresh = 0, fps = 0;
     // Always set dpyAttr res to mVInfo res
-    getAttrForMode(mXres, mYres, fps);
+    getAttrForConfig(mActiveConfig, mXres, mYres, refresh, fps);
     mMDPScalingMode = false;
 
     if(overlay::Overlay::getInstance()->isUIScalingOnExternalSupported()
@@ -653,19 +666,6 @@
     ALOGD_IF(DEBUG, "%s xres=%d, yres=%d", __FUNCTION__, mXres, mYres);
 }
 
-void HDMIDisplay::getAttrForMode(uint32_t& width, uint32_t& height,
-        uint32_t& fps) {
-    for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
-        if (gEDIDData[dataIndex].mMode == mCurrentMode) {
-            width = gEDIDData[dataIndex].mWidth;
-            height = gEDIDData[dataIndex].mHeight;
-            fps = gEDIDData[dataIndex].mFps;
-            return;
-        }
-    }
-    ALOGE("%s Unable to get attributes for %d", __FUNCTION__, mCurrentMode);
-}
-
 /* returns the fd related to the node specified*/
 int HDMIDisplay::openDeviceNode(const char* node, int fileMode) const {
     char sysFsFilePath[MAX_SYSFS_FILE_PATH];
@@ -743,8 +743,8 @@
 // not match the current config
 bool HDMIDisplay::isValidConfigChange(int newConfig) {
     int newMode = mEDIDModes[newConfig];
-    uint32_t width = 0, height = 0, refresh = 0;
-    getAttrForConfig(newConfig, width, height, refresh);
+    uint32_t width = 0, height = 0, refresh = 0, fps = 0;
+    getAttrForConfig(newConfig, width, height, refresh, fps);
     return ((mXres == width) && (mYres == height)) || mEnableResolutionChange;
 }
 
@@ -760,21 +760,16 @@
 }
 
 int HDMIDisplay::getAttrForConfig(int config, uint32_t& xres,
-        uint32_t& yres, uint32_t& refresh) const {
+        uint32_t& yres, uint32_t& refresh, uint32_t& fps) const {
     if(config < 0 || config > mModeCount) {
         ALOGE("%s Invalid configuration %d", __FUNCTION__, config);
         return -EINVAL;
     }
-    int mode = mEDIDModes[config];
-    uint32_t fps = 0;
-    // Retrieve the mode attributes from gEDIDData
-    for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
-        if (gEDIDData[dataIndex].mMode == mode) {
-            xres = gEDIDData[dataIndex].mWidth;
-            yres = gEDIDData[dataIndex].mHeight;
-            fps = gEDIDData[dataIndex].mFps;
-        }
-    }
+
+    xres = mDisplayConfigs[config].active_h;
+    yres = mDisplayConfigs[config].active_v;
+    fps = (mDisplayConfigs[config].refresh_rate / 1000);
+
     refresh = (uint32_t) 1000000000l / fps;
     ALOGD_IF(DEBUG, "%s xres(%d) yres(%d) fps(%d) refresh(%d)", __FUNCTION__,
             xres, yres, fps, refresh);
diff --git a/libhdmi/hdmi.h b/libhdmi/hdmi.h
index d262a63..32c48ff 100644
--- a/libhdmi/hdmi.h
+++ b/libhdmi/hdmi.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -22,6 +22,7 @@
 #define HWC_HDMI_DISPLAY_H
 
 #include <linux/fb.h>
+#include <video/msm_hdmi_modes.h>
 
 struct msm_hdmi_mode_timing_info;
 
@@ -35,16 +36,6 @@
     HDMI_SCAN_BOTH_SUPPORTED     = 3
 };
 
-// Structure to store EDID related data
-struct EDIDData {
-    int mMode, mWidth, mHeight, mFps;
-    // Predetermined ordering for each mode
-    int mModeOrder;
-    EDIDData(int mode, int width, int height, int fps, int order)
-    : mMode(mode), mWidth(width), mHeight(height), mFps(fps), mModeOrder(order)
-    { }
-};
-
 class HDMIDisplay
 {
 public:
@@ -71,7 +62,7 @@
     int getActiveConfig() const { return mActiveConfig; };
     int setActiveConfig(int newConfig);
     int getAttrForConfig(int config, uint32_t& xres,
-            uint32_t& yres, uint32_t& refresh) const;
+            uint32_t& yres, uint32_t& refresh, uint32_t& fps) const;
     int getDisplayConfigs(uint32_t* configs, size_t* numConfigs) const;
 
 private:
@@ -90,10 +81,12 @@
     bool isInterlacedMode(int mode);
     void resetInfo();
     void setAttributes();
-    void getAttrForMode(uint32_t& width, uint32_t& height, uint32_t& fps);
     int openDeviceNode(const char* node, int fileMode) const;
     int getModeIndex(int mode);
     bool isValidConfigChange(int newConfig);
+    void requestNewPage(int pageNumber);
+    void readConfigs();
+    bool readResFile(char* configBuffer);
 
     int mFd;
     int mFbNum;
@@ -105,11 +98,11 @@
     int mActiveConfig;
     // mEDIDModes contains a list of HDMI video formats (modes) supported by the
     // HDMI display
-    int mEDIDModes[64];
+    int mEDIDModes[HDMI_VFRMT_MAX];
     int mModeCount;
     fb_var_screeninfo mVInfo;
     // Holds all the HDMI modes and timing info supported by driver
-    msm_hdmi_mode_timing_info* supported_video_mode_lut;
+    msm_hdmi_mode_timing_info *mDisplayConfigs;
     uint32_t mXres, mYres, mVsyncPeriod, mPrimaryWidth, mPrimaryHeight;
     bool mMDPScalingMode;
     bool mUnderscanSupported;
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index fd3bb69..b84daad 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -752,7 +752,7 @@
     bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
     // If hotpluggable or virtual displays are inactive return error
     if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
-        ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
+        ALOGW("%s display (%d) is not connected anymore", __FUNCTION__, disp);
         return -EINVAL;
     }
 
@@ -809,10 +809,11 @@
     const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
             sizeof(DISPLAY_ATTRIBUTES)[0]);
 
-    uint32_t xres = 0, yres = 0, refresh = 0;
+    uint32_t xres = 0, yres = 0, refresh = 0, fps = 0;
     int ret = 0;
     if (hotPluggable) {
-        ret = ctx->mHDMIDisplay->getAttrForConfig(config, xres, yres, refresh);
+        ret = ctx->mHDMIDisplay->getAttrForConfig(config, xres,
+                yres, refresh, fps);
         if(ret < 0) {
             ALOGE("%s Error getting attributes for config %d",
                     __FUNCTION__, config);
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 38c0810..546a67b 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -216,8 +216,13 @@
         return false;
     }
 
-    if (mEngine == NULL || !(validateParams(ctx, list))) {
-        ALOGE("%s: Invalid Params", __FUNCTION__);
+    if (mEngine == NULL) {
+        ALOGW("%s: Copybit HAL not enabled", __FUNCTION__);
+        return false;
+    }
+
+    if (!(validateParams(ctx, list))) {
+        ALOGE("%s: validateParams() failed", __FUNCTION__);
         return false;
     }
     PtorInfo* ptorInfo = &(ctx->mPtorInfo);
diff --git a/libhwcomposer/hwc_dump_layers.cpp b/libhwcomposer/hwc_dump_layers.cpp
index 6a8feb2..aad984d 100644
--- a/libhwcomposer/hwc_dump_layers.cpp
+++ b/libhwcomposer/hwc_dump_layers.cpp
@@ -130,7 +130,7 @@
         mDumpCntLimPng = (mDumpCntLimPng < 0) ? 0: mDumpCntLimPng;
         if (mDumpCntLimPng) {
             snprintf(mDumpDirPng, sizeof(mDumpDirPng),
-                    "/data/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
+                    "/data/misc/display/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
                     dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
                     dumpTime.tm_mday, dumpTime.tm_hour,
                     dumpTime.tm_min, dumpTime.tm_sec);
@@ -160,7 +160,7 @@
         mDumpCntLimRaw = (mDumpCntLimRaw < 0) ? 0: mDumpCntLimRaw;
         if (mDumpCntLimRaw) {
             snprintf(mDumpDirRaw, sizeof(mDumpDirRaw),
-                    "/data/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
+                    "/data/misc/display/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
                     dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
                     dumpTime.tm_mday, dumpTime.tm_hour,
                     dumpTime.tm_min, dumpTime.tm_sec);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 7f31ad0..34cc39f 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -217,6 +217,9 @@
     mCurrentFrame.reset(numLayers);
     ctx->mOverlay->clear(mDpy);
     ctx->mLayerRotMap[mDpy]->clear();
+    resetROI(ctx, mDpy);
+    memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+    mCurrentFrame.dropCount = 0;
 }
 
 void MDPComp::reset() {
@@ -593,7 +596,8 @@
             hwc_rect_t updatingRect = dst;
 
 #ifdef QCOM_BSP
-            if(!needsScaling(layer) && !layer->transform)
+            if(!needsScaling(layer) && !layer->transform &&
+                   (!isYuvBuffer((private_handle_t *)layer->handle)))
             {
                 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
                 int x_off = dst.left - src.left;
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index d1c68a5..c6179e4 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -121,10 +121,19 @@
             /* We need to send hotplug to SF only when we are disconnecting
              * HDMI as an external display. */
             if(dpy == HWC_DISPLAY_EXTERNAL) {
-                ALOGE_IF(UEVENT_DEBUG,"%s:Sending EXTERNAL OFFLINE hotplug"
-                        "event", __FUNCTION__);
+                ALOGI("%s: Sending EXTERNAL OFFLINE event", __FUNCTION__);
                 ctx->proc->hotplug(ctx->proc, dpy, EXTERNAL_OFFLINE);
             }
+
+            //On 8994, 8992 due to hardware limitations, we disable bwc
+            //when HDMI intf is active
+            if((qdutils::MDPVersion::getInstance().is8994() or
+                qdutils::MDPVersion::getInstance().is8092()) and
+                    qdutils::MDPVersion::getInstance().supportsBWC()) {
+                Locker::Autolock _l(ctx->mDrawLock);
+                ctx->mBWCEnabled = true;
+            }
+
             break;
         }
     case EXTERNAL_ONLINE:
@@ -136,6 +145,15 @@
                 break;
             }
 
+            //On 8994, 8992 due to hardware limitations, we disable bwc
+            //when HDMI intf is active
+            if((qdutils::MDPVersion::getInstance().is8994() or
+                qdutils::MDPVersion::getInstance().is8092()) and
+                    qdutils::MDPVersion::getInstance().supportsBWC()) {
+                Locker::Autolock _l(ctx->mDrawLock);
+                ctx->mBWCEnabled = false;
+            }
+
             if (ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
                 ctx->mDrawLock.lock();
                 handle_online(ctx, dpy);
@@ -193,14 +211,13 @@
             ctx->mDrawLock.unlock();
 
             /* External display is HDMI */
-            ALOGE_IF(UEVENT_DEBUG, "%s: Sending EXTERNAL ONLINE"
-                    "hotplug event", __FUNCTION__);
+            ALOGI("%s: Sending EXTERNAL ONLINE event", __FUNCTION__);
             ctx->proc->hotplug(ctx->proc, dpy, EXTERNAL_ONLINE);
             break;
         }
     default:
         {
-            ALOGE("%s: Invalid state to swtich:%d", __FUNCTION__, switch_state);
+            ALOGE("%s: Invalid state to switch:%d", __FUNCTION__, switch_state);
             break;
         }
     }
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index bc3491e..f53e8c4 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -2724,12 +2724,6 @@
 // Handles online events when HDMI is the primary display. In particular,
 // online events for hdmi connected before AND after boot up and HWC init.
 void handle_online(hwc_context_t* ctx, int dpy) {
-    //On 8994 due to hardware limitations, we disable bwc completely when HDMI
-    //intf is active
-    if(qdutils::MDPVersion::getInstance().is8994() and
-            qdutils::MDPVersion::getInstance().supportsBWC()) {
-        ctx->mBWCEnabled = false;
-    }
     // Close the current fd if it was opened earlier on when HWC
     // was initialized.
     if (ctx->dpyAttr[dpy].fd >= 0) {
@@ -2760,12 +2754,6 @@
     resetDisplayInfo(ctx, dpy);
     ctx->dpyAttr[dpy].connected = false;
     ctx->dpyAttr[dpy].isActive = false;
-    //On 8994 due to hardware limitations, we enable bwc only when HDMI
-    //intf is inactive
-    if(qdutils::MDPVersion::getInstance().is8994() and
-            qdutils::MDPVersion::getInstance().supportsBWC()) {
-        ctx->mBWCEnabled = true;
-    }
 }
 
 };//namespace qhwc
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index 06418bf..a294a75 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -223,13 +223,15 @@
         private_handle_t* ohnd, int dpy) {
     bool scalingMode = false;
     int fbWidth = ctx->dpyAttr[dpy].xres;
-    int fbHeight =  ctx->dpyAttr[dpy].yres;
-    if((getWidth(ohnd) != fbWidth) || (getHeight(ohnd) != fbHeight)) {
+    int fbHeight = ctx->dpyAttr[dpy].yres;
+    int alW = 0, alH = 0;
+    getBufferSizeAndDimensions(fbWidth, fbHeight, ohnd->format, alW, alH);
+    if((getWidth(ohnd) != alW) || (getHeight(ohnd) != alH)) {
         scalingMode = true;
     }
     ctx->dpyAttr[dpy].mMDPScalingMode = scalingMode;
 
     ALOGD_IF(HWCVIRTUAL_LOG, "%s fb(%dx%d) outputBuffer(%dx%d) scalingMode=%d",
-            __FUNCTION__, fbWidth, fbHeight,
+            __FUNCTION__, alW, alH,
             getWidth(ohnd), getHeight(ohnd), scalingMode);
 }
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 3932c4c..1290f32 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -374,8 +374,21 @@
     if(errVal) {
         /* No dump for failure due to insufficient resource */
         if(errVal != E2BIG) {
-            mdp_wrapper::dump("Bad ov dump: ",
-                *list.overlay_list[list.processed_overlays]);
+            //ENODEV is returned when the driver cannot satisfy a pipe request.
+            //This could happen if previous round's UNSET hasn't been commited
+            //yet, either because of a missed vsync or because of difference in
+            //vsyncs of primary and external. This is expected during
+            //transition scenarios, but should be considered fatal if seen
+            //continuously.
+            if(errVal == ENODEV) {
+                ALOGW("%s: Pipe unavailable. Likely previous UNSET pending. "
+                    "Fatal if seen continuously.", __FUNCTION__);
+            } else {
+                ALOGE("%s failed, error %d: %s", __FUNCTION__, errVal,
+                        strerror(errVal));
+                mdp_wrapper::dump("Bad ov dump: ",
+                        *list.overlay_list[list.processed_overlays]);
+            }
         }
         return false;
     }