int i;
        u16 x, y, w, h;
        unsigned long flags;
+       bool area_changed;
 
        x = *xi;
        y = *yi;
 
        spin_lock_irqsave(&dss_cache.lock, flags);
 
-       /* We need to show the whole overlay if it is scaled. So look for
-        * those, and make the update area larger if found.
-        * Also mark the overlay cache dirty */
-       for (i = 0; i < num_ovls; ++i) {
-               unsigned x1, y1, x2, y2;
-               unsigned outw, outh;
-
-               oc = &dss_cache.overlay_cache[i];
-
-               if (oc->channel != mgr->id)
-                       continue;
-
-               oc->dirty = true;
-
-               if (!oc->enabled)
-                       continue;
-
-               if (!dispc_is_overlay_scaled(oc))
-                       continue;
-
-               outw = oc->out_width == 0 ? oc->width : oc->out_width;
-               outh = oc->out_height == 0 ? oc->height : oc->out_height;
-
-               /* is the overlay outside the update region? */
-               if (!rectangle_intersects(x, y, w, h,
-                                       oc->pos_x, oc->pos_y,
-                                       outw, outh))
-                       continue;
-
-               /* if the overlay totally inside the update region? */
-               if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
-                                       x, y, w, h))
-                       continue;
-
-               if (x > oc->pos_x)
-                       x1 = oc->pos_x;
-               else
-                       x1 = x;
-
-               if (y > oc->pos_y)
-                       y1 = oc->pos_y;
-               else
-                       y1 = y;
-
-               if ((x + w) < (oc->pos_x + outw))
-                       x2 = oc->pos_x + outw;
-               else
-                       x2 = x + w;
-
-               if ((y + h) < (oc->pos_y + outh))
-                       y2 = oc->pos_y + outh;
-               else
-                       y2 = y + h;
-
-               x = x1;
-               y = y1;
-               w = x2 - x1;
-               h = y2 - y1;
-
-               make_even(&x, &w);
-
-               DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n",
+       /*
+        * Execute the outer loop until the inner loop has completed
+        * once without increasing the update area. This will ensure that
+        * all scaled overlays end up completely within the update area.
+        */
+       do {
+               area_changed = false;
+
+               /* We need to show the whole overlay if it is scaled. So look
+                * for those, and make the update area larger if found.
+                * Also mark the overlay cache dirty */
+               for (i = 0; i < num_ovls; ++i) {
+                       unsigned x1, y1, x2, y2;
+                       unsigned outw, outh;
+
+                       oc = &dss_cache.overlay_cache[i];
+
+                       if (oc->channel != mgr->id)
+                               continue;
+
+                       oc->dirty = true;
+
+                       if (!oc->enabled)
+                               continue;
+
+                       if (!dispc_is_overlay_scaled(oc))
+                               continue;
+
+                       outw = oc->out_width == 0 ?
+                               oc->width : oc->out_width;
+                       outh = oc->out_height == 0 ?
+                               oc->height : oc->out_height;
+
+                       /* is the overlay outside the update region? */
+                       if (!rectangle_intersects(x, y, w, h,
+                                               oc->pos_x, oc->pos_y,
+                                               outw, outh))
+                               continue;
+
+                       /* if the overlay totally inside the update region? */
+                       if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
+                                               x, y, w, h))
+                               continue;
+
+                       if (x > oc->pos_x)
+                               x1 = oc->pos_x;
+                       else
+                               x1 = x;
+
+                       if (y > oc->pos_y)
+                               y1 = oc->pos_y;
+                       else
+                               y1 = y;
+
+                       if ((x + w) < (oc->pos_x + outw))
+                               x2 = oc->pos_x + outw;
+                       else
+                               x2 = x + w;
+
+                       if ((y + h) < (oc->pos_y + outh))
+                               y2 = oc->pos_y + outh;
+                       else
+                               y2 = y + h;
+
+                       x = x1;
+                       y = y1;
+                       w = x2 - x1;
+                       h = y2 - y1;
+
+                       make_even(&x, &w);
+
+                       DSSDBG("changing upd area due to ovl(%d) "
+                              "scaling %d,%d %dx%d\n",
                                i, x, y, w, h);
-       }
+
+                       area_changed = true;
+               }
+       } while (area_changed);
 
        mc = &dss_cache.manager_cache[mgr->id];
        mc->do_manual_update = true;