diff --git a/firmware/target/arm/rk27xx/lcdif-rk27xx.c b/firmware/target/arm/rk27xx/lcdif-rk27xx.c
index d584739..300c6d8 100644
--- a/firmware/target/arm/rk27xx/lcdif-rk27xx.c
+++ b/firmware/target/arm/rk27xx/lcdif-rk27xx.c
@@ -68,6 +68,24 @@ static uint32_t lcd_data_transform(uint32_t data)
     return (r | g | b);
 }
 
+static void lcdctrl_buff_setup(int width, int height)
+{
+    HOR_ACT = width + 3;        /* define horizonatal active region */
+    VERT_ACT = height;          /* define vertical active region */
+
+    width = width  >> 1;
+
+    LINE0_YADDR = 0;
+    LINE1_YADDR = 1 * width;
+    LINE2_YADDR = 2 * width;
+    LINE3_YADDR = 3 * width;
+
+    LINE0_UVADDR = LINE0_YADDR + 1;
+    LINE1_UVADDR = LINE1_YADDR + 1;
+    LINE2_UVADDR = LINE2_YADDR + 1;
+    LINE3_UVADDR = LINE3_YADDR + 1;
+}
+
 static void lcdctrl_init(void)
 {
     int i;
@@ -187,18 +205,20 @@ static void dwdma_start(uint8_t ch, struct llp_t *llp, uint8_t handshake)
    DWDMA_DMA_CHEN = (0x101<<ch);
 }
 
-static void create_llp(void)
+static void create_llp(int x, int y, int width, int height)
 {
     int i;
 
+    width = width>>1;
+
     /* build LLPs */
-    for (i=0; i<LCD_HEIGHT; i++)
-        llp_setup((void *)FBADDR(0,i),
-                  (void*)(LCD_BUFF+((i%4)*4*LCD_WIDTH/2)),
+    for (i=0; i<height; i++)
+        llp_setup((void *)FBADDR(x,y+i),
+                  (void*)(LCD_BUFF+((i%4)*4*width)),
                   &(scr_llp[i]),
-                  LCD_WIDTH/2);
+                  width);
 
-    llp_end(&scr_llp[LCD_HEIGHT-1]);
+    llp_end(&scr_llp[height-1]);
 }
 
 /* Public functions */
@@ -243,19 +263,23 @@ void lcd_init_device(void)
 {
     iomux_lcd(LCD_DATABUS_WIDTH);   /* setup pins for lcd interface */
     dwdma_init();                   /* init dwdma module */
-    create_llp();                   /* build LLPs for screen update dma */
     lcdctrl_init();                 /* basic lcdc module configuration */
 }
 
-void lcd_update()
+void lcd_update_rect(int x, int y, int width, int height)
 {
-    lcd_set_gram_area(0, 0, LCD_WIDTH, LCD_HEIGHT);
+    width = (width + 1) & ~1;
+
+    lcd_set_gram_area(x, y, width, height);
+    create_llp(x, y, width, height);
     lcdctrl_bypass(0);
 
+    /* whole framebuffer for now */
     commit_discard_dcache_range(FBADDR(0,0), 2*LCD_WIDTH*LCD_HEIGHT);
 
     while (!(LCDC_STA & LCDC_MCU_IDLE));
 
+    lcdctrl_buff_setup(width, height);
     dwdma_start(0, scr_llp, 6);
     udelay(10);
 
@@ -265,3 +289,8 @@ void lcd_update()
     /* Wait for DMA transfer to finish */
     while (DWDMA_CTL_L(0) & (1<<27));
 }
+
+void lcd_update()
+{
+    lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
+}
diff --git a/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c b/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c
index 988f710..ca73a18 100644
--- a/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c
+++ b/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c
@@ -178,6 +178,7 @@ void lcd_set_gram_area(int x, int y, int width, int height)
     LCDC_CTRL &= ~RGB24B;
 }
 
+#if 0
 void lcd_update_rect(int x, int y, int width, int height)
 {
     int px = x, py = y;
@@ -195,7 +196,7 @@ void lcd_update_rect(int x, int y, int width, int height)
 /* Blit a YUV bitmap directly to the LCD
  * provided by generic fallback in lcd-16bit-common.c
  */
-#if 0
+
 void lcd_blit_yuv(unsigned char * const src[3],
                   int src_x, int src_y, int stride,
                   int x, int y, int width, int height)