int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
 
 int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
-                                   u16 *x, u16 *y, u16 *w, u16 *h);
+                                   u16 *x, u16 *y, u16 *w, u16 *h,
+                                   bool enlarge_update_area);
 int omap_dsi_update(struct omap_dss_device *dssdev,
                int channel,
                u16 x, u16 y, u16 w, u16 h,
 
 }
 
 int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
-                                   u16 *x, u16 *y, u16 *w, u16 *h)
+                                   u16 *x, u16 *y, u16 *w, u16 *h,
+                                   bool enlarge_update_area)
 {
        u16 dw, dh;
 
        dsi_perf_mark_setup();
 
        if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
-               dss_setup_partial_planes(dssdev, x, y, w, h);
+               dss_setup_partial_planes(dssdev, x, y, w, h,
+                               enlarge_update_area);
                dispc_set_lcd_size(*w, *h);
        }
 
 
 
        /* manual update region */
        u16 x, y, w, h;
+
+       /* enlarge the update area if the update area contains scaled
+        * overlays */
+       bool enlarge_update_area;
 };
 
 static struct {
        u16 x, y, w, h;
        u32 paddr;
        int r;
+       u16 orig_w, orig_h, orig_outw, orig_outh;
 
        DSSDBGF("%d", plane);
 
        outh = c->out_height == 0 ? c->height : c->out_height;
        paddr = c->paddr;
 
+       orig_w = w;
+       orig_h = h;
+       orig_outw = outw;
+       orig_outh = outh;
+
        if (c->manual_update && mc->do_manual_update) {
                unsigned bpp;
+               unsigned scale_x_m = w, scale_x_d = outw;
+               unsigned scale_y_m = h, scale_y_d = outh;
+
                /* If the overlay is outside the update region, disable it */
                if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
                                        x, y, outw, outh)) {
                        BUG();
                }
 
-               if (dispc_is_overlay_scaled(c)) {
-                       /* If the overlay is scaled, the update area has
-                        * already been enlarged to cover the whole overlay. We
-                        * only need to adjust x/y here */
-                       x = c->pos_x - mc->x;
-                       y = c->pos_y - mc->y;
+               if (mc->x > c->pos_x) {
+                       x = 0;
+                       outw -= (mc->x - c->pos_x);
+                       paddr += (mc->x - c->pos_x) *
+                               scale_x_m / scale_x_d * bpp / 8;
                } else {
-                       if (mc->x > c->pos_x) {
-                               x = 0;
-                               w -= (mc->x - c->pos_x);
-                               paddr += (mc->x - c->pos_x) * bpp / 8;
-                       } else {
-                               x = c->pos_x - mc->x;
-                       }
+                       x = c->pos_x - mc->x;
+               }
 
-                       if (mc->y > c->pos_y) {
-                               y = 0;
-                               h -= (mc->y - c->pos_y);
-                               paddr += (mc->y - c->pos_y) * c->screen_width *
-                                       bpp / 8;
-                       } else {
-                               y = c->pos_y - mc->y;
-                       }
+               if (mc->y > c->pos_y) {
+                       y = 0;
+                       outh -= (mc->y - c->pos_y);
+                       paddr += (mc->y - c->pos_y) *
+                               scale_y_m / scale_y_d *
+                               c->screen_width * bpp / 8;
+               } else {
+                       y = c->pos_y - mc->y;
+               }
 
-                       if (mc->w < (x+w))
-                               w -= (x+w) - (mc->w);
+               if (mc->w < (x + outw))
+                       outw -= (x + outw) - (mc->w);
 
-                       if (mc->h < (y+h))
-                               h -= (y+h) - (mc->h);
+               if (mc->h < (y + outh))
+                       outh -= (y + outh) - (mc->h);
 
-                       outw = w;
-                       outh = h;
-               }
+               w = w * outw / orig_outw;
+               h = h * outh / orig_outh;
        }
 
        r = dispc_setup_plane(plane,
 /* Configure dispc for partial update. Return possibly modified update
  * area */
 void dss_setup_partial_planes(struct omap_dss_device *dssdev,
-               u16 *xi, u16 *yi, u16 *wi, u16 *hi)
+               u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area)
 {
        struct overlay_cache_data *oc;
        struct manager_cache_data *mc;
 
                        oc->dirty = true;
 
+                       if (!enlarge_update_area)
+                               continue;
+
                        if (!oc->enabled)
                                continue;
 
 
        mc = &dss_cache.manager_cache[mgr->id];
        mc->do_manual_update = true;
+       mc->enlarge_update_area = enlarge_update_area;
        mc->x = x;
        mc->y = y;
        mc->w = w;