From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 03 Jan 2024 09:43:39 +0000
Subject: [PATCH] update kernel to 5.10.198

---
 kernel/drivers/video/rockchip/rga/rga_mmu_info.c | 2448 ++++++++++++++++++++++++++++++-----------------------------
 1 files changed, 1,239 insertions(+), 1,209 deletions(-)

diff --git a/kernel/drivers/video/rockchip/rga/rga_mmu_info.c b/kernel/drivers/video/rockchip/rga/rga_mmu_info.c
index a8d7e62..9dcffa5 100644
--- a/kernel/drivers/video/rockchip/rga/rga_mmu_info.c
+++ b/kernel/drivers/video/rockchip/rga/rga_mmu_info.c
@@ -1,253 +1,298 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-
-
-#include <linux/version.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/pagemap.h>
-#include <linux/seq_file.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/memory.h>
-#include <linux/dma-mapping.h>
-#include <asm/memory.h>
-#include <asm/atomic.h>
-#include <asm/cacheflush.h>
-#include "rga_mmu_info.h"
-#include <linux/delay.h>
-
-extern rga_service_info rga_service;
-extern struct rga_mmu_buf_t rga_mmu_buf;
+
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/memory.h>
+#include <linux/dma-mapping.h>
+#include <asm/memory.h>
+#include <asm/atomic.h>
+#include <asm/cacheflush.h>
+#include "rga_mmu_info.h"
+#include <linux/delay.h>
+
+extern rga_service_info rga_service;
+extern struct rga_mmu_buf_t rga_mmu_buf;
 
 #if RGA_DEBUGFS
 extern int RGA_CHECK_MODE;
 #endif
-
-#define KERNEL_SPACE_VALID    0xc0000000
-
-static int rga_mmu_buf_get(struct rga_mmu_buf_t *t, uint32_t size)
-{
-    mutex_lock(&rga_service.lock);
-    t->front += size;
-    mutex_unlock(&rga_service.lock);
-
-    return 0;
-}
-
-static int rga_mmu_buf_get_try(struct rga_mmu_buf_t *t, uint32_t size)
-{
-	int ret = 0;
-
-	mutex_lock(&rga_service.lock);
-	if ((t->back - t->front) > t->size) {
-		if(t->front + size > t->back - t->size) {
-			ret = -ENOMEM;
-			goto out;
-		}
-	} else {
-		if ((t->front + size) > t->back) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		if (t->front + size > t->size) {
-			if (size > (t->back - t->size)) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			t->front = 0;
-		}
-	}
-
-out:
-	mutex_unlock(&rga_service.lock);
-	return ret;
-}
-
-static int rga_mem_size_cal(unsigned long Mem, uint32_t MemSize, unsigned long *StartAddr)
-{
-    unsigned long start, end;
-    uint32_t pageCount;
-
-    end = (Mem + (MemSize + PAGE_SIZE - 1)) >> PAGE_SHIFT;
-    start = Mem >> PAGE_SHIFT;
-    pageCount = end - start;
-    *StartAddr = start;
-    return pageCount;
-}
-
-static int rga_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr, unsigned long v_addr,
-                                        int format, uint32_t w, uint32_t h, unsigned long *StartAddr )
-{
-    uint32_t size_yrgb = 0;
-    uint32_t size_uv = 0;
-    uint32_t size_v = 0;
-    uint32_t stride = 0;
-    unsigned long start, end;
-    uint32_t pageCount;
-
-    switch(format)
-    {
-        case RK_FORMAT_RGBA_8888 :
-            stride = (w * 4 + 3) & (~3);
-            size_yrgb = stride*h;
-            start = yrgb_addr >> PAGE_SHIFT;
-            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
-            break;
-        case RK_FORMAT_RGBX_8888 :
-            stride = (w * 4 + 3) & (~3);
-            size_yrgb = stride*h;
-            start = yrgb_addr >> PAGE_SHIFT;
-            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
-            break;
-        case RK_FORMAT_RGB_888 :
-            stride = (w * 3 + 3) & (~3);
-            size_yrgb = stride*h;
-            start = yrgb_addr >> PAGE_SHIFT;
-            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
-            break;
-        case RK_FORMAT_BGRA_8888 :
-            size_yrgb = w*h*4;
-            start = yrgb_addr >> PAGE_SHIFT;
-            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
-            break;
-        case RK_FORMAT_RGB_565 :
-            stride = (w*2 + 3) & (~3);
-            size_yrgb = stride * h;
-            start = yrgb_addr >> PAGE_SHIFT;
-            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
-            break;
-        case RK_FORMAT_RGBA_5551 :
-            stride = (w*2 + 3) & (~3);
-            size_yrgb = stride * h;
-            start = yrgb_addr >> PAGE_SHIFT;
-            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
-            break;
-        case RK_FORMAT_RGBA_4444 :
-            stride = (w*2 + 3) & (~3);
-            size_yrgb = stride * h;
-            start = yrgb_addr >> PAGE_SHIFT;
-            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
-            break;
-        case RK_FORMAT_BGR_888 :
-            stride = (w*3 + 3) & (~3);
-            size_yrgb = stride * h;
-            start = yrgb_addr >> PAGE_SHIFT;
-            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
-            break;
-
-        /* YUV FORMAT */
-        case RK_FORMAT_YCbCr_422_SP :
-            stride = (w + 3) & (~3);
-            size_yrgb = stride * h;
-            size_uv = stride * h;
-            start = MIN(yrgb_addr, uv_addr);
-
-            start >>= PAGE_SHIFT;
-            end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv));
-            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-            pageCount = end - start;
-            break;
-        case RK_FORMAT_YCbCr_422_P :
-            stride = (w + 3) & (~3);
-            size_yrgb = stride * h;
-            size_uv = ((stride >> 1) * h);
-            size_v = ((stride >> 1) * h);
-            start = MIN(MIN(yrgb_addr, uv_addr), v_addr);
-            start = start >> PAGE_SHIFT;
-            end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v));
-            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-            pageCount = end - start;
-            break;
-        case RK_FORMAT_YCbCr_420_SP :
-            stride = (w + 3) & (~3);
-            size_yrgb = stride * h;
-            size_uv = (stride * (h >> 1));
-            start = MIN(yrgb_addr, uv_addr);
-            start >>= PAGE_SHIFT;
-            end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv));
-            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-            pageCount = end - start;
-            break;
-        case RK_FORMAT_YCbCr_420_P :
-            stride = (w + 3) & (~3);
-            size_yrgb = stride * h;
-            size_uv = ((stride >> 1) * (h >> 1));
-            size_v = ((stride >> 1) * (h >> 1));
-            start = MIN(MIN(yrgb_addr, uv_addr), v_addr);
-            start >>= PAGE_SHIFT;
-            end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v));
-            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-            pageCount = end - start;
-            break;
-
-        case RK_FORMAT_YCrCb_422_SP :
-            stride = (w + 3) & (~3);
-            size_yrgb = stride * h;
-            size_uv = stride * h;
-            start = MIN(yrgb_addr, uv_addr);
-            start >>= PAGE_SHIFT;
-            end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv));
-            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-            pageCount = end - start;
-            break;
-        case RK_FORMAT_YCrCb_422_P :
-            stride = (w + 3) & (~3);
-            size_yrgb = stride * h;
-            size_uv = ((stride >> 1) * h);
-            size_v = ((stride >> 1) * h);
-            start = MIN(MIN(yrgb_addr, uv_addr), v_addr);
-            start >>= PAGE_SHIFT;
-            end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v));
-            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-            pageCount = end - start;
-            break;
-
-        case RK_FORMAT_YCrCb_420_SP :
-            stride = (w + 3) & (~3);
-            size_yrgb = stride * h;
-            size_uv = (stride * (h >> 1));
-            start = MIN(yrgb_addr, uv_addr);
-            start >>= PAGE_SHIFT;
-            end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv));
-            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-            pageCount = end - start;
-            break;
-        case RK_FORMAT_YCrCb_420_P :
-            stride = (w + 3) & (~3);
-            size_yrgb = stride * h;
-            size_uv = ((stride >> 1) * (h >> 1));
-            size_v = ((stride >> 1) * (h >> 1));
-            start = MIN(MIN(yrgb_addr, uv_addr), v_addr);
-            start >>= PAGE_SHIFT;
-            end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v));
-            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-            pageCount = end - start;
-            break;
-        #if 0
-        case RK_FORMAT_BPP1 :
-            break;
-        case RK_FORMAT_BPP2 :
-            break;
-        case RK_FORMAT_BPP4 :
-            break;
-        case RK_FORMAT_BPP8 :
-            break;
-        #endif
-        default :
-            pageCount = 0;
-            start = 0;
-            break;
-    }
-
-    *StartAddr = start;
-    return pageCount;
-}
-
+
+#define KERNEL_SPACE_VALID    0xc0000000
+
+void rga_dma_flush_range(void *pstart, void *pend)
+{
+	dma_sync_single_for_device(rga_drvdata->dev, virt_to_phys(pstart), pend - pstart, DMA_TO_DEVICE);
+}
+
+static int rga_mmu_buf_get(struct rga_mmu_buf_t *t, uint32_t size)
+{
+    mutex_lock(&rga_service.lock);
+    t->front += size;
+    mutex_unlock(&rga_service.lock);
+
+    return 0;
+}
+
+static void rga_current_mm_read_lock(struct mm_struct *mm)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
+	mmap_read_lock(mm);
+#else
+	down_read(&mm->mmap_sem);
+#endif
+}
+
+static void rga_current_mm_read_unlock(struct mm_struct *mm)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
+	mmap_read_unlock(mm);
+#else
+	up_read(&mm->mmap_sem);
+#endif
+}
+
+static long rga_get_user_pages(struct page **pages, unsigned long Memory,
+			       uint32_t pageCount, int writeFlag,
+			       struct mm_struct *current_mm)
+{
+	#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 168) && \
+		LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
+		return get_user_pages(current, current_mm, Memory << PAGE_SHIFT,
+				      pageCount, writeFlag ? FOLL_WRITE : 0, pages, NULL);
+	#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
+		return get_user_pages(current, current_mm, Memory << PAGE_SHIFT,
+				      pageCount, writeFlag ? FOLL_WRITE : 0, 0, pages, NULL);
+	#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
+		return get_user_pages_remote(current, current_mm, Memory << PAGE_SHIFT,
+					     pageCount, writeFlag ? FOLL_WRITE : 0, pages,
+					     NULL, NULL);
+	#else
+		return get_user_pages_remote(current_mm, Memory << PAGE_SHIFT,
+					     pageCount, writeFlag ? FOLL_WRITE : 0, pages,
+					     NULL, NULL);
+	#endif
+}
+
+static int rga_mmu_buf_get_try(struct rga_mmu_buf_t *t, uint32_t size)
+{
+	int ret = 0;
+
+	mutex_lock(&rga_service.lock);
+	if ((t->back - t->front) > t->size) {
+		if(t->front + size > t->back - t->size) {
+			ret = -ENOMEM;
+			goto out;
+		}
+	} else {
+		if ((t->front + size) > t->back) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		if (t->front + size > t->size) {
+			if (size > (t->back - t->size)) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			t->front = 0;
+		}
+	}
+
+out:
+	mutex_unlock(&rga_service.lock);
+	return ret;
+}
+
+static int rga_mem_size_cal(unsigned long Mem, uint32_t MemSize, unsigned long *StartAddr)
+{
+    unsigned long start, end;
+    uint32_t pageCount;
+
+    end = (Mem + (MemSize + PAGE_SIZE - 1)) >> PAGE_SHIFT;
+    start = Mem >> PAGE_SHIFT;
+    pageCount = end - start;
+    *StartAddr = start;
+    return pageCount;
+}
+
+static int rga_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr, unsigned long v_addr,
+                                        int format, uint32_t w, uint32_t h, unsigned long *StartAddr )
+{
+    uint32_t size_yrgb = 0;
+    uint32_t size_uv = 0;
+    uint32_t size_v = 0;
+    uint32_t stride = 0;
+    unsigned long start, end;
+    uint32_t pageCount;
+
+    switch(format)
+    {
+        case RK_FORMAT_RGBA_8888 :
+            stride = (w * 4 + 3) & (~3);
+            size_yrgb = stride*h;
+            start = yrgb_addr >> PAGE_SHIFT;
+            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
+            break;
+        case RK_FORMAT_RGBX_8888 :
+            stride = (w * 4 + 3) & (~3);
+            size_yrgb = stride*h;
+            start = yrgb_addr >> PAGE_SHIFT;
+            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
+            break;
+        case RK_FORMAT_RGB_888 :
+            stride = (w * 3 + 3) & (~3);
+            size_yrgb = stride*h;
+            start = yrgb_addr >> PAGE_SHIFT;
+            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
+            break;
+        case RK_FORMAT_BGRA_8888 :
+            size_yrgb = w*h*4;
+            start = yrgb_addr >> PAGE_SHIFT;
+            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
+            break;
+        case RK_FORMAT_RGB_565 :
+            stride = (w*2 + 3) & (~3);
+            size_yrgb = stride * h;
+            start = yrgb_addr >> PAGE_SHIFT;
+            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
+            break;
+        case RK_FORMAT_RGBA_5551 :
+            stride = (w*2 + 3) & (~3);
+            size_yrgb = stride * h;
+            start = yrgb_addr >> PAGE_SHIFT;
+            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
+            break;
+        case RK_FORMAT_RGBA_4444 :
+            stride = (w*2 + 3) & (~3);
+            size_yrgb = stride * h;
+            start = yrgb_addr >> PAGE_SHIFT;
+            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
+            break;
+        case RK_FORMAT_BGR_888 :
+            stride = (w*3 + 3) & (~3);
+            size_yrgb = stride * h;
+            start = yrgb_addr >> PAGE_SHIFT;
+            pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT;
+            break;
+
+        /* YUV FORMAT */
+        case RK_FORMAT_YCbCr_422_SP :
+            stride = (w + 3) & (~3);
+            size_yrgb = stride * h;
+            size_uv = stride * h;
+            start = MIN(yrgb_addr, uv_addr);
+
+            start >>= PAGE_SHIFT;
+            end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv));
+            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+            pageCount = end - start;
+            break;
+        case RK_FORMAT_YCbCr_422_P :
+            stride = (w + 3) & (~3);
+            size_yrgb = stride * h;
+            size_uv = ((stride >> 1) * h);
+            size_v = ((stride >> 1) * h);
+            start = MIN(MIN(yrgb_addr, uv_addr), v_addr);
+            start = start >> PAGE_SHIFT;
+            end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v));
+            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+            pageCount = end - start;
+            break;
+        case RK_FORMAT_YCbCr_420_SP :
+            stride = (w + 3) & (~3);
+            size_yrgb = stride * h;
+            size_uv = (stride * (h >> 1));
+            start = MIN(yrgb_addr, uv_addr);
+            start >>= PAGE_SHIFT;
+            end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv));
+            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+            pageCount = end - start;
+            break;
+        case RK_FORMAT_YCbCr_420_P :
+            stride = (w + 3) & (~3);
+            size_yrgb = stride * h;
+            size_uv = ((stride >> 1) * (h >> 1));
+            size_v = ((stride >> 1) * (h >> 1));
+            start = MIN(MIN(yrgb_addr, uv_addr), v_addr);
+            start >>= PAGE_SHIFT;
+            end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v));
+            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+            pageCount = end - start;
+            break;
+
+        case RK_FORMAT_YCrCb_422_SP :
+            stride = (w + 3) & (~3);
+            size_yrgb = stride * h;
+            size_uv = stride * h;
+            start = MIN(yrgb_addr, uv_addr);
+            start >>= PAGE_SHIFT;
+            end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv));
+            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+            pageCount = end - start;
+            break;
+        case RK_FORMAT_YCrCb_422_P :
+            stride = (w + 3) & (~3);
+            size_yrgb = stride * h;
+            size_uv = ((stride >> 1) * h);
+            size_v = ((stride >> 1) * h);
+            start = MIN(MIN(yrgb_addr, uv_addr), v_addr);
+            start >>= PAGE_SHIFT;
+            end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v));
+            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+            pageCount = end - start;
+            break;
+
+        case RK_FORMAT_YCrCb_420_SP :
+            stride = (w + 3) & (~3);
+            size_yrgb = stride * h;
+            size_uv = (stride * (h >> 1));
+            start = MIN(yrgb_addr, uv_addr);
+            start >>= PAGE_SHIFT;
+            end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv));
+            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+            pageCount = end - start;
+            break;
+        case RK_FORMAT_YCrCb_420_P :
+            stride = (w + 3) & (~3);
+            size_yrgb = stride * h;
+            size_uv = ((stride >> 1) * (h >> 1));
+            size_v = ((stride >> 1) * (h >> 1));
+            start = MIN(MIN(yrgb_addr, uv_addr), v_addr);
+            start >>= PAGE_SHIFT;
+            end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v));
+            end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+            pageCount = end - start;
+            break;
+        #if 0
+        case RK_FORMAT_BPP1 :
+            break;
+        case RK_FORMAT_BPP2 :
+            break;
+        case RK_FORMAT_BPP4 :
+            break;
+        case RK_FORMAT_BPP8 :
+            break;
+        #endif
+        default :
+            pageCount = 0;
+            start = 0;
+            break;
+    }
+
+    *StartAddr = start;
+    return pageCount;
+}
+
 #if RGA_DEBUGFS
 static int rga_usermemory_cheeck(struct page **pages, u32 w, u32 h, u32 format, int flag)
 {
@@ -314,289 +359,304 @@
 }
 #endif
 
-static int rga_MapUserMemory(struct page **pages,
-                                            uint32_t *pageTable,
-                                            unsigned long Memory,
-                                            uint32_t pageCount)
-{
-    int32_t result;
-    uint32_t i;
-    uint32_t status;
-    unsigned long Address;
-
-    status = 0;
-    Address = 0;
-
-    do {
-        down_read(&current->mm->mmap_sem);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
-        result = get_user_pages(current, current->mm,
-            Memory << PAGE_SHIFT, pageCount, 1, 0,
-            pages, NULL);
-#else
-		result = get_user_pages_remote(current, current->mm,
-			Memory << PAGE_SHIFT, pageCount, 1, pages, NULL, NULL);
+static int rga_MapUserMemory(struct page **pages,
+                                            uint32_t *pageTable,
+                                            unsigned long Memory,
+                                            uint32_t pageCount)
+{
+    int32_t result;
+    uint32_t i;
+    uint32_t status;
+    unsigned long Address;
+
+    status = 0;
+    Address = 0;
+
+    do {
+        rga_current_mm_read_lock(current->mm);
+
+	result = rga_get_user_pages(pages, Memory, pageCount, 1, current->mm);
+
+        rga_current_mm_read_unlock(current->mm);
+
+        #if 0
+        if(result <= 0 || result < pageCount)
+        {
+            status = 0;
+
+            for(i=0; i<pageCount; i++)
+            {
+                temp = armv7_va_to_pa((Memory + i) << PAGE_SHIFT);
+                if (temp == 0xffffffff)
+                {
+                    printk("rga find mmu phy ddr error\n ");
+                    status = RGA_OUT_OF_RESOURCES;
+                    break;
+                }
+
+                pageTable[i] = temp;
+            }
+
+            return status;
+        }
+        #else
+        if(result <= 0 || result < pageCount)
+        {
+            struct vm_area_struct *vma;
+
+            if (result>0) {
+		rga_current_mm_read_lock(current->mm);
+
+		for (i = 0; i < result; i++)
+			put_page(pages[i]);
+
+		rga_current_mm_read_unlock(current->mm);
+	    }
+
+            for(i=0; i<pageCount; i++)
+            {
+                vma = find_vma(current->mm, (Memory + i) << PAGE_SHIFT);
+
+                if (vma)//&& (vma->vm_flags & VM_PFNMAP) )
+                {
+                    do
+                    {
+                        pte_t       * pte;
+                        spinlock_t  * ptl;
+                        unsigned long pfn;
+                        pgd_t * pgd;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
+						p4d_t * p4d;
 #endif
-        up_read(&current->mm->mmap_sem);
-
-        #if 0
-        if(result <= 0 || result < pageCount)
-        {
-            status = 0;
-
-            for(i=0; i<pageCount; i++)
-            {
-                temp = armv7_va_to_pa((Memory + i) << PAGE_SHIFT);
-                if (temp == 0xffffffff)
-                {
-                    printk("rga find mmu phy ddr error\n ");
-                    status = RGA_OUT_OF_RESOURCES;
-                    break;
-                }
-
-                pageTable[i] = temp;
-            }
-
-            return status;
-        }
-        #else
-        if(result <= 0 || result < pageCount)
-        {
-            struct vm_area_struct *vma;
-
-            if (result>0) {
-			    down_read(&current->mm->mmap_sem);
-			    for (i = 0; i < result; i++)
-				    put_page(pages[i]);
-			    up_read(&current->mm->mmap_sem);
-		    }
-
-            for(i=0; i<pageCount; i++)
-            {
-                vma = find_vma(current->mm, (Memory + i) << PAGE_SHIFT);
-
-                if (vma)//&& (vma->vm_flags & VM_PFNMAP) )
-                {
-                    do
-                    {
-                        pte_t       * pte;
-                        spinlock_t  * ptl;
-                        unsigned long pfn;
-                        pgd_t * pgd;
-                        pud_t * pud;
-
-                        pgd = pgd_offset(current->mm, (Memory + i) << PAGE_SHIFT);
-
-                        if(pgd_val(*pgd) == 0)
-                        {
-                            //printk("rga pgd value is zero \n");
-                            break;
-                        }
-
-                        pud = pud_offset(pgd, (Memory + i) << PAGE_SHIFT);
-                        if (pud)
-                        {
-                            pmd_t * pmd = pmd_offset(pud, (Memory + i) << PAGE_SHIFT);
-                            if (pmd)
-                            {
-                                pte = pte_offset_map_lock(current->mm, pmd, (Memory + i) << PAGE_SHIFT, &ptl);
-                                if (!pte)
-                                {
-                                    pte_unmap_unlock(pte, ptl);
-                                    break;
-                                }
-                            }
-                            else
-                            {
-                                break;
-                            }
-                        }
-                        else
-                        {
-                            break;
-                        }
-
-                        pfn = pte_pfn(*pte);
-                        Address = ((pfn << PAGE_SHIFT) | (((unsigned long)((Memory + i) << PAGE_SHIFT)) & ~PAGE_MASK));
-                        pte_unmap_unlock(pte, ptl);
-                    }
-                    while (0);
-
-                    pageTable[i] = Address;
-                }
-                else
-                {
-                    status = RGA_OUT_OF_RESOURCES;
-                    break;
-                }
-            }
-
-            return status;
-        }
-        #endif
-
-        /* Fill the page table. */
-        for(i=0; i<pageCount; i++)
-        {
-            /* Get the physical address from page struct. */
-            pageTable[i] = page_to_phys(pages[i]);
-        }
-
-        down_read(&current->mm->mmap_sem);
-		for (i = 0; i < result; i++)
-			put_page(pages[i]);
-		up_read(&current->mm->mmap_sem);
-
-        return 0;
-    }
-    while(0);
-
-    return status;
-}
-
-static int rga_MapION(struct sg_table *sg,
-                               uint32_t *Memory,
-                               int32_t  pageCount,
-                               uint32_t offset)
-{
-    uint32_t i;
-    uint32_t status;
-    unsigned long Address;
-    uint32_t mapped_size = 0;
-    uint32_t len = 0;
-    struct scatterlist *sgl = sg->sgl;
-    uint32_t sg_num = 0;
-
-    status = 0;
-    Address = 0;
-    offset = offset >> PAGE_SHIFT;
-    if (offset != 0) {
-        do {
-            len += (sg_dma_len(sgl) >> PAGE_SHIFT);
-	        if (len == offset) {
-	    	    sg_num += 1;
-		    break;
-    	    }
-    	    else {
-                if (len > offset)
-                     break;
-    	    }
-                sg_num += 1;
-        }
-        while((sgl = sg_next(sgl)) && (mapped_size < pageCount) && (sg_num < sg->nents));
-
-        sgl = sg->sgl;
-    	len = 0;
-        do {
-            len += (sg_dma_len(sgl) >> PAGE_SHIFT);
-            sgl = sg_next(sgl);
-        }
-        while(--sg_num);
-
-        offset -= len;
-
-        len = sg_dma_len(sgl) >> PAGE_SHIFT;
-        Address = sg_phys(sgl);
-    	Address += offset;
-
-        for(i=offset; i<len; i++) {
-             Memory[i - offset] = Address + (i << PAGE_SHIFT);
-        }
-        mapped_size += (len - offset);
-        sg_num = 1;
-        sgl = sg_next(sgl);
-        do {
-            len = sg_dma_len(sgl) >> PAGE_SHIFT;
-            Address = sg_phys(sgl);
-
-            for(i=0; i<len; i++) {
-                Memory[mapped_size + i] = Address + (i << PAGE_SHIFT);
-            }
-
-            mapped_size += len;
-            sg_num += 1;
-        }
-        while((sgl = sg_next(sgl)) && (mapped_size < pageCount) && (sg_num < sg->nents));
-    }
-    else {
-        do {
-            len = sg_dma_len(sgl) >> PAGE_SHIFT;
-            Address = sg_phys(sgl);
-            for(i=0; i<len; i++) {
-                Memory[mapped_size + i] = Address + (i << PAGE_SHIFT);
-            }
-            mapped_size += len;
-            sg_num += 1;
-        }
-        while((sgl = sg_next(sgl)) && (mapped_size < pageCount) && (sg_num < sg->nents));
-    }
-    return 0;
-}
-
-
-static int rga_mmu_info_BitBlt_mode(struct rga_reg *reg, struct rga_req *req)
-{
-    int SrcMemSize, DstMemSize;
-    unsigned long SrcStart, DstStart;
-    uint32_t i;
-    uint32_t AllSize;
-    uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys;
-    int ret;
-    int status;
-    uint32_t uv_size, v_size;
-
-    struct page **pages = NULL;
-
-    MMU_Base = NULL;
-
-    SrcMemSize = 0;
-    DstMemSize = 0;
-
-    do {
-        /* cal src buf mmu info */
-        SrcMemSize = rga_buf_size_cal(req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr,
-                                        req->src.format, req->src.vir_w, req->src.act_h + req->src.y_offset,
-                                        &SrcStart);
-        if(SrcMemSize == 0) {
-            return -EINVAL;
-        }
-
-        /* cal dst buf mmu info */
-
-        DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr,
-                                        req->dst.format, req->dst.vir_w, req->dst.vir_h,
-                                        &DstStart);
-        if(DstMemSize == 0)
-            return -EINVAL;
-
-        /* Cal out the needed mem size */
-        SrcMemSize = (SrcMemSize + 15) & (~15);
-        DstMemSize = (DstMemSize + 15) & (~15);
-        AllSize = SrcMemSize + DstMemSize;
-
-        if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) {
-            pr_err("RGA Get MMU mem failed\n");
-            status = RGA_MALLOC_ERROR;
-            break;
-        }
-
-        mutex_lock(&rga_service.lock);
-        MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
-        MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
-        mutex_unlock(&rga_service.lock);
-
-        pages = rga_mmu_buf.pages;
-
-        if((req->mmu_info.mmu_flag >> 8) & 1) {
-            if (req->sg_src) {
-                ret = rga_MapION(req->sg_src, &MMU_Base[0], SrcMemSize, req->line_draw_info.flag);
-            }
-            else {
-                ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], SrcStart, SrcMemSize);
-                if (ret < 0) {
-                    pr_err("rga map src memory failed\n");
-                    status = ret;
-                    break;
+                        pud_t * pud;
+
+                        pgd = pgd_offset(current->mm, (Memory + i) << PAGE_SHIFT);
+
+                        if(pgd_val(*pgd) == 0)
+                        {
+                            //printk("rga pgd value is zero \n");
+                            break;
+                        }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
+						/* In the four-level page table, it will do nothing and return pgd. */
+						p4d = p4d_offset(pgd, (Memory + i) << PAGE_SHIFT);
+						if (p4d_none(*p4d) || unlikely(p4d_bad(*p4d))) {
+							pr_err("RGA2 failed to get p4d, result = %d, pageCount = %d\n",
+								   result, pageCount);
+							status = RGA_OUT_OF_RESOURCES;
+							break;
+						}
+
+						pud = pud_offset(p4d, (Memory + i) << PAGE_SHIFT);
+#else
+						pud = pud_offset(pgd, (Memory + i) << PAGE_SHIFT);
+#endif
+                        if (pud)
+                        {
+                            pmd_t * pmd = pmd_offset(pud, (Memory + i) << PAGE_SHIFT);
+                            if (pmd)
+                            {
+                                pte = pte_offset_map_lock(current->mm, pmd, (Memory + i) << PAGE_SHIFT, &ptl);
+                                if (!pte)
+                                {
+                                    pte_unmap_unlock(pte, ptl);
+                                    break;
+                                }
+                            }
+                            else
+                            {
+                                break;
+                            }
+                        }
+                        else
+                        {
+                            break;
+                        }
+
+                        pfn = pte_pfn(*pte);
+                        Address = ((pfn << PAGE_SHIFT) | (((unsigned long)((Memory + i) << PAGE_SHIFT)) & ~PAGE_MASK));
+                        pte_unmap_unlock(pte, ptl);
+                    }
+                    while (0);
+
+                    pageTable[i] = Address;
+                }
+                else
+                {
+                    status = RGA_OUT_OF_RESOURCES;
+                    break;
+                }
+            }
+
+            return status;
+        }
+        #endif
+
+        /* Fill the page table. */
+        for(i=0; i<pageCount; i++)
+        {
+            /* Get the physical address from page struct. */
+            pageTable[i] = page_to_phys(pages[i]);
+        }
+
+	rga_current_mm_read_lock(current->mm);
+
+	for (i = 0; i < result; i++)
+		put_page(pages[i]);
+
+	rga_current_mm_read_unlock(current->mm);
+
+        return 0;
+    }
+    while(0);
+
+    return status;
+}
+
+static int rga_MapION(struct sg_table *sg,
+                               uint32_t *Memory,
+                               int32_t  pageCount,
+                               uint32_t offset)
+{
+    uint32_t i;
+    uint32_t status;
+    unsigned long Address;
+    uint32_t mapped_size = 0;
+    uint32_t len = 0;
+    struct scatterlist *sgl = sg->sgl;
+    uint32_t sg_num = 0;
+
+    status = 0;
+    Address = 0;
+    offset = offset >> PAGE_SHIFT;
+    if (offset != 0) {
+        do {
+            len += (sg_dma_len(sgl) >> PAGE_SHIFT);
+	        if (len == offset) {
+	    	    sg_num += 1;
+		    break;
+    	    }
+    	    else {
+                if (len > offset)
+                     break;
+    	    }
+                sg_num += 1;
+        }
+        while((sgl = sg_next(sgl)) && (mapped_size < pageCount) && (sg_num < sg->nents));
+
+        sgl = sg->sgl;
+    	len = 0;
+        do {
+            len += (sg_dma_len(sgl) >> PAGE_SHIFT);
+            sgl = sg_next(sgl);
+        }
+        while(--sg_num);
+
+        offset -= len;
+
+        len = sg_dma_len(sgl) >> PAGE_SHIFT;
+        Address = sg_phys(sgl);
+    	Address += offset;
+
+        for(i=offset; i<len; i++) {
+             Memory[i - offset] = Address + (i << PAGE_SHIFT);
+        }
+        mapped_size += (len - offset);
+        sg_num = 1;
+        sgl = sg_next(sgl);
+        do {
+            len = sg_dma_len(sgl) >> PAGE_SHIFT;
+            Address = sg_phys(sgl);
+
+            for(i=0; i<len; i++) {
+                Memory[mapped_size + i] = Address + (i << PAGE_SHIFT);
+            }
+
+            mapped_size += len;
+            sg_num += 1;
+        }
+        while((sgl = sg_next(sgl)) && (mapped_size < pageCount) && (sg_num < sg->nents));
+    }
+    else {
+        do {
+            len = sg_dma_len(sgl) >> PAGE_SHIFT;
+            Address = sg_phys(sgl);
+            for(i=0; i<len; i++) {
+                Memory[mapped_size + i] = Address + (i << PAGE_SHIFT);
+            }
+            mapped_size += len;
+            sg_num += 1;
+        }
+        while((sgl = sg_next(sgl)) && (mapped_size < pageCount) && (sg_num < sg->nents));
+    }
+    return 0;
+}
+
+
+static int rga_mmu_info_BitBlt_mode(struct rga_reg *reg, struct rga_req *req)
+{
+    int SrcMemSize, DstMemSize;
+    unsigned long SrcStart, DstStart;
+    uint32_t i;
+    uint32_t AllSize;
+    uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys;
+    int ret;
+    int status;
+    uint32_t uv_size, v_size;
+
+    struct page **pages = NULL;
+
+    MMU_Base = NULL;
+
+    SrcMemSize = 0;
+    DstMemSize = 0;
+
+    do {
+        /* cal src buf mmu info */
+        SrcMemSize = rga_buf_size_cal(req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr,
+                                        req->src.format, req->src.vir_w, req->src.act_h + req->src.y_offset,
+                                        &SrcStart);
+        if(SrcMemSize == 0) {
+            return -EINVAL;
+        }
+
+        /* cal dst buf mmu info */
+
+        DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr,
+                                        req->dst.format, req->dst.vir_w, req->dst.vir_h,
+                                        &DstStart);
+        if(DstMemSize == 0)
+            return -EINVAL;
+
+        /* Cal out the needed mem size */
+        SrcMemSize = (SrcMemSize + 15) & (~15);
+        DstMemSize = (DstMemSize + 15) & (~15);
+        AllSize = SrcMemSize + DstMemSize;
+
+        if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) {
+            pr_err("RGA Get MMU mem failed\n");
+            status = RGA_MALLOC_ERROR;
+            break;
+        }
+
+        mutex_lock(&rga_service.lock);
+        MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
+        MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
+        mutex_unlock(&rga_service.lock);
+
+        pages = rga_mmu_buf.pages;
+
+        if((req->mmu_info.mmu_flag >> 8) & 1) {
+            if (req->sg_src) {
+                ret = rga_MapION(req->sg_src, &MMU_Base[0], SrcMemSize, req->line_draw_info.flag);
+            }
+            else {
+                ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], SrcStart, SrcMemSize);
+                if (ret < 0) {
+                    pr_err("rga map src memory failed\n");
+                    status = ret;
+                    break;
                 }
 
 #if RGA_DEBUGFS
@@ -604,692 +664,662 @@
 		rga_usermemory_cheeck(&pages[0], req->src.vir_w,
 				      req->src.vir_h, req->src.format, 1);
 #endif
-            }
-        }
-        else {
-            MMU_p = MMU_Base;
-
-            if(req->src.yrgb_addr == (unsigned long)rga_service.pre_scale_buf) {
-                for(i=0; i<SrcMemSize; i++)
-                    MMU_p[i] = rga_service.pre_scale_buf[i];
-            }
-            else {
-                for(i=0; i<SrcMemSize; i++)
-                    MMU_p[i] = (uint32_t)((SrcStart + i) << PAGE_SHIFT);
-            }
-        }
-
-        if ((req->mmu_info.mmu_flag >> 10) & 1) {
-            if (req->sg_dst) {
-                ret = rga_MapION(req->sg_dst, &MMU_Base[SrcMemSize], DstMemSize, req->line_draw_info.line_width);
-            }
-            else {
-                ret = rga_MapUserMemory(&pages[SrcMemSize], &MMU_Base[SrcMemSize], DstStart, DstMemSize);
-                if (ret < 0) {
-                    pr_err("rga map dst memory failed\n");
-                    status = ret;
-                    break;
-                }
+            }
+        }
+        else {
+            MMU_p = MMU_Base;
+
+            if(req->src.yrgb_addr == (unsigned long)rga_service.pre_scale_buf) {
+                for(i=0; i<SrcMemSize; i++)
+                    MMU_p[i] = rga_service.pre_scale_buf[i];
+            }
+            else {
+                for(i=0; i<SrcMemSize; i++)
+                    MMU_p[i] = (uint32_t)((SrcStart + i) << PAGE_SHIFT);
+            }
+        }
+
+        if ((req->mmu_info.mmu_flag >> 10) & 1) {
+            if (req->sg_dst) {
+                ret = rga_MapION(req->sg_dst, &MMU_Base[SrcMemSize], DstMemSize, req->line_draw_info.line_width);
+            }
+            else {
+                ret = rga_MapUserMemory(&pages[SrcMemSize], &MMU_Base[SrcMemSize], DstStart, DstMemSize);
+                if (ret < 0) {
+                    pr_err("rga map dst memory failed\n");
+                    status = ret;
+                    break;
+                }
 
 #if RGA_DEBUGFS
 	if (RGA_CHECK_MODE)
 		rga_usermemory_cheeck(&pages[0], req->src.vir_w,
 				      req->src.vir_h, req->src.format, 2);
 #endif
-            }
-        }
-        else {
-            MMU_p = MMU_Base + SrcMemSize;
-            for(i=0; i<DstMemSize; i++)
-                MMU_p[i] = (uint32_t)((DstStart + i) << PAGE_SHIFT);
-        }
-
-        MMU_Base[AllSize] = MMU_Base[AllSize-1];
-
-        /* zsq
-         * change the buf address in req struct
-         */
-
-        req->mmu_info.base_addr = (unsigned long)MMU_Base_phys >> 2;
-
-        uv_size = (req->src.uv_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT;
-        v_size = (req->src.v_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT;
-
-        req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK));
-        req->src.uv_addr = (req->src.uv_addr & (~PAGE_MASK)) | (uv_size << PAGE_SHIFT);
-        req->src.v_addr = (req->src.v_addr & (~PAGE_MASK)) | (v_size << PAGE_SHIFT);
-
-        uv_size = (req->dst.uv_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT;
-
-        req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | (SrcMemSize << PAGE_SHIFT);
-        req->dst.uv_addr = (req->dst.uv_addr & (~PAGE_MASK)) | ((SrcMemSize + uv_size) << PAGE_SHIFT);
-
-        /* flush data to DDR */
-        #ifdef CONFIG_ARM
-        dmac_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
-        outer_flush_range(virt_to_phys(MMU_Base), virt_to_phys(MMU_Base + AllSize + 1));
-        #elif defined(CONFIG_ARM64)
-        __dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
-        #endif
-
-        rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16);
-        reg->MMU_len = AllSize + 16;
-
-        status = 0;
-
-        return status;
-    }
-    while(0);
-
-    return status;
-}
-
-static int rga_mmu_info_color_palette_mode(struct rga_reg *reg, struct rga_req *req)
-{
-    int SrcMemSize, DstMemSize, CMDMemSize;
-    unsigned long SrcStart, DstStart, CMDStart;
-    struct page **pages = NULL;
-    uint32_t i;
-    uint32_t AllSize;
-    uint32_t *MMU_Base = NULL, *MMU_Base_phys = NULL;
-    uint32_t *MMU_p;
-    int ret, status = 0;
-    uint32_t stride;
-
-    uint8_t shift;
-    uint16_t sw, byte_num;
-
-    shift = 3 - (req->palette_mode & 3);
-    sw = req->src.vir_w;
-    byte_num = sw >> shift;
-    stride = (byte_num + 3) & (~3);
-
-    do {
-        SrcMemSize = rga_mem_size_cal(req->src.yrgb_addr, stride, &SrcStart);
-        if(SrcMemSize == 0) {
-            return -EINVAL;
-        }
-
-        DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr,
-                                        req->dst.format, req->dst.vir_w, req->dst.vir_h,
-                                        &DstStart);
-        if(DstMemSize == 0) {
-            return -EINVAL;
-        }
-
-        CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart);
-        if(CMDMemSize == 0) {
-            return -EINVAL;
-        }
-
-        SrcMemSize = (SrcMemSize + 15) & (~15);
-        DstMemSize = (DstMemSize + 15) & (~15);
-        CMDMemSize = (CMDMemSize + 15) & (~15);
-
-        AllSize = SrcMemSize + DstMemSize + CMDMemSize;
-
-        if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) {
-            pr_err("RGA Get MMU mem failed\n");
-            status = RGA_MALLOC_ERROR;
-            break;
-        }
-
-        mutex_lock(&rga_service.lock);
-        MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
-        MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
-        mutex_unlock(&rga_service.lock);
-
-        pages = rga_mmu_buf.pages;
-
-        /* map CMD addr */
-        for(i=0; i<CMDMemSize; i++) {
-            MMU_Base[i] = (uint32_t)virt_to_phys((uint32_t *)((CMDStart + i)<<PAGE_SHIFT));
-        }
-
-        /* map src addr */
-        if (req->src.yrgb_addr < KERNEL_SPACE_VALID) {
-            ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize);
-            if (ret < 0) {
-                pr_err("rga map src memory failed\n");
-                status = ret;
-                break;
-            }
-        }
-        else {
-            MMU_p = MMU_Base + CMDMemSize;
-
-            for(i=0; i<SrcMemSize; i++)
-            {
-                MMU_p[i] = (uint32_t)virt_to_phys((uint32_t *)((SrcStart + i) << PAGE_SHIFT));
-            }
-        }
-
-        /* map dst addr */
-        if (req->src.yrgb_addr < KERNEL_SPACE_VALID) {
-            ret = rga_MapUserMemory(&pages[CMDMemSize + SrcMemSize], &MMU_Base[CMDMemSize + SrcMemSize], DstStart, DstMemSize);
-            if (ret < 0) {
-                pr_err("rga map dst memory failed\n");
-                status = ret;
-                break;
-            }
-        }
-        else {
-            MMU_p = MMU_Base + CMDMemSize + SrcMemSize;
-            for(i=0; i<DstMemSize; i++)
-                MMU_p[i] = (uint32_t)virt_to_phys((uint32_t *)((DstStart + i) << PAGE_SHIFT));
-        }
-
-
-        /* zsq
-         * change the buf address in req struct
-         * for the reason of lie to MMU
-         */
-        req->mmu_info.base_addr = (virt_to_phys(MMU_Base)>>2);
-        req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT);
-        req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | ((CMDMemSize + SrcMemSize) << PAGE_SHIFT);
-
-        /*record the malloc buf for the cmd end to release*/
-        reg->MMU_base = MMU_Base;
-
-        /* flush data to DDR */
-        #ifdef CONFIG_ARM
-        dmac_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
-        outer_flush_range(virt_to_phys(MMU_Base),virt_to_phys(MMU_Base + AllSize + 1));
-        #elif defined(CONFIG_ARM64)
-        __dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
-        #endif
-
-        rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16);
-        reg->MMU_len = AllSize + 16;
-
+            }
+        }
+        else {
+            MMU_p = MMU_Base + SrcMemSize;
+            for(i=0; i<DstMemSize; i++)
+                MMU_p[i] = (uint32_t)((DstStart + i) << PAGE_SHIFT);
+        }
+
+        MMU_Base[AllSize] = MMU_Base[AllSize-1];
+
+        /* zsq
+         * change the buf address in req struct
+         */
+
+        req->mmu_info.base_addr = (unsigned long)MMU_Base_phys >> 2;
+
+        uv_size = (req->src.uv_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT;
+        v_size = (req->src.v_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT;
+
+        req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK));
+        req->src.uv_addr = (req->src.uv_addr & (~PAGE_MASK)) | (uv_size << PAGE_SHIFT);
+        req->src.v_addr = (req->src.v_addr & (~PAGE_MASK)) | (v_size << PAGE_SHIFT);
+
+        uv_size = (req->dst.uv_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT;
+
+        req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | (SrcMemSize << PAGE_SHIFT);
+        req->dst.uv_addr = (req->dst.uv_addr & (~PAGE_MASK)) | ((SrcMemSize + uv_size) << PAGE_SHIFT);
+
+        /* flush data to DDR */
+        rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
+
+        rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16);
+        reg->MMU_len = AllSize + 16;
+
+        status = 0;
+
         return status;
-
-    }
-    while(0);
-
-    return 0;
-}
-
-static int rga_mmu_info_color_fill_mode(struct rga_reg *reg, struct rga_req *req)
-{
-    int DstMemSize;
-    unsigned long DstStart;
-    struct page **pages = NULL;
-    uint32_t i;
-    uint32_t AllSize;
-    uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys;
-    int ret;
-    int status;
-
-    MMU_Base = NULL;
-
-    do {
-        DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr,
-                                        req->dst.format, req->dst.vir_w, req->dst.vir_h,
-                                        &DstStart);
-        if(DstMemSize == 0) {
-            return -EINVAL;
-        }
-
-        AllSize = (DstMemSize + 15) & (~15);
-
-        pages = rga_mmu_buf.pages;
-
-        if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) {
-            pr_err("RGA Get MMU mem failed\n");
-            status = RGA_MALLOC_ERROR;
-            break;
-        }
-
-        mutex_lock(&rga_service.lock);
-        MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
-        MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
-        mutex_unlock(&rga_service.lock);
-
-        if (req->dst.yrgb_addr < KERNEL_SPACE_VALID) {
-            if (req->sg_dst) {
-                ret = rga_MapION(req->sg_dst, &MMU_Base[0], DstMemSize, req->line_draw_info.line_width);
-            }
-            else {
-                ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], DstStart, DstMemSize);
-                if (ret < 0) {
-                    pr_err("rga map dst memory failed\n");
-                    status = ret;
-                    break;
-                }
-            }
-        }
-        else {
-            MMU_p = MMU_Base;
-            for(i=0; i<DstMemSize; i++)
-                MMU_p[i] = (uint32_t)((DstStart + i) << PAGE_SHIFT);
-        }
-
-        MMU_Base[AllSize] = MMU_Base[AllSize - 1];
-
-        /* zsq
-         * change the buf address in req struct
-         */
-
-        req->mmu_info.base_addr = ((unsigned long)(MMU_Base_phys)>>2);
-        req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK));
-
-        /*record the malloc buf for the cmd end to release*/
-        reg->MMU_base = MMU_Base;
-
-        /* flush data to DDR */
-        #ifdef CONFIG_ARM
-        dmac_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
-        outer_flush_range(virt_to_phys(MMU_Base),virt_to_phys(MMU_Base + AllSize + 1));
-        #elif defined(CONFIG_ARM64)
-        __dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
-        #endif
-
-        rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16);
-        reg->MMU_len = AllSize + 16;
-
-        return 0;
-    }
-    while(0);
-
-    return status;
-}
-
-
-static int rga_mmu_info_line_point_drawing_mode(struct rga_reg *reg, struct rga_req *req)
-{
-    return 0;
-}
-
-static int rga_mmu_info_blur_sharp_filter_mode(struct rga_reg *reg, struct rga_req *req)
-{
-    return 0;
-}
-
-
-
-static int rga_mmu_info_pre_scale_mode(struct rga_reg *reg, struct rga_req *req)
-{
-    int SrcMemSize, DstMemSize;
-    unsigned long SrcStart, DstStart;
-    struct page **pages = NULL;
-    uint32_t i;
-    uint32_t AllSize;
-    uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys;
-    int ret;
-    int status;
-    uint32_t uv_size, v_size;
-
-    MMU_Base = NULL;
-
-    do {
-        /* cal src buf mmu info */
-        SrcMemSize = rga_buf_size_cal(req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr,
-                                        req->src.format, req->src.vir_w, req->src.vir_h,
-                                        &SrcStart);
-        if(SrcMemSize == 0) {
-            return -EINVAL;
-        }
-
-        /* cal dst buf mmu info */
-        DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr,
-                                        req->dst.format, req->dst.vir_w, req->dst.vir_h,
-                                        &DstStart);
-        if(DstMemSize == 0) {
-            return -EINVAL;
-        }
-
-	    SrcMemSize = (SrcMemSize + 15) & (~15);
-	    DstMemSize = (DstMemSize + 15) & (~15);
-
-        AllSize = SrcMemSize + DstMemSize;
-
-        pages = rga_mmu_buf.pages;
-
-        if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) {
-            pr_err("RGA Get MMU mem failed\n");
-            status = RGA_MALLOC_ERROR;
-            break;
-        }
-
-        mutex_lock(&rga_service.lock);
-        MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
-        MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
-        mutex_unlock(&rga_service.lock);
-
-        /* map src pages */
-        if ((req->mmu_info.mmu_flag >> 8) & 1) {
-            if (req->sg_src) {
-                ret = rga_MapION(req->sg_src, &MMU_Base[0], SrcMemSize,req->line_draw_info.flag);
-            }
-            else {
-                ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], SrcStart, SrcMemSize);
-                if (ret < 0) {
-                    pr_err("rga map src memory failed\n");
-                    status = ret;
-                    break;
-                }
-            }
-        }
-        else {
-            MMU_p = MMU_Base;
-
-            for(i=0; i<SrcMemSize; i++)
-                MMU_p[i] = (uint32_t)((SrcStart + i) << PAGE_SHIFT);
-        }
-
-        if((req->mmu_info.mmu_flag >> 10) & 1) {
-            if (req->sg_dst) {
-                ret = rga_MapION(req->sg_dst, &MMU_Base[SrcMemSize], DstMemSize, req->line_draw_info.line_width);
-            }
-            else {
-                ret = rga_MapUserMemory(&pages[SrcMemSize], &MMU_Base[SrcMemSize], DstStart, DstMemSize);
-                if (ret < 0) {
-                    pr_err("rga map dst memory failed\n");
-                    status = ret;
-                    break;
-                }
-            }
-        }
-        else
-        {
-            /* kernel space */
-            MMU_p = MMU_Base + SrcMemSize;
-
-            if(req->dst.yrgb_addr == (unsigned long)rga_service.pre_scale_buf) {
-                for(i=0; i<DstMemSize; i++)
-                    MMU_p[i] = rga_service.pre_scale_buf[i];
-            }
-            else {
-                for(i=0; i<DstMemSize; i++)
-                    MMU_p[i] = (uint32_t)((DstStart + i) << PAGE_SHIFT);
-            }
-        }
-
-        MMU_Base[AllSize] = MMU_Base[AllSize];
-
-        /* zsq
-         * change the buf address in req struct
-         * for the reason of lie to MMU
-         */
-
-        req->mmu_info.base_addr = ((unsigned long)(MMU_Base_phys)>>2);
-
-        uv_size = (req->src.uv_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT;
-        v_size = (req->src.v_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT;
-
-        req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK));
-        req->src.uv_addr = (req->src.uv_addr & (~PAGE_MASK)) | (uv_size << PAGE_SHIFT);
-        req->src.v_addr = (req->src.v_addr & (~PAGE_MASK)) | (v_size << PAGE_SHIFT);
-
-        uv_size = (req->dst.uv_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT;
-        v_size = (req->dst.v_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT;
-
-        req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | ((SrcMemSize) << PAGE_SHIFT);
-        req->dst.uv_addr = (req->dst.uv_addr & (~PAGE_MASK)) | ((SrcMemSize + uv_size) << PAGE_SHIFT);
-        req->dst.v_addr = (req->dst.v_addr & (~PAGE_MASK)) | ((SrcMemSize + v_size) << PAGE_SHIFT);
-
-        /*record the malloc buf for the cmd end to release*/
-        reg->MMU_base = MMU_Base;
-
-        /* flush data to DDR */
-        #ifdef CONFIG_ARM
-        dmac_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
-        outer_flush_range(virt_to_phys(MMU_Base),virt_to_phys(MMU_Base + AllSize + 1));
-        #elif defined(CONFIG_ARM64)
-        __dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
-        #endif
-
-	    rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16);
-        reg->MMU_len = AllSize + 16;
-
-        return 0;
-    }
-    while(0);
-
-    return status;
-}
-
-
-static int rga_mmu_info_update_palette_table_mode(struct rga_reg *reg, struct rga_req *req)
-{
-    int SrcMemSize, CMDMemSize;
-    unsigned long SrcStart, CMDStart;
-    struct page **pages = NULL;
-    uint32_t i;
-    uint32_t AllSize;
-    uint32_t *MMU_Base, *MMU_p;
-    int ret, status;
-
-    MMU_Base = NULL;
-
-    do {
-        /* cal src buf mmu info */
-        SrcMemSize = rga_mem_size_cal(req->src.yrgb_addr, req->src.vir_w * req->src.vir_h, &SrcStart);
-        if(SrcMemSize == 0) {
-            return -EINVAL;
-        }
-
-        /* cal cmd buf mmu info */
-        CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart);
-        if(CMDMemSize == 0) {
-            return -EINVAL;
-        }
-
-        AllSize = SrcMemSize + CMDMemSize;
-
-        pages = kzalloc(AllSize * sizeof(struct page *), GFP_KERNEL);
-        if(pages == NULL) {
-            pr_err("RGA MMU malloc pages mem failed\n");
-            status = RGA_MALLOC_ERROR;
-            break;
-        }
-
-        MMU_Base = kzalloc((AllSize + 1)* sizeof(uint32_t), GFP_KERNEL);
-        if(pages == NULL) {
-            pr_err("RGA MMU malloc MMU_Base point failed\n");
-            status = RGA_MALLOC_ERROR;
-            break;
-        }
-
-        for(i=0; i<CMDMemSize; i++) {
-            MMU_Base[i] = (uint32_t)virt_to_phys((uint32_t *)((CMDStart + i) << PAGE_SHIFT));
-        }
-
-        if (req->src.yrgb_addr < KERNEL_SPACE_VALID)
-        {
-            ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize);
-            if (ret < 0) {
-                pr_err("rga map src memory failed\n");
-                return -EINVAL;
-            }
-        }
-        else
-        {
-            MMU_p = MMU_Base + CMDMemSize;
-
-                for(i=0; i<SrcMemSize; i++)
-                {
-                    MMU_p[i] = (uint32_t)virt_to_phys((uint32_t *)((SrcStart + i) << PAGE_SHIFT));
-                }
-        }
-
-        /* zsq
-         * change the buf address in req struct
-         * for the reason of lie to MMU
-         */
-        req->mmu_info.base_addr = (virt_to_phys(MMU_Base) >> 2);
-
-        req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT);
-
-        /*record the malloc buf for the cmd end to release*/
-        reg->MMU_base = MMU_Base;
-
-        /* flush data to DDR */
-        #ifdef CONFIG_ARM
-        dmac_flush_range(MMU_Base, (MMU_Base + AllSize));
-        outer_flush_range(virt_to_phys(MMU_Base),virt_to_phys(MMU_Base + AllSize));
-        #elif defined(CONFIG_ARM64)
-        __dma_flush_range(MMU_Base, (MMU_Base + AllSize));
-        #endif
-
-
-        if (pages != NULL) {
-            /* Free the page table */
-            kfree(pages);
-        }
-
-        return 0;
-    }
-    while(0);
-
-    if (pages != NULL)
-        kfree(pages);
-
-    if (MMU_Base != NULL)
-        kfree(MMU_Base);
-
-    return status;
-}
-
-static int rga_mmu_info_update_patten_buff_mode(struct rga_reg *reg, struct rga_req *req)
-{
-    int SrcMemSize, CMDMemSize;
-    unsigned long SrcStart, CMDStart;
-    struct page **pages = NULL;
-    uint32_t i;
-    uint32_t AllSize;
-    uint32_t *MMU_Base, *MMU_p;
-    int ret, status;
-
-    MMU_Base = MMU_p = 0;
-
-    do
-    {
-
-        /* cal src buf mmu info */
-        SrcMemSize = rga_mem_size_cal(req->pat.yrgb_addr, req->pat.vir_w * req->pat.vir_h * 4, &SrcStart);
-        if(SrcMemSize == 0) {
-            return -EINVAL;
-        }
-
-        /* cal cmd buf mmu info */
-        CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart);
-        if(CMDMemSize == 0) {
-            return -EINVAL;
-        }
-
-        AllSize = SrcMemSize + CMDMemSize;
-
-        pages = kzalloc(AllSize * sizeof(struct page *), GFP_KERNEL);
-        if(pages == NULL) {
-            pr_err("RGA MMU malloc pages mem failed\n");
-            status = RGA_MALLOC_ERROR;
-            break;
-        }
-
-        MMU_Base = kzalloc(AllSize * sizeof(uint32_t), GFP_KERNEL);
-        if(MMU_Base == NULL) {
-            pr_err("RGA MMU malloc MMU_Base point failed\n");
-            status = RGA_MALLOC_ERROR;
-            break;
-        }
-
-        for(i=0; i<CMDMemSize; i++) {
-            MMU_Base[i] = virt_to_phys((uint32_t *)((CMDStart + i) << PAGE_SHIFT));
-        }
-
-        if (req->src.yrgb_addr < KERNEL_SPACE_VALID)
-        {
-            ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize);
-            if (ret < 0) {
-                pr_err("rga map src memory failed\n");
-                status = ret;
-                break;
-            }
-        }
-        else
-        {
-            MMU_p = MMU_Base + CMDMemSize;
-
-            for(i=0; i<SrcMemSize; i++)
-            {
-                MMU_p[i] = (uint32_t)virt_to_phys((uint32_t *)((SrcStart + i) << PAGE_SHIFT));
-            }
-        }
-
-        /* zsq
-         * change the buf address in req struct
-         * for the reason of lie to MMU
-         */
-        req->mmu_info.base_addr = (virt_to_phys(MMU_Base) >> 2);
-
-        req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT);
-
-        /*record the malloc buf for the cmd end to release*/
-        reg->MMU_base = MMU_Base;
-
-        /* flush data to DDR */
-        #ifdef CONFIG_ARM
-        dmac_flush_range(MMU_Base, (MMU_Base + AllSize));
-        outer_flush_range(virt_to_phys(MMU_Base),virt_to_phys(MMU_Base + AllSize));
-        #elif defined(CONFIG_ARM64)
-        __dma_flush_range(MMU_Base, (MMU_Base + AllSize));
-        #endif
-
-        if (pages != NULL) {
-            /* Free the page table */
-            kfree(pages);
-        }
-
-        return 0;
-
-    }
-    while(0);
-
-    if (pages != NULL)
-        kfree(pages);
-
-    if (MMU_Base != NULL)
-        kfree(MMU_Base);
-
-    return status;
-}
-
-int rga_set_mmu_info(struct rga_reg *reg, struct rga_req *req)
-{
-    int ret;
-
-    switch (req->render_mode) {
-        case bitblt_mode :
-            ret = rga_mmu_info_BitBlt_mode(reg, req);
-            break;
-        case color_palette_mode :
-            ret = rga_mmu_info_color_palette_mode(reg, req);
-            break;
-        case color_fill_mode :
-            ret = rga_mmu_info_color_fill_mode(reg, req);
-            break;
-        case line_point_drawing_mode :
-            ret = rga_mmu_info_line_point_drawing_mode(reg, req);
-            break;
-        case blur_sharp_filter_mode :
-            ret = rga_mmu_info_blur_sharp_filter_mode(reg, req);
-            break;
-        case pre_scaling_mode :
-            ret = rga_mmu_info_pre_scale_mode(reg, req);
-            break;
-        case update_palette_table_mode :
-            ret = rga_mmu_info_update_palette_table_mode(reg, req);
-            break;
-        case update_patten_buff_mode :
-            ret = rga_mmu_info_update_patten_buff_mode(reg, req);
-            break;
-        default :
-            ret = -1;
-            break;
-    }
-
-    return ret;
-}
-
+    }
+    while(0);
+
+    return status;
+}
+
+static int rga_mmu_info_color_palette_mode(struct rga_reg *reg, struct rga_req *req)
+{
+    int SrcMemSize, DstMemSize, CMDMemSize;
+    unsigned long SrcStart, DstStart, CMDStart;
+    struct page **pages = NULL;
+    uint32_t i;
+    uint32_t AllSize;
+    uint32_t *MMU_Base = NULL, *MMU_Base_phys = NULL;
+    uint32_t *MMU_p;
+    int ret, status = 0;
+    uint32_t stride;
+
+    uint8_t shift;
+    uint16_t sw, byte_num;
+
+    shift = 3 - (req->palette_mode & 3);
+    sw = req->src.vir_w;
+    byte_num = sw >> shift;
+    stride = (byte_num + 3) & (~3);
+
+    do {
+        SrcMemSize = rga_mem_size_cal(req->src.yrgb_addr, stride, &SrcStart);
+        if(SrcMemSize == 0) {
+            return -EINVAL;
+        }
+
+        DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr,
+                                        req->dst.format, req->dst.vir_w, req->dst.vir_h,
+                                        &DstStart);
+        if(DstMemSize == 0) {
+            return -EINVAL;
+        }
+
+        CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart);
+        if(CMDMemSize == 0) {
+            return -EINVAL;
+        }
+
+        SrcMemSize = (SrcMemSize + 15) & (~15);
+        DstMemSize = (DstMemSize + 15) & (~15);
+        CMDMemSize = (CMDMemSize + 15) & (~15);
+
+        AllSize = SrcMemSize + DstMemSize + CMDMemSize;
+
+        if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) {
+            pr_err("RGA Get MMU mem failed\n");
+            status = RGA_MALLOC_ERROR;
+            break;
+        }
+
+        mutex_lock(&rga_service.lock);
+        MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
+        MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
+        mutex_unlock(&rga_service.lock);
+
+        pages = rga_mmu_buf.pages;
+
+        /* map CMD addr */
+        for(i=0; i<CMDMemSize; i++) {
+            MMU_Base[i] = (uint32_t)virt_to_phys((uint32_t *)((CMDStart + i)<<PAGE_SHIFT));
+        }
+
+        /* map src addr */
+        if (req->src.yrgb_addr < KERNEL_SPACE_VALID) {
+            ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize);
+            if (ret < 0) {
+                pr_err("rga map src memory failed\n");
+                status = ret;
+                break;
+            }
+        }
+        else {
+            MMU_p = MMU_Base + CMDMemSize;
+
+            for(i=0; i<SrcMemSize; i++)
+            {
+                MMU_p[i] = (uint32_t)virt_to_phys((uint32_t *)((SrcStart + i) << PAGE_SHIFT));
+            }
+        }
+
+        /* map dst addr */
+        if (req->src.yrgb_addr < KERNEL_SPACE_VALID) {
+            ret = rga_MapUserMemory(&pages[CMDMemSize + SrcMemSize], &MMU_Base[CMDMemSize + SrcMemSize], DstStart, DstMemSize);
+            if (ret < 0) {
+                pr_err("rga map dst memory failed\n");
+                status = ret;
+                break;
+            }
+        }
+        else {
+            MMU_p = MMU_Base + CMDMemSize + SrcMemSize;
+            for(i=0; i<DstMemSize; i++)
+                MMU_p[i] = (uint32_t)virt_to_phys((uint32_t *)((DstStart + i) << PAGE_SHIFT));
+        }
+
+
+        /* zsq
+         * change the buf address in req struct
+         * for the reason of lie to MMU
+         */
+        req->mmu_info.base_addr = (virt_to_phys(MMU_Base)>>2);
+        req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT);
+        req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | ((CMDMemSize + SrcMemSize) << PAGE_SHIFT);
+
+        /*record the malloc buf for the cmd end to release*/
+        reg->MMU_base = MMU_Base;
+
+        /* flush data to DDR */
+        rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
+
+        rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16);
+        reg->MMU_len = AllSize + 16;
+
+        return status;
+
+    }
+    while(0);
+
+    return 0;
+}
+
+static int rga_mmu_info_color_fill_mode(struct rga_reg *reg, struct rga_req *req)
+{
+    int DstMemSize;
+    unsigned long DstStart;
+    struct page **pages = NULL;
+    uint32_t i;
+    uint32_t AllSize;
+    uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys;
+    int ret;
+    int status;
+
+    MMU_Base = NULL;
+
+    do {
+        DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr,
+                                        req->dst.format, req->dst.vir_w, req->dst.vir_h,
+                                        &DstStart);
+        if(DstMemSize == 0) {
+            return -EINVAL;
+        }
+
+        AllSize = (DstMemSize + 15) & (~15);
+
+        pages = rga_mmu_buf.pages;
+
+        if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) {
+            pr_err("RGA Get MMU mem failed\n");
+            status = RGA_MALLOC_ERROR;
+            break;
+        }
+
+        mutex_lock(&rga_service.lock);
+        MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
+        MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
+        mutex_unlock(&rga_service.lock);
+
+        if (req->dst.yrgb_addr < KERNEL_SPACE_VALID) {
+            if (req->sg_dst) {
+                ret = rga_MapION(req->sg_dst, &MMU_Base[0], DstMemSize, req->line_draw_info.line_width);
+            }
+            else {
+                ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], DstStart, DstMemSize);
+                if (ret < 0) {
+                    pr_err("rga map dst memory failed\n");
+                    status = ret;
+                    break;
+                }
+            }
+        }
+        else {
+            MMU_p = MMU_Base;
+            for(i=0; i<DstMemSize; i++)
+                MMU_p[i] = (uint32_t)((DstStart + i) << PAGE_SHIFT);
+        }
+
+        MMU_Base[AllSize] = MMU_Base[AllSize - 1];
+
+        /* zsq
+         * change the buf address in req struct
+         */
+
+        req->mmu_info.base_addr = ((unsigned long)(MMU_Base_phys)>>2);
+        req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK));
+
+        /*record the malloc buf for the cmd end to release*/
+        reg->MMU_base = MMU_Base;
+
+        /* flush data to DDR */
+        rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
+
+        rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16);
+        reg->MMU_len = AllSize + 16;
+
+        return 0;
+    }
+    while(0);
+
+    return status;
+}
+
+
+static int rga_mmu_info_line_point_drawing_mode(struct rga_reg *reg, struct rga_req *req)
+{
+    return 0;
+}
+
+static int rga_mmu_info_blur_sharp_filter_mode(struct rga_reg *reg, struct rga_req *req)
+{
+    return 0;
+}
+
+
+
+static int rga_mmu_info_pre_scale_mode(struct rga_reg *reg, struct rga_req *req)
+{
+    int SrcMemSize, DstMemSize;
+    unsigned long SrcStart, DstStart;
+    struct page **pages = NULL;
+    uint32_t i;
+    uint32_t AllSize;
+    uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys;
+    int ret;
+    int status;
+    uint32_t uv_size, v_size;
+
+    MMU_Base = NULL;
+
+    do {
+        /* cal src buf mmu info */
+        SrcMemSize = rga_buf_size_cal(req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr,
+                                        req->src.format, req->src.vir_w, req->src.vir_h,
+                                        &SrcStart);
+        if(SrcMemSize == 0) {
+            return -EINVAL;
+        }
+
+        /* cal dst buf mmu info */
+        DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr,
+                                        req->dst.format, req->dst.vir_w, req->dst.vir_h,
+                                        &DstStart);
+        if(DstMemSize == 0) {
+            return -EINVAL;
+        }
+
+	    SrcMemSize = (SrcMemSize + 15) & (~15);
+	    DstMemSize = (DstMemSize + 15) & (~15);
+
+        AllSize = SrcMemSize + DstMemSize;
+
+        pages = rga_mmu_buf.pages;
+
+        if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) {
+            pr_err("RGA Get MMU mem failed\n");
+            status = RGA_MALLOC_ERROR;
+            break;
+        }
+
+        mutex_lock(&rga_service.lock);
+        MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
+        MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1));
+        mutex_unlock(&rga_service.lock);
+
+        /* map src pages */
+        if ((req->mmu_info.mmu_flag >> 8) & 1) {
+            if (req->sg_src) {
+                ret = rga_MapION(req->sg_src, &MMU_Base[0], SrcMemSize,req->line_draw_info.flag);
+            }
+            else {
+                ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], SrcStart, SrcMemSize);
+                if (ret < 0) {
+                    pr_err("rga map src memory failed\n");
+                    status = ret;
+                    break;
+                }
+            }
+        }
+        else {
+            MMU_p = MMU_Base;
+
+            for(i=0; i<SrcMemSize; i++)
+                MMU_p[i] = (uint32_t)((SrcStart + i) << PAGE_SHIFT);
+        }
+
+        if((req->mmu_info.mmu_flag >> 10) & 1) {
+            if (req->sg_dst) {
+                ret = rga_MapION(req->sg_dst, &MMU_Base[SrcMemSize], DstMemSize, req->line_draw_info.line_width);
+            }
+            else {
+                ret = rga_MapUserMemory(&pages[SrcMemSize], &MMU_Base[SrcMemSize], DstStart, DstMemSize);
+                if (ret < 0) {
+                    pr_err("rga map dst memory failed\n");
+                    status = ret;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            /* kernel space */
+            MMU_p = MMU_Base + SrcMemSize;
+
+            if(req->dst.yrgb_addr == (unsigned long)rga_service.pre_scale_buf) {
+                for(i=0; i<DstMemSize; i++)
+                    MMU_p[i] = rga_service.pre_scale_buf[i];
+            }
+            else {
+                for(i=0; i<DstMemSize; i++)
+                    MMU_p[i] = (uint32_t)((DstStart + i) << PAGE_SHIFT);
+            }
+        }
+
+        MMU_Base[AllSize] = MMU_Base[AllSize];
+
+        /* zsq
+         * change the buf address in req struct
+         * for the reason of lie to MMU
+         */
+
+        req->mmu_info.base_addr = ((unsigned long)(MMU_Base_phys)>>2);
+
+        uv_size = (req->src.uv_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT;
+        v_size = (req->src.v_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT;
+
+        req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK));
+        req->src.uv_addr = (req->src.uv_addr & (~PAGE_MASK)) | (uv_size << PAGE_SHIFT);
+        req->src.v_addr = (req->src.v_addr & (~PAGE_MASK)) | (v_size << PAGE_SHIFT);
+
+        uv_size = (req->dst.uv_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT;
+        v_size = (req->dst.v_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT;
+
+        req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | ((SrcMemSize) << PAGE_SHIFT);
+        req->dst.uv_addr = (req->dst.uv_addr & (~PAGE_MASK)) | ((SrcMemSize + uv_size) << PAGE_SHIFT);
+        req->dst.v_addr = (req->dst.v_addr & (~PAGE_MASK)) | ((SrcMemSize + v_size) << PAGE_SHIFT);
+
+        /*record the malloc buf for the cmd end to release*/
+        reg->MMU_base = MMU_Base;
+
+        /* flush data to DDR */
+        rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1));
+
+	    rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16);
+        reg->MMU_len = AllSize + 16;
+
+        return 0;
+    }
+    while(0);
+
+    return status;
+}
+
+
+static int rga_mmu_info_update_palette_table_mode(struct rga_reg *reg, struct rga_req *req)
+{
+    int SrcMemSize, CMDMemSize;
+    unsigned long SrcStart, CMDStart;
+    struct page **pages = NULL;
+    uint32_t i;
+    uint32_t AllSize;
+    uint32_t *MMU_Base, *MMU_p;
+    int ret, status;
+
+    MMU_Base = NULL;
+
+    do {
+        /* cal src buf mmu info */
+        SrcMemSize = rga_mem_size_cal(req->src.yrgb_addr, req->src.vir_w * req->src.vir_h, &SrcStart);
+        if(SrcMemSize == 0) {
+            return -EINVAL;
+        }
+
+        /* cal cmd buf mmu info */
+        CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart);
+        if(CMDMemSize == 0) {
+            return -EINVAL;
+        }
+
+        AllSize = SrcMemSize + CMDMemSize;
+
+        pages = kzalloc(AllSize * sizeof(struct page *), GFP_KERNEL);
+        if(pages == NULL) {
+            pr_err("RGA MMU malloc pages mem failed\n");
+            status = RGA_MALLOC_ERROR;
+            break;
+        }
+
+        MMU_Base = kzalloc((AllSize + 1)* sizeof(uint32_t), GFP_KERNEL);
+        if(pages == NULL) {
+            pr_err("RGA MMU malloc MMU_Base point failed\n");
+            status = RGA_MALLOC_ERROR;
+            break;
+        }
+
+        for(i=0; i<CMDMemSize; i++) {
+            MMU_Base[i] = (uint32_t)virt_to_phys((uint32_t *)((CMDStart + i) << PAGE_SHIFT));
+        }
+
+        if (req->src.yrgb_addr < KERNEL_SPACE_VALID)
+        {
+            ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize);
+            if (ret < 0) {
+                pr_err("rga map src memory failed\n");
+                return -EINVAL;
+            }
+        }
+        else
+        {
+            MMU_p = MMU_Base + CMDMemSize;
+
+                for(i=0; i<SrcMemSize; i++)
+                {
+                    MMU_p[i] = (uint32_t)virt_to_phys((uint32_t *)((SrcStart + i) << PAGE_SHIFT));
+                }
+        }
+
+        /* zsq
+         * change the buf address in req struct
+         * for the reason of lie to MMU
+         */
+        req->mmu_info.base_addr = (virt_to_phys(MMU_Base) >> 2);
+
+        req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT);
+
+        /*record the malloc buf for the cmd end to release*/
+        reg->MMU_base = MMU_Base;
+
+        /* flush data to DDR */
+        rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize));
+
+
+        if (pages != NULL) {
+            /* Free the page table */
+            kfree(pages);
+        }
+
+        return 0;
+    }
+    while(0);
+
+    if (pages != NULL)
+        kfree(pages);
+
+    if (MMU_Base != NULL)
+        kfree(MMU_Base);
+
+    return status;
+}
+
+static int rga_mmu_info_update_patten_buff_mode(struct rga_reg *reg, struct rga_req *req)
+{
+    int SrcMemSize, CMDMemSize;
+    unsigned long SrcStart, CMDStart;
+    struct page **pages = NULL;
+    uint32_t i;
+    uint32_t AllSize;
+    uint32_t *MMU_Base, *MMU_p;
+    int ret, status;
+
+    MMU_Base = MMU_p = 0;
+
+    do
+    {
+
+        /* cal src buf mmu info */
+        SrcMemSize = rga_mem_size_cal(req->pat.yrgb_addr, req->pat.vir_w * req->pat.vir_h * 4, &SrcStart);
+        if(SrcMemSize == 0) {
+            return -EINVAL;
+        }
+
+        /* cal cmd buf mmu info */
+        CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart);
+        if(CMDMemSize == 0) {
+            return -EINVAL;
+        }
+
+        AllSize = SrcMemSize + CMDMemSize;
+
+        pages = kzalloc(AllSize * sizeof(struct page *), GFP_KERNEL);
+        if(pages == NULL) {
+            pr_err("RGA MMU malloc pages mem failed\n");
+            status = RGA_MALLOC_ERROR;
+            break;
+        }
+
+        MMU_Base = kzalloc(AllSize * sizeof(uint32_t), GFP_KERNEL);
+        if(MMU_Base == NULL) {
+            pr_err("RGA MMU malloc MMU_Base point failed\n");
+            status = RGA_MALLOC_ERROR;
+            break;
+        }
+
+        for(i=0; i<CMDMemSize; i++) {
+            MMU_Base[i] = virt_to_phys((uint32_t *)((CMDStart + i) << PAGE_SHIFT));
+        }
+
+        if (req->src.yrgb_addr < KERNEL_SPACE_VALID)
+        {
+            ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize);
+            if (ret < 0) {
+                pr_err("rga map src memory failed\n");
+                status = ret;
+                break;
+            }
+        }
+        else
+        {
+            MMU_p = MMU_Base + CMDMemSize;
+
+            for(i=0; i<SrcMemSize; i++)
+            {
+                MMU_p[i] = (uint32_t)virt_to_phys((uint32_t *)((SrcStart + i) << PAGE_SHIFT));
+            }
+        }
+
+        /* zsq
+         * change the buf address in req struct
+         * for the reason of lie to MMU
+         */
+        req->mmu_info.base_addr = (virt_to_phys(MMU_Base) >> 2);
+
+        req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT);
+
+        /*record the malloc buf for the cmd end to release*/
+        reg->MMU_base = MMU_Base;
+
+        /* flush data to DDR */
+        rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize));
+
+        if (pages != NULL) {
+            /* Free the page table */
+            kfree(pages);
+        }
+
+        return 0;
+
+    }
+    while(0);
+
+    if (pages != NULL)
+        kfree(pages);
+
+    if (MMU_Base != NULL)
+        kfree(MMU_Base);
+
+    return status;
+}
+
+int rga_set_mmu_info(struct rga_reg *reg, struct rga_req *req)
+{
+    int ret;
+
+    switch (req->render_mode) {
+        case bitblt_mode :
+            ret = rga_mmu_info_BitBlt_mode(reg, req);
+            break;
+        case color_palette_mode :
+            ret = rga_mmu_info_color_palette_mode(reg, req);
+            break;
+        case color_fill_mode :
+            ret = rga_mmu_info_color_fill_mode(reg, req);
+            break;
+        case line_point_drawing_mode :
+            ret = rga_mmu_info_line_point_drawing_mode(reg, req);
+            break;
+        case blur_sharp_filter_mode :
+            ret = rga_mmu_info_blur_sharp_filter_mode(reg, req);
+            break;
+        case pre_scaling_mode :
+            ret = rga_mmu_info_pre_scale_mode(reg, req);
+            break;
+        case update_palette_table_mode :
+            ret = rga_mmu_info_update_palette_table_mode(reg, req);
+            break;
+        case update_patten_buff_mode :
+            ret = rga_mmu_info_update_patten_buff_mode(reg, req);
+            break;
+        default :
+            ret = -1;
+            break;
+    }
+
+    return ret;
+}
+

--
Gitblit v1.6.2