new_codec: modified the method of memory usage to improve performance.
authorKitae Kim <kt920.kim@samsung.com>
Sun, 1 Sep 2013 13:32:28 +0000 (22:32 +0900)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Thu, 27 Feb 2014 06:27:01 +0000 (15:27 +0900)
Separate the memory to use effectively from several regions
when processing mutli contexts.

Change-Id: I4e4269d31aac6ad5ba53e76eedb7c4733e8e95db
Signed-off-by: Kitae Kim <kt920.kim@samsung.com>
drivers/maru/maru_new_codec.c

index c8ef484..642f4a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Virtual Codec PCI device driver
+ * Virtual Codec Device Driver
  *
  * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
  *
@@ -49,7 +49,7 @@
 #include <linux/slab.h>
 
 
-MODULE_DESCRIPTION("Virtual New Codec Device Driver");
+MODULE_DESCRIPTION("Virtual Codec Device Driver");
 MODULE_AUTHOR("Kitae KIM <kt920.kim@samsung.com");
 MODULE_LICENSE("GPL2");
 
@@ -59,25 +59,38 @@ MODULE_LICENSE("GPL2");
 #define PCI_VENDOR_ID_TIZEN_EMUL                       0xC9B5
 #define PCI_DEVICE_ID_VIRTUAL_NEW_CODEC                0x1040
 
+/* interrupt identifier for NEWCODEC */
+#define CODEC_IRQ_TASK 0x1f
+
+//
+#define DEVICE_MEMORY_COUNT 8
+#define CODEC_CONTEXT_SIZE 1024
+
+// DEBUG
 #ifndef CODEC_DEBUG
-#define CODEC_LOG(fmt, ...) \
+#define DEBUG(fmt, ...) \
        printk(KERN_DEBUG "[%s][%d]: " fmt, DEVICE_NAME, __LINE__, ##__VA_ARGS__)
 #else
-#define CODEC_LOG(fmt, ...)
+#define DEBUG(fmt, ...)
 #endif
 
-#define CODEC_IRQ_TASK 0x1f
-#define CODEC_DEVICE_MEM_COUNT 8
+#define ERROR(fmt, ...) \
+       printk(KERN_ERR "[%s][%d]: " fmt, DEVICE_NAME, __LINE__, ##__VA_ARGS__)
+
+#define INFO(fmt, ...) \
+       printk(KERN_INFO "[%s][%d]: " fmt, DEVICE_NAME, __LINE__, ##__VA_ARGS__)
+
 
-//#define TIME_CHECK
-#ifdef TIME_CHECK
+#ifdef CODEC_TIME_LOG
 #include <linux/time.h>
-#define NEWCODEC_TIME_CHECK \
+#define NEWCODEC_CURRENT_TIME \
 { \
        struct timeval now; \
        do_gettimeofday(&now); \
-       printk(KERN_INFO "%ld.%06ld: irq handler.\n", (long)now.tv_sec, (long)now.tv_usec); \
+       printk(KERN_INFO "[%s][%d] current time: %ld.%06ld\n", DEVICE_NAME, __LINE__, (long)now.tv_sec, (long)now.tv_usec); \
 }
+#else
+#define NEWCODEC_CURRENT_TIME
 #endif
 
 struct codec_param {
@@ -93,7 +106,7 @@ struct codec_mem_info {
 };
 
 enum codec_io_cmd {
-       CODEC_CMD_COPY_TO_DEVICE_MEM = 5,       // plugin and driver
+       CODEC_CMD_COPY_TO_DEVICE_MEM = 5,       // user and driver
        CODEC_CMD_COPY_FROM_DEVICE_MEM,
        CODEC_CMD_API_INDEX = 10,                       // driver and device
        CODEC_CMD_CONTEXT_INDEX,
@@ -103,12 +116,18 @@ enum codec_io_cmd {
        CODEC_CMD_GET_QUEUE,
        CODEC_CMD_POP_WRITE_QUEUE,
        CODEC_CMD_RESET_AVCONTEXT,
-       CODEC_CMD_GET_VERSION = 20,                     // plugin, driver and device
+       CODEC_CMD_GET_VERSION = 20,                     // user, driver and device
        CODEC_CMD_GET_ELEMENT,
        CODEC_CMD_GET_CONTEXT_INDEX,
        CODEC_CMD_SECURE_MEMORY= 30,
        CODEC_CMD_RELEASE_MEMORY,
-       CODEC_CMD_COPY_FROM_DEVICE_MEM2,
+       CODEC_CMD_USE_DEVICE_MEM,
+       CODEC_CMD_REQ_FROM_SMALL_MEMORY,
+       CODEC_CMD_REQ_FROM_MEDIUM_MEMORY,
+       CODEC_CMD_REQ_FROM_LARGE_MEMORY,
+       CODEC_CMD_S_SECURE_BUFFER,
+       CODEC_CMD_M_SECURE_BUFFER,
+       CODEC_CMD_L_SECURE_BUFFER,
 };
 
 enum codec_api_index {
@@ -129,7 +148,6 @@ struct device_mem {
        struct list_head entry;
 };
 
-
 struct newcodec_device {
        struct pci_dev *dev;
 
@@ -145,53 +163,121 @@ struct newcodec_device {
        struct list_head avail_memblk;
        struct list_head used_memblk;
 
+       struct list_head avail_s_memblk;
+       struct list_head used_s_memblk;
+       struct list_head avail_m_memblk;
+       struct list_head used_m_memblk;
+       struct list_head avail_l_memblk;
+       struct list_head used_l_memblk;
+
        spinlock_t lock;
 
        int version;
 };
 
 static struct newcodec_device *newcodec;
-static int context_flags[1024] = { 0, };
+static int context_flags[CODEC_CONTEXT_SIZE] = { 0, };
 
+// semaphore, mutex
 static DEFINE_MUTEX(critical_section);
 static DEFINE_MUTEX(newcodec_blk_mutex);
 
 static struct semaphore newcodec_buffer_mutex =
-       __SEMAPHORE_INITIALIZER(newcodec_buffer_mutex, CODEC_DEVICE_MEM_COUNT);
+       __SEMAPHORE_INITIALIZER(newcodec_buffer_mutex, DEVICE_MEMORY_COUNT);
 
-static DECLARE_WAIT_QUEUE_HEAD(wait_queue);
+#define        ENTER_CRITICAL_SECTION  mutex_lock(&critical_section);
+#define LEAVE_CRITICAL_SECTION mutex_unlock(&critical_section);
 
-// static void newcodec_add_task(struct list_head *entry, uint32_t file);
+#define CODEC_S_DEVICE_MEM_COUNT       63      // small                (256K)  8M
+#define CODEC_XS_DEVICE_MEM_COUNT      8       // extra small  (1M)    8M
+#define CODEC_M_DEVICE_MEM_COUNT       4       // medium               (2M)    8M
+#define CODEC_L_DEVICE_MEM_COUNT       2       // large                (4M)    8M
+
+#define CODEC_S_DEVICE_MEM_SIZE                0x40000         // small
+#define CODEC_XS_DEVICE_MEM_SIZE       0x100000        // extra small
+#define CODEC_M_DEVICE_MEM_SIZE                0x200000        // medium
+#define CODEC_L_DEVICE_MEM_SIZE                0x400000        // large
+
+static DEFINE_MUTEX(s_block_mutex);
+static DEFINE_MUTEX(m_block_mutex);
+static DEFINE_MUTEX(l_block_mutex);
+
+static struct semaphore s_buffer_sema =
+       __SEMAPHORE_INITIALIZER(s_buffer_sema, CODEC_S_DEVICE_MEM_COUNT);
+
+static struct semaphore m_buffer_sema =
+       __SEMAPHORE_INITIALIZER(m_buffer_sema, CODEC_M_DEVICE_MEM_COUNT);
+
+static struct semaphore l_buffer_sema =
+       __SEMAPHORE_INITIALIZER(l_buffer_sema, CODEC_L_DEVICE_MEM_COUNT);
+
+// bottom-half
+static DECLARE_WAIT_QUEUE_HEAD(wait_queue);
 
 static struct workqueue_struct *newcodec_bh_workqueue;
 static void newcodec_bh_func(struct work_struct *work);
 static DECLARE_WORK(newcodec_bh_work, newcodec_bh_func);
 static void newcodec_bh(struct newcodec_device *dev);
 
-#define        ENTER_CRITICAL_SECTION  mutex_lock(&critical_section);
-#define LEAVE_CRITICAL_SECTION mutex_unlock(&critical_section);
+
+// internal function
+static void newcodec_write_data(int cmd1, int cmd2,
+                                                               uint32_t value1, uint32_t value2);
+
+
+static void newcodec_divide_device_memory(void)
+{
+       struct device_mem *elem = NULL;
+       int index = 0, cnt;
+
+       elem =
+               kzalloc(sizeof(struct device_mem) * (63 + 4 + 2), GFP_KERNEL);
+       if (!elem) {
+               ERROR("falied to allocate memory!!\n");
+               return;
+       }
+
+       for (cnt = 0; cnt < CODEC_S_DEVICE_MEM_COUNT; index++, cnt++) {
+               elem[index].mem_offset = (index + 1) * CODEC_S_DEVICE_MEM_SIZE;
+               elem[index].occupied = false;
+               list_add_tail(&elem[index].entry, &newcodec->avail_s_memblk);
+       }
+
+       for (cnt = 0; cnt < CODEC_M_DEVICE_MEM_COUNT; index++, cnt++) {
+               elem[index].mem_offset = (16 * 1024 * 1024) + (cnt * CODEC_M_DEVICE_MEM_SIZE);
+               elem[index].occupied = false;
+               list_add_tail(&elem[index].entry, &newcodec->avail_m_memblk);
+       }
+
+#if 1
+       for (cnt = 0; cnt < CODEC_L_DEVICE_MEM_COUNT; index++, cnt++) {
+               elem[index].mem_offset = (16 * 1024 * 1024) + (8 * 1024 * 1024) + (cnt * CODEC_L_DEVICE_MEM_SIZE);
+               elem[index].occupied = false;
+               list_add_tail(&elem[index].entry, &newcodec->avail_l_memblk);
+       }
+#endif
+}
 
 static void newcodec_bh_func(struct work_struct *work)
 {
        uint32_t value;
 
-       CODEC_LOG("%s\n", __func__);
+       DEBUG("%s\n", __func__);
        do {
                value = readl(newcodec->ioaddr + CODEC_CMD_GET_QUEUE);
-               CODEC_LOG("read a value from device %x.\n", value);
+               DEBUG("read a value from device %x.\n", value);
                if (value) {
-//                     newcodec_add_task(&newcodec->req_task, value);
-            context_flags[value] = 1;
-            wake_up_interruptible(&wait_queue);
+                       context_flags[value] = 1;
+                       wake_up_interruptible(&wait_queue);
                } else {
-                       CODEC_LOG("there is no available task\n");
+                       DEBUG("there is no available task\n");
                }
        } while (value);
 }
 
 static void newcodec_bh(struct newcodec_device *dev)
 {
-       CODEC_LOG("add bottom-half function to codec_workqueue\n");
+       DEBUG("add bottom-half function to codec_workqueue\n");
        queue_work(newcodec_bh_workqueue, &newcodec_bh_work);
 }
 
@@ -200,80 +286,245 @@ static int lock_buffer(void)
        int ret;
        ret = down_interruptible(&newcodec_buffer_mutex);
 
-//     CODEC_LOG("lock buffer_mutex: %d\n", newcodec_buffer_mutex.count);
+//     DEBUG("lock buffer_mutex: %d\n", newcodec_buffer_mutex.count);
        return ret;
 }
 
 static void unlock_buffer(void)
 {
     up(&newcodec_buffer_mutex);
-//     CODEC_LOG("unlock buffer_mutex: %d\n", newcodec_buffer_mutex.count);
+//     DEBUG("unlock buffer_mutex: %d\n", newcodec_buffer_mutex.count);
 }
 
-static void release_device_memory(uint32_t mem_offset)
+static int secure_s_device_memory(uint32_t blk_id)
 {
-//     struct device_mem_mgr *mem_mgr = NULL;
-//     int index;
+       int ret = -1;
+       struct device_mem *elem = NULL;
 
-#if 0
-       for (index = 0; index < CODEC_DEVICE_MEM_COUNT; index++) {
-               mem_mgr = &newcodec->mem_mgr[index];
-               if (mem_mgr->mem_offset == mem_offset) {
-                       mem_mgr->occupied = false;
-                       mem_mgr->context_id = 0;
-                       break;
+       // decrease s_buffer_semaphore
+       DEBUG("before down s_buffer_sema: %d\n", s_buffer_sema.count);
+       ret = down_interruptible(&s_buffer_sema);
+       DEBUG("after down s_buffer_sema: %d\n", s_buffer_sema.count);
+       if (ret < 0) {
+               ERROR("no available memory block\n");
+               return ret;
+       }
+
+       mutex_lock(&s_block_mutex);
+
+       NEWCODEC_CURRENT_TIME
+
+       if (!list_empty(&newcodec->avail_s_memblk)) {
+               elem =
+                       list_first_entry(&newcodec->avail_s_memblk,
+                                                       struct device_mem, entry);
+               if (!elem) {
+                       ret = -1;
+                       up(&s_buffer_sema);
+                       ERROR("failed to get first entry from avail_s_memblk.\n");
+               } else {
+                       elem->blk_id = blk_id;
+                       elem->occupied = true;
+
+                       list_move_tail(&elem->entry, &newcodec->used_s_memblk);
+                       ret = elem->mem_offset;
+                       DEBUG("get available memory region: 0x%x\n", ret);
                }
+       } else {
+               ERROR("the number of buffer mutex: %d\n",  s_buffer_sema.count);
+               ERROR("no available memory block\n");
+               ret = -1;
+               up(&s_buffer_sema);
        }
-#endif
-       {
-               struct device_mem *elem = NULL;
-               struct list_head *pos, *temp;
 
-//             printk(KERN_INFO "release the memory offset: 0x%x", mem_offset);
-               mutex_lock(&newcodec_blk_mutex);
+       NEWCODEC_CURRENT_TIME
 
-               if (!list_empty(&newcodec->used_memblk)) {
-                       list_for_each_safe(pos, temp, &newcodec->used_memblk) {
-                               elem = list_entry(pos, struct device_mem, entry);
-                               if (elem->mem_offset == (uint32_t)mem_offset) {
-//                                     printk(KERN_INFO "move %p to avail_memblk, mem_offset: 0x%x", elem, mem_offset);
+       mutex_unlock(&s_block_mutex);
 
-                                       elem->blk_id = 0;
-                                       elem->occupied = false;
-                                       list_move(&elem->entry, &newcodec->avail_memblk);
+       return ret;
+}
 
-                                       unlock_buffer();
-                                       break;
-                               }
+static void release_s_device_memory(uint32_t mem_offset)
+{
+       struct device_mem *elem = NULL;
+       struct list_head *pos, *temp;
+
+       mutex_lock(&s_block_mutex);
+       if (!list_empty(&newcodec->used_s_memblk)) {
+               list_for_each_safe(pos, temp, &newcodec->used_s_memblk) {
+                       elem = list_entry(pos, struct device_mem, entry);
+                       if (elem->mem_offset == (uint32_t)mem_offset) {
+
+                               elem->blk_id = 0;
+                               elem->occupied = false;
+                               list_move_tail(&elem->entry, &newcodec->avail_s_memblk);
+
+                           up(&s_buffer_sema);
+                               DEBUG("unlock s_buffer_sema: %d\n", s_buffer_sema.count);
+
+                               break;
                        }
+               }
+       } else {
+               DEBUG("there is no used memory block.\n");
+       }
+       mutex_unlock(&s_block_mutex);
+}
+
+static int secure_m_device_memory(uint32_t blk_id)
+{
+       int ret = -1;
+       struct device_mem *elem = NULL;
+
+       // decrease m_buffer_semaphore
+       INFO("before down m_buffer_sema: %d\n", m_buffer_sema.count);
+       ret = down_interruptible(&m_buffer_sema);
+       INFO("after down m_buffer_sema: %d\n", m_buffer_sema.count);
+       if (ret < 0) {
+               ERROR("m_buffer_sema: %d\n", m_buffer_sema.count);
+               ERROR("no available memory block\n");
+               return ret;
+       }
+
+       mutex_lock(&m_block_mutex);
+
+       if (!list_empty(&newcodec->avail_m_memblk)) {
+               elem =
+                       list_first_entry(&newcodec->avail_m_memblk,
+                                                       struct device_mem, entry);
+               if (!elem) {
+                       ret = -1;
+                       up(&m_buffer_sema);
+                       ERROR("failed to get first entry from avail_m_memblk. %d\n", m_buffer_sema.count);
                } else {
-                       CODEC_LOG("there is no used memory block.\n");
+                       elem->blk_id = blk_id;
+                       elem->occupied = true;
+
+                       list_move_tail(&elem->entry, &newcodec->used_m_memblk);
+                       ret = elem->mem_offset;
+                       DEBUG("get available memory region: 0x%x\n", ret);
                }
+       } else {
+               ERROR("no available memory block\n");
+               ret = -1;
+               up(&m_buffer_sema);
+               ERROR("the number of buffer mutex: %d\n",  m_buffer_sema.count);
+       }
 
-               mutex_unlock(&newcodec_blk_mutex);
+       mutex_unlock(&m_block_mutex);
+
+       return ret;
+}
+
+static void release_m_device_memory(uint32_t mem_offset)
+{
+       struct device_mem *elem = NULL;
+       struct list_head *pos, *temp;
+
+       mutex_lock(&m_block_mutex);
+       if (!list_empty(&newcodec->used_m_memblk)) {
+               list_for_each_safe(pos, temp, &newcodec->used_m_memblk) {
+                       elem = list_entry(pos, struct device_mem, entry);
+                       if (elem->mem_offset == (uint32_t)mem_offset) {
+
+                               elem->blk_id = 0;
+                               elem->occupied = false;
+                               list_move_tail(&elem->entry, &newcodec->avail_m_memblk);
+
+                           up(&m_buffer_sema);
+                               INFO("unlock m_buffer_sema: %d\n", m_buffer_sema.count);
+
+                               break;
+                       }
+               }
+       } else {
+               DEBUG("there is no used memory block.\n");
        }
+       mutex_unlock(&m_block_mutex);
 }
 
 
-static int32_t secure_device_memory(uint32_t blk_id)
+static int32_t secure_l_device_memory(uint32_t blk_id)
 {
-//     struct device_mem_mgr *mem_mgr = NULL;
-//     int index, ret = -1;
        int ret = -1;
+       struct device_mem *elem = NULL;
 
-#if 0
-       if (!newcodec->mem_mgr) {
-               printk(KERN_ERR "Invalid access to mem_mgr variable.\n");
+#if 1
+       // decrease m_buffer_semaphore
+       DEBUG("before down l_buffer_semaphore: %d\n", l_buffer_sema.count);
+       ret = down_interruptible(&l_buffer_sema);
+       DEBUG("after down l_buffer_semaphore: %d\n", l_buffer_sema.count);
+       if (ret < 0) {
+               ERROR("l_buffer_semaphore: %d\n", l_buffer_sema.count);
+               ERROR("no available memory block\n");
                return ret;
        }
+
+       mutex_lock(&l_block_mutex);
+
+       if (!list_empty(&newcodec->avail_l_memblk)) {
+               elem =
+                       list_first_entry(&newcodec->avail_l_memblk,
+                                                       struct device_mem, entry);
+               if (!elem) {
+                       ret = -1;
+                       up(&l_buffer_sema);
+                       ERROR("failed to get first entry from avail_l_memblk.\n");
+               } else {
+                       elem->blk_id = blk_id;
+                       elem->occupied = true;
+
+                       list_move_tail(&elem->entry, &newcodec->used_l_memblk);
+                       ret = elem->mem_offset;
+                       DEBUG("get available memory region: 0x%x\n", ret);
+               }
+       } else {
+               ERROR("the number of buffer mutex: %d\n",  l_buffer_sema.count);
+               ERROR("no available memory block\n");
+               ret = -1;
+               up(&l_buffer_sema);
+       }
+
+       mutex_unlock(&l_block_mutex);
 #endif
 
-//     CODEC_LOG("try to lock the buffer_mutex. %x, %d\n",
-//                     blk_id, newcodec_buffer_mutex.count);
+       return ret;
+}
+
+static void release_l_device_memory(uint32_t mem_offset)
+{
+       struct device_mem *elem = NULL;
+       struct list_head *pos, *temp;
+
+#if 1
+       mutex_lock(&l_block_mutex);
+       if (!list_empty(&newcodec->used_l_memblk)) {
+               list_for_each_safe(pos, temp, &newcodec->used_l_memblk) {
+                       elem = list_entry(pos, struct device_mem, entry);
+                       if (elem->mem_offset == (uint32_t)mem_offset) {
 
-       if (lock_buffer()) {
-        // TODO: need some care...
-    }
+                               elem->blk_id = 0;
+                               elem->occupied = false;
+                               list_move(&elem->entry, &newcodec->avail_l_memblk);
+
+                           up(&l_buffer_sema);
+                               DEBUG("up l_buffer_semaphore: %d\n", l_buffer_sema.count);
+
+                               break;
+                       }
+               }
+       } else {
+               DEBUG("there is no used memory block.\n");
+       }
+       mutex_unlock(&l_block_mutex);
+#endif
+}
+
+static int32_t secure_device_memory(uint32_t blk_id)
+{
+       int ret = 0;
+
+       lock_buffer();
 
        {
                // check whether avail_memblk is empty.
@@ -287,57 +538,63 @@ static int32_t secure_device_memory(uint32_t blk_id)
                        elem =
                                list_first_entry(&newcodec->avail_memblk, struct device_mem, entry);
                        if (!elem) {
-                               printk(KERN_ERR "failed to get first entry from avail_memblk\n");
-                               return ret;
+                               ERROR("failed to get first entry from avail_memblk\n");
+                               ret = -1;
+                       } else {
+                               elem->blk_id = blk_id;
+                               elem->occupied = true;
+
+                               list_move_tail(&elem->entry, &newcodec->used_memblk);
+                               ret = elem->mem_offset;
                        }
-                       elem->blk_id = blk_id;
-                       elem->occupied = true;
-
-//                     printk(KERN_INFO "selected memblk: %p, offset: 0x%x", elem, elem->mem_offset);
-//                     printk(KERN_INFO "avail_memblk is not empty. 0x%x", elem->mem_offset);
-
-                       list_move_tail(&elem->entry, &newcodec->used_memblk);
-                       ret = elem->mem_offset;
-
-                       elem =
-                               list_first_entry(&newcodec->avail_memblk, struct device_mem, entry);
-//                     printk(KERN_INFO "head of avail_memblk %p", elem);
-
                } else {
-                       printk(KERN_ERR "[%s][%d]: the number of buffer mutex: %d\n",
-                                       DEVICE_NAME, __LINE__, newcodec_buffer_mutex.count);
-                       printk(KERN_ERR "[%s][%d]: no available memory block\n",
-                                       DEVICE_NAME, __LINE__);
+                       ERROR("no available memory block\n");
+                       ERROR("the number of buffer mutex: %d\n", newcodec_buffer_mutex.count);
+                       ret = -1;
                }
 
                mutex_unlock(&newcodec_blk_mutex);
        }
 
-//     printk(KERN_ERR "secure_memory, mem_offset: 0x%x\n", ret);
-
-#if 0
-       for (index = 0; index < CODEC_DEVICE_MEM_COUNT; index++) {
-               mem_mgr = &newcodec->mem_mgr[index];
-
-           CODEC_LOG("mem_mgr[%d] : %d, 0x%x\n", index, mem_mgr->occupied, mem_mgr->mem_offset);
+       return ret;
+}
 
-               if (!mem_mgr->occupied) {
-                       mem_mgr->occupied = true;
-                       mem_mgr->context_id = file;
+static void release_device_memory(uint32_t mem_offset)
+{
 
-                       ret = index;
-            break;
+#if 0
+       struct device_mem *elem = NULL;
+       struct list_head *pos, *temp;
+
+       mutex_lock(&newcodec_blk_mutex);
+       if (!list_empty(&newcodec->used_memblk)) {
+               list_for_each_safe(pos, temp, &newcodec->used_memblk) {
+                       elem = list_entry(pos, struct device_mem, entry);
+                       if (elem->mem_offset == (uint32_t)mem_offset) {
+                               elem->blk_id = 0;
+                               elem->occupied = false;
+                               list_move(&elem->entry, &newcodec->avail_memblk);
+
+                               unlock_buffer();
+                               break;
+                       }
                }
+       } else {
+               DEBUG("there is no used memory block.\n");
        }
+       mutex_unlock(&newcodec_blk_mutex);
 #endif
 
-#if 0
-       if (ret == newcodec->mem_size) {
-               printk(KERN_ERR "mem_offset overflow: 0x%x\n", ret);
+       if (mem_offset < (16 * 1024 * 1024)) {
+               DEBUG("release small size of memory\n");
+               release_s_device_memory(mem_offset);
+       } else if (mem_offset - (24 * 1024 * 1024)) {
+               DEBUG("release medium size of memory\n");
+               release_m_device_memory(mem_offset);
+       } else {
+               DEBUG("release large size of memory\n");
+               release_l_device_memory(mem_offset);
        }
-#endif
-
-       return ret;
 }
 
 static long newcodec_ioctl(struct file *file,
@@ -347,45 +604,32 @@ static long newcodec_ioctl(struct file *file,
        long value = 0, ret = 0;
 
        switch (cmd) {
-#if 0
-       case CODEC_CMD_REMOVE_TASK_QUEUE:
-    {
-               uint32_t mem_offset;
-
-               if (copy_from_user(&mem_offset, (void *)arg, sizeof(uint32_t))) {
-                       printk(KERN_ERR "ioctl: failed to copy data to user\n");
-                       ret = -EIO;
-                       break;
-               }
-               release_device_memory(mem_offset);
-               break;
-    }
-#endif
        case CODEC_CMD_COPY_TO_DEVICE_MEM:
        {
-               CODEC_LOG("copy data to device memory\n");
+               DEBUG("copy data to device memory\n");
                value =
                        secure_device_memory((uint32_t)file);
                if (value < 0) {
-                       CODEC_LOG(KERN_ERR "failed to get available memory\n");
+                       ERROR("failed to get available memory\n");
+                       ret = -EINVAL;  
                } else {
                        if (copy_to_user((void *)arg, &value, sizeof(uint32_t))) {
-                               printk(KERN_ERR "ioctl: failed to copy data to user.\n");
+                               ERROR("ioctl: failed to copy data to user.\n");
                                ret = -EIO;
                        }
                }
        }
                break;
-
        case CODEC_CMD_COPY_FROM_DEVICE_MEM:
        {
-               CODEC_LOG("copy data from device memory. %p\n", file);
+               DEBUG("copy data from device memory. %p\n", file);
                value =
                        secure_device_memory((uint32_t)file);
                if (value < 0) {
-                       CODEC_LOG(KERN_ERR "failed to get available memory\n");
+                       ERROR("failed to get available memory\n");
+                       ret = -EINVAL;
                } else {
-                       CODEC_LOG("send a request to pop data from device. %p\n", file);
+                       DEBUG("send a request to pop data from device. %p\n", file);
 
                        ENTER_CRITICAL_SECTION;
                        writel((uint32_t)value,
@@ -395,49 +639,42 @@ static long newcodec_ioctl(struct file *file,
                        LEAVE_CRITICAL_SECTION;
 
                        if (copy_to_user((void *)arg, &value, sizeof(uint32_t))) {
-                               printk(KERN_ERR "ioctl: failed to copy data to user.\n");
+                               ERROR("ioctl: failed to copy data to user.\n");
                                ret = -EIO;
                        }
                }
        }
                break;
-#if 0
-       case CODEC_CMD_RELEASE_DEVICE_MEM:
-       {
-               uint32_t mem_offset;
 
-               if (copy_from_user(&mem_offset, (void *)arg, sizeof(uint32_t))) {
-                       printk(KERN_ERR "ioctl: failed to copy data to user\n");
-                       ret = -EIO;
-                       break;
-               }
-
-               release_device_memory(mem_offset);
-       }
-               break;
-#endif
        case CODEC_CMD_GET_VERSION:
-               CODEC_LOG("return codec device version: %d\n", newcodec->version);
+               DEBUG("%s version: %d\n", DEVICE_NAME, newcodec->version);
 
                if (copy_to_user((void *)arg, &newcodec->version, sizeof(int))) {
-                       printk(KERN_ERR "ioctl: failed to copy data to user\n");
+                       ERROR("ioctl: failed to copy data to user\n");
                        ret = -EIO;
            }
                break;
        case CODEC_CMD_GET_ELEMENT:
-               CODEC_LOG("request a device to get codec element\n");
+               DEBUG("request a device to get codec elements\n");
 
                ENTER_CRITICAL_SECTION;
-               readl(newcodec->ioaddr + cmd);
+               value = readl(newcodec->ioaddr + cmd);
                LEAVE_CRITICAL_SECTION;
+
+               if (value < 0) {
+                       ERROR("ioctl: failed to get elements. %d\n", (int)value);
+                       ret = -EINVAL;
+               }
                break;
        case CODEC_CMD_GET_CONTEXT_INDEX:
-               CODEC_LOG("request a device to get an index of codec context \n");
+               DEBUG("request a device to get an index of codec context \n");
 
                value = readl(newcodec->ioaddr + cmd);
-
-               if (copy_to_user((void *)arg, &value, sizeof(int))) {
-                       printk(KERN_ERR "ioctl: failed to copy data to user\n");
+               if (value < 0 || value > CODEC_CONTEXT_SIZE) {
+                       ERROR("ioctl: failed to get proper context. %d\n", (int)value);
+                       ret = -EINVAL;
+               } else if (copy_to_user((void *)arg, &value, sizeof(int))) {
+                       ERROR("ioctl: failed to copy data to user\n");
                        ret = -EIO;
            }
                break;
@@ -445,10 +682,11 @@ static long newcodec_ioctl(struct file *file,
                value =
                        secure_device_memory((uint32_t)file);
                if (value < 0) {
-                       CODEC_LOG(KERN_ERR "failed to get available memory\n");
+                       ERROR("failed to get available memory\n");
+                       ret = -EINVAL;
                } else {
                        if (copy_to_user((void *)arg, &value, sizeof(uint32_t))) {
-                               printk(KERN_ERR "ioctl: failed to copy data to user.\n");
+                               ERROR("ioctl: failed to copy data to user.\n");
                                ret = -EIO;
                        }
                }
@@ -458,57 +696,151 @@ static long newcodec_ioctl(struct file *file,
                uint32_t mem_offset;
 
                if (copy_from_user(&mem_offset, (void *)arg, sizeof(uint32_t))) {
-                       printk(KERN_ERR "ioctl: failed to copy data to user\n");
+                       ERROR("ioctl: failed to copy data from user\n");
                        ret = -EIO;
                        break;
                }
                release_device_memory(mem_offset);
     }
         break;
-    case CODEC_CMD_COPY_FROM_DEVICE_MEM2:
+    case CODEC_CMD_USE_DEVICE_MEM:
        {
                uint32_t mem_offset;
 
                if (copy_from_user(&mem_offset, (void *)arg, sizeof(uint32_t))) {
-                       printk(KERN_ERR "ioctl: failed to copy data to user\n");
+                       ERROR("ioctl: failed to copy data from user\n");
                        ret = -EIO;
                        break;
                }
 
-//             printk(KERN_INFO "copy data from device memory2. 0x%x\n", mem_offset);
-
                if (mem_offset == newcodec->mem_size) {
-                       printk(KERN_ERR "offset of device memory is overflow!! 0x%x\n", mem_offset);
-               }
-               // notify that codec device can copy data to memory region.
-               CODEC_LOG("send a request to pop data from device. %p\n", file);
+                       ERROR("offset of device memory is overflow!! 0x%x\n", mem_offset);
+                       ret = -EIO;
+               } else {
+                       // notify that codec device can copy data to memory region.
+                       DEBUG("send a request to pop data from device. %p\n", file);
 
-               ENTER_CRITICAL_SECTION;
-               writel((uint32_t)mem_offset,
+                       ENTER_CRITICAL_SECTION;
+                       writel((uint32_t)mem_offset,
                                        newcodec->ioaddr + CODEC_CMD_DEVICE_MEM_OFFSET);
-               writel((uint32_t)file,
-                       newcodec->ioaddr + CODEC_CMD_POP_WRITE_QUEUE);
-               LEAVE_CRITICAL_SECTION;
+                       writel((uint32_t)file,
+                                       newcodec->ioaddr + CODEC_CMD_POP_WRITE_QUEUE);
+                       LEAVE_CRITICAL_SECTION;
+               }
        }
                break;
+       case CODEC_CMD_REQ_FROM_SMALL_MEMORY:
+               DEBUG("read small size of data from device memory\n");
 
-#if 0
-    case CODEC_CMD_COPY_FROM_DEVICE_MEM3:
-       {
-               uint32_t mem_offset;
+               value =
+                       secure_s_device_memory((uint32_t)file);
+               if (value < 0) {
+                       ERROR("failed to get available memory\n");
+                       ret = -EINVAL;
+               } else {
+                       DEBUG("send a request to pop data from device. %p\n", file);
 
-               if (copy_from_user(&mem_offset, (void *)arg, sizeof(uint32_t))) {
-                       printk(KERN_ERR "ioctl: failed to copy data to user\n");
-                       ret = -EIO;
-                       break;
+                       newcodec_write_data(CODEC_CMD_DEVICE_MEM_OFFSET,
+                                                               CODEC_CMD_POP_WRITE_QUEUE,
+                                                               (uint32_t)value, (uint32_t)file);
+
+                       if (copy_to_user((void *)arg, &value, sizeof(int32_t))) {
+                               ERROR("ioctl: failed to copy data to user.\n");
+                               ret = -EIO;
+                       }
                }
+               break;
+       case CODEC_CMD_REQ_FROM_MEDIUM_MEMORY:
+               DEBUG("read large size of data from device memory\n");
 
-//             printk(KERN_INFO "DEVICE_MEM3. memory_offset for decoded picture: 0x%x\n", mem_offset);
-       }
+               value =
+                       secure_m_device_memory((uint32_t)file);
+               if (value < 0) {
+                       ERROR("failed to get available memory\n");
+                       ret = -EINVAL;
+               } else {
+                       DEBUG("send a request to pop data from device. %p\n", file);
+
+                       ENTER_CRITICAL_SECTION;
+                       writel((uint32_t)value,
+                                       newcodec->ioaddr + CODEC_CMD_DEVICE_MEM_OFFSET);
+                       writel((uint32_t)file,
+                                       newcodec->ioaddr + CODEC_CMD_POP_WRITE_QUEUE);
+                       LEAVE_CRITICAL_SECTION;
+
+                       if (copy_to_user((void *)arg, &value, sizeof(uint32_t))) {
+                               ERROR("ioctl: failed to copy data to user.\n");
+                               ret = -EIO;
+                       }
+               }
                break;
-#endif
+       case CODEC_CMD_REQ_FROM_LARGE_MEMORY:
+               DEBUG("read large size of data from device memory\n");
+
+               value =
+                       secure_l_device_memory((uint32_t)file);
+               if (value < 0) {
+                       ERROR("failed to get available memory\n");
+                       ret = -EINVAL;
+
+               } else {
+                       DEBUG("send a request to pop data from device. %p\n", file);
+
+                       ENTER_CRITICAL_SECTION;
+                       writel((uint32_t)value,
+                                       newcodec->ioaddr + CODEC_CMD_DEVICE_MEM_OFFSET);
+                       writel((uint32_t)file,
+                                       newcodec->ioaddr + CODEC_CMD_POP_WRITE_QUEUE);
+                       LEAVE_CRITICAL_SECTION;
+
+                       if (copy_to_user((void *)arg, &value, sizeof(uint32_t))) {
+                               ERROR("ioctl: failed to copy data to user.\n");
+                               ret = -EIO;
+                       }
+               }
+               break;
+    case CODEC_CMD_S_SECURE_BUFFER:
+               value =
+                       secure_s_device_memory((uint32_t)file);
+               if (value < 0) {
+                       ERROR("failed to get available memory\n");
+                       ret = -EINVAL;
+               } else {
+                       if (copy_to_user((void *)arg, &value, sizeof(uint32_t))) {
+                               ERROR("ioctl: failed to copy data to user.\n");
+                               ret = -EIO;
+                       }
+               }
+        break;
+    case CODEC_CMD_M_SECURE_BUFFER:
+               value =
+                       secure_m_device_memory((uint32_t)file);
+               if (value < 0) {
+                       ERROR("failed to get available memory\n");
+                       ret = -EINVAL;
+               } else {
+                       if (copy_to_user((void *)arg, &value, sizeof(uint32_t))) {
+                               ERROR("ioctl: failed to copy data to user.\n");
+                               ret = -EIO;
+                       }
+               }
+        break;
+    case CODEC_CMD_L_SECURE_BUFFER:
+               value =
+                       secure_l_device_memory((uint32_t)file);
+               if (value < 0) {
+                       ERROR("failed to get available memory\n");
+                       ret = -EINVAL;
+               } else {
+                       if (copy_to_user((void *)arg, &value, sizeof(uint32_t))) {
+                               ERROR("ioctl: failed to copy data to user.\n");
+                               ret = -EIO;
+                       }
+               }
+        break;
        default:
-               CODEC_LOG("no available command.");
+               DEBUG("no available command.");
+               ret = -EINVAL;
                break;
        }
 
@@ -518,78 +850,181 @@ static long newcodec_ioctl(struct file *file,
 static ssize_t newcodec_read(struct file *file, char __user *buf,
                                                        size_t count, loff_t *fops)
 {
-       CODEC_LOG("do nothing.\n");
+       DEBUG("do nothing.\n");
        return 0;
 }
 
+static void newcodec_write_data(int cmd1, int cmd2,
+                                                               uint32_t value1, uint32_t value2)
+{
+       ENTER_CRITICAL_SECTION;
+       writel(value1, newcodec->ioaddr + cmd1);
+       writel(value2, newcodec->ioaddr + cmd2);
+       LEAVE_CRITICAL_SECTION;
+}
+
+static void newcodec_func(struct codec_param *param, uint32_t file_index)
+{
+       int ctx_index, api_index;
+
+       ctx_index = param->ctx_index;
+       api_index = param->api_index;
+       DEBUG("context index: %d\n", ctx_index);
+
+       switch (api_index) {
+               case CODEC_INIT:
+
+                       NEWCODEC_CURRENT_TIME
+
+                       newcodec_write_data(CODEC_CMD_FILE_INDEX,
+                                                               CODEC_CMD_CONTEXT_INDEX,
+                                                               file_index, ctx_index);
+               
+                       NEWCODEC_CURRENT_TIME
+
+//                     INFO("init context_flags[%d]: %d\n", ctx_index, context_flags[ctx_index]);
+
+//                     wait_event_interruptible(wait_queue, context_flags[ctx_index] != 0);
+//                     context_flags[ctx_index] = 0;
+                       break;
+               case CODEC_DECODE_VIDEO... CODEC_ENCODE_AUDIO:
+
+                       NEWCODEC_CURRENT_TIME
+
+                       newcodec_write_data(CODEC_CMD_FILE_INDEX,
+                                                               CODEC_CMD_CONTEXT_INDEX,
+                                                               file_index, ctx_index);
+
+                       if (api_index == CODEC_ENCODE_VIDEO) {
+                               // in case of medium and large size of data
+                               release_device_memory(param->mem_offset);
+                       } else {
+                               // in case of small size of data
+//                             INFO("release small size of data\n");
+                               release_s_device_memory(param->mem_offset);
+                       }
+#if 0
+                       INFO("video ~ audio. context_flags[%d]: %d\n", ctx_index, context_flags[ctx_index]);
+#endif
+                       wait_event_interruptible(wait_queue, context_flags[ctx_index] != 0);
+                       context_flags[ctx_index] = 0;
+                       break;
+               case CODEC_PICTURE_COPY:
+                       newcodec_write_data(CODEC_CMD_FILE_INDEX,
+                                                               CODEC_CMD_CONTEXT_INDEX,
+                                                               file_index, ctx_index);
+               wait_event_interruptible(wait_queue, context_flags[ctx_index] != 0);
+            context_flags[ctx_index] = 0;
+                       break;
+               case CODEC_DEINIT:
+                       newcodec_write_data(CODEC_CMD_FILE_INDEX,
+                                                               CODEC_CMD_CONTEXT_INDEX,
+                                                               file_index, ctx_index);
+
+                       context_flags[ctx_index] = 0;
+//                     INFO("deinit. reset context_flags[%d]: %d\n", ctx_index, context_flags[ctx_index]);
+                       break;
+               default:
+                       ERROR("undefined function index: %d", api_index);
+       }
+}
+
+
+#if 0
+static ssize_t newcodec_write(struct file *file, const char __user *buf, size_t count, loff_t *fops)
+{
+       struct codec_param ioparam = { 0 };
+
+       DEBUG("enter %s. %p\n", __func__, file);
+
+       if (!newcodec) {
+               ERROR("failed to get codec device info\n");
+               return -EINVAL;
+       }
+
+       if (copy_from_user(&ioparam, buf, sizeof(struct codec_param))) {
+               ERROR("failed to get codec parameter from user\n");
+               return -EIO;
+    }
+
+       newcodec_func(&ioparam, (uint32_t)file);
+
+       DEBUG("leave %s. %p\n", __func__, file);
+       return 0;
+}
+#endif
+
+#if 1
 /* Copy data between guest and host using mmap operation. */
 static ssize_t newcodec_write(struct file *file, const char __user *buf, size_t count, loff_t *fops)
 {
-       struct codec_param param_info;
-       int api_index;
+       struct codec_param ioparam = { 0 };
+       int api_index, ctx_index;
 
        if (!newcodec) {
-               printk(KERN_ERR "failed to get codec device info\n");
+               ERROR("failed to get codec device info\n");
                return -EINVAL;
        }
 
-       memset (&param_info, 0x00, sizeof(struct codec_param));
-       if (copy_from_user(&param_info, buf, sizeof(struct codec_param))) {
-               printk(KERN_ERR
-                       "failed to get codec parameter info from user\n");
+//     memset (&ioparam, 0x00, sizeof(struct codec_param));
+       if (copy_from_user(&ioparam, buf, sizeof(struct codec_param))) {
+               ERROR("failed to get codec parameter info from user\n");
                return -EIO;
     }
 
-       CODEC_LOG("enter %s. %p\n", __func__, file);
+       DEBUG("enter %s. %p\n", __func__, file);
+
+       api_index = ioparam.api_index;
+    ctx_index = ioparam.ctx_index;
 
-       api_index = param_info.api_index;
        switch (api_index) {
        case CODEC_INIT:
                {
-                       int ctx_index;
-
                        ENTER_CRITICAL_SECTION;
                        writel((uint32_t)file,
                                        newcodec->ioaddr + CODEC_CMD_FILE_INDEX);
-                       writel((uint32_t)param_info.mem_offset,
+                       writel((uint32_t)ioparam.mem_offset,
                                        newcodec->ioaddr + CODEC_CMD_DEVICE_MEM_OFFSET);
-#if 1
-                       writel((int32_t)param_info.ctx_index,
+                       writel((int32_t)ioparam.ctx_index,
                                        newcodec->ioaddr + CODEC_CMD_CONTEXT_INDEX);
-                       writel((int32_t)param_info.api_index,
+                       writel((int32_t)ioparam.api_index,
                                        newcodec->ioaddr + CODEC_CMD_API_INDEX);
-#endif
                        LEAVE_CRITICAL_SECTION;
 
-                       release_device_memory(param_info.mem_offset);
-
-            ctx_index = param_info.ctx_index;
-                       CODEC_LOG("context index: %d\n", ctx_index);
+//                     release_device_memory(ioparam.mem_offset);
+                       DEBUG("context index: %d\n", ctx_index);
 
                wait_event_interruptible(wait_queue, context_flags[ctx_index] != 0);
+
+                       DEBUG("wakeup. %d\n", ctx_index);
+
             context_flags[ctx_index] = 0;
                }
                        break;
                case CODEC_DECODE_VIDEO... CODEC_ENCODE_AUDIO:
                {
-            int ctx_index;
-
                        ENTER_CRITICAL_SECTION;
                        writel((uint32_t)file,
                                        newcodec->ioaddr + CODEC_CMD_FILE_INDEX);
-                       writel((uint32_t)param_info.mem_offset,
+                       writel((uint32_t)ioparam.mem_offset,
                                        newcodec->ioaddr + CODEC_CMD_DEVICE_MEM_OFFSET);
-#if 1
-                       writel((int32_t)param_info.ctx_index,
+                       writel((int32_t)ioparam.ctx_index,
                                        newcodec->ioaddr + CODEC_CMD_CONTEXT_INDEX);
-                       writel((int32_t)param_info.api_index,
+                       writel((int32_t)ioparam.api_index,
                                        newcodec->ioaddr + CODEC_CMD_API_INDEX);
-#endif
                        LEAVE_CRITICAL_SECTION;
 
-                       release_device_memory(param_info.mem_offset);
 
-            ctx_index = param_info.ctx_index;
+                       if (api_index == CODEC_ENCODE_VIDEO) {
+                               // in case of medium and large size of data
+                               release_device_memory(ioparam.mem_offset);
+                       } else {
+                               // in case of small size of data
+                               release_s_device_memory(ioparam.mem_offset);
+                       }
+
+//                     release_device_memory(ioparam.mem_offset);
+
                wait_event_interruptible(wait_queue, context_flags[ctx_index] != 0);
             context_flags[ctx_index] = 0;
                }
@@ -597,21 +1032,18 @@ static ssize_t newcodec_write(struct file *file, const char __user *buf, size_t
 
                case CODEC_PICTURE_COPY:
                {
-                       int ctx_index;
-
                        ENTER_CRITICAL_SECTION;
                        writel((uint32_t)file,
                                        newcodec->ioaddr + CODEC_CMD_FILE_INDEX);
-                       writel((uint32_t)param_info.mem_offset,
+                       writel((uint32_t)ioparam.mem_offset,
                                        newcodec->ioaddr + CODEC_CMD_DEVICE_MEM_OFFSET);
-                       writel((int32_t)param_info.ctx_index,
+                       writel((int32_t)ioparam.ctx_index,
                                        newcodec->ioaddr + CODEC_CMD_CONTEXT_INDEX);
-                       writel((int32_t)param_info.api_index,
+                       writel((int32_t)ioparam.api_index,
                                        newcodec->ioaddr + CODEC_CMD_API_INDEX);
                        LEAVE_CRITICAL_SECTION;
 
-            ctx_index = param_info.ctx_index;
-               wait_event_interruptible(wait_queue, context_flags[ctx_index] != 0);
+               wait_event_interruptible(wait_queue, context_flags[ctx_index] != 0);
             context_flags[ctx_index] = 0;
                }
                        break;
@@ -620,20 +1052,21 @@ static ssize_t newcodec_write(struct file *file, const char __user *buf, size_t
                        ENTER_CRITICAL_SECTION;
                        writel((uint32_t)file,
                                        newcodec->ioaddr + CODEC_CMD_FILE_INDEX);
-//                     writel((uint32_t)param_info.mem_offset,
+//                     writel((uint32_t)ioparam.mem_offset,
 //                                     newcodec->ioaddr + CODEC_CMD_DEVICE_MEM_OFFSET);
-                       writel((int32_t)param_info.ctx_index,
+                       writel((int32_t)ioparam.ctx_index,
                                        newcodec->ioaddr + CODEC_CMD_CONTEXT_INDEX);
-                       writel((int32_t)param_info.api_index,
+                       writel((int32_t)ioparam.api_index,
                                        newcodec->ioaddr + CODEC_CMD_API_INDEX);
                        LEAVE_CRITICAL_SECTION;
                        break;
                default:
-                       printk(KERN_ERR "wrong api command: %d", api_index);
+                       ERROR("wrong api command: %d", api_index);
        }
 
        return 0;
 }
+#endif
 
 static int newcodec_mmap(struct file *file, struct vm_area_struct *vm)
 {
@@ -644,7 +1077,7 @@ static int newcodec_mmap(struct file *file, struct vm_area_struct *vm)
 
        size = vm->vm_end - vm->vm_start;
        if (size > newcodec->mem_size) {
-               printk(KERN_ERR "over mapping size\n");
+               ERROR("over mapping size\n");
                return -EINVAL;
        }
        off = vm->vm_pgoff << PAGE_SHIFT;
@@ -653,7 +1086,7 @@ static int newcodec_mmap(struct file *file, struct vm_area_struct *vm)
        ret = remap_pfn_range(vm, vm->vm_start, phys_addr,
                        size, vm->vm_page_prot);
        if (ret < 0) {
-               printk(KERN_ERR "failed to remap page range\n");
+               ERROR("failed to remap page range\n");
                return -EAGAIN;
        }
 
@@ -676,7 +1109,8 @@ static irqreturn_t newcodec_irq_handler(int irq, void *dev_id)
 
        spin_lock_irqsave(&dev->lock, flags);
 
-       CODEC_LOG("handle an interrupt from codec device.\n");
+       DEBUG("handle an interrupt from codec device.\n");
+       NEWCODEC_CURRENT_TIME
        newcodec_bh(dev);
 
        spin_unlock_irqrestore(&dev->lock, flags);
@@ -686,12 +1120,12 @@ static irqreturn_t newcodec_irq_handler(int irq, void *dev_id)
 
 static int newcodec_open(struct inode *inode, struct file *file)
 {
-       CODEC_LOG("open! struct file:%p\n", file);
+       DEBUG("open! struct file:%p\n", file);
 
        /* register interrupt handler */
        if (request_irq(newcodec->dev->irq, newcodec_irq_handler,
                IRQF_SHARED, DEVICE_NAME, newcodec)) {
-               printk(KERN_ERR "failed to register irq handle\n");
+               ERROR("failed to register irq handle\n");
                return -EBUSY;
        }
 
@@ -704,12 +1138,13 @@ static int newcodec_release(struct inode *inode, struct file *file)
 {
        /* free irq */
        if (newcodec->dev->irq) {
-               CODEC_LOG("free registered irq\n");
+               DEBUG("free registered irq\n");
                free_irq(newcodec->dev->irq, newcodec);
        }
 
-       CODEC_LOG("%s. file: %p\n", __func__, file);
+       DEBUG("%s. file: %p\n", __func__, file);
 
+#if 0
        /* free resource */
        {
                struct device_mem *elem = NULL;
@@ -721,7 +1156,7 @@ static int newcodec_release(struct inode *inode, struct file *file)
                        list_for_each_safe(pos, temp, &newcodec->used_memblk) {
                                elem = list_entry(pos, struct device_mem, entry);
                                if (elem->blk_id == (uint32_t)file) {
-                                       CODEC_LOG("move element(%p) to available memory block.\n", elem);
+                                       DEBUG("move element(%p) to available memory block.\n", elem);
 
                                        elem->blk_id = 0;
                                        elem->occupied = false;
@@ -731,11 +1166,40 @@ static int newcodec_release(struct inode *inode, struct file *file)
                                }
                        }
                } else {
-                       CODEC_LOG("there is no used memory block.\n");
+                       DEBUG("there is no used memory block.\n");
                }
 
                mutex_unlock(&newcodec_blk_mutex);
        }
+#endif
+
+       /* free resource */
+       {
+               struct device_mem *elem = NULL;
+               struct list_head *pos, *temp;
+
+               mutex_lock(&s_block_mutex);
+
+               if (!list_empty(&newcodec->used_s_memblk)) {
+                       list_for_each_safe(pos, temp, &newcodec->used_s_memblk) {
+                               elem = list_entry(pos, struct device_mem, entry);
+                               if (elem->blk_id == (uint32_t)file) {
+                                       DEBUG("move element(%p) to available memory block.\n", elem);
+
+                                       elem->blk_id = 0;
+                                       elem->occupied = false;
+                                       list_move_tail(&elem->entry, &newcodec->avail_s_memblk);
+
+                                       up(&s_buffer_sema);
+                               }
+                       }
+               } else {
+                       DEBUG("there is no used memory block.\n");
+               }
+
+               mutex_unlock(&s_block_mutex);
+       }
+
 
        /* notify closing codec device of qemu. */
        if (file) {
@@ -773,7 +1237,7 @@ static void newcodec_get_device_version(void)
        newcodec->version =
                readl(newcodec->ioaddr + CODEC_CMD_GET_VERSION);
 
-       printk(KERN_INFO "codec device version: %d\n",
+       INFO("device version: %d\n",
                newcodec->version);
 }
 
@@ -782,11 +1246,11 @@ static int __devinit newcodec_probe(struct pci_dev *pci_dev,
 {
        int ret = 0;
 
-       printk(KERN_INFO "%s: driver is probed.\n", DEVICE_NAME);
+       INFO("%s: driver is probed.\n", DEVICE_NAME);
 
        newcodec = kzalloc(sizeof(struct newcodec_device), GFP_KERNEL);
        if (!newcodec) {
-               printk(KERN_ERR "Failed to allocate memory for codec.\n");
+               ERROR("Failed to allocate memory for codec.\n");
                return -ENOMEM;
        }
 
@@ -795,28 +1259,38 @@ static int __devinit newcodec_probe(struct pci_dev *pci_dev,
        INIT_LIST_HEAD(&newcodec->avail_memblk);
        INIT_LIST_HEAD(&newcodec->used_memblk);
 
+       INIT_LIST_HEAD(&newcodec->avail_s_memblk);
+       INIT_LIST_HEAD(&newcodec->used_s_memblk);
+       INIT_LIST_HEAD(&newcodec->avail_m_memblk);
+       INIT_LIST_HEAD(&newcodec->used_m_memblk);
+       INIT_LIST_HEAD(&newcodec->avail_l_memblk);
+       INIT_LIST_HEAD(&newcodec->used_l_memblk);
+
+#if 0
        {
                struct device_mem *elem = NULL;
                int index;
 
                elem =
-                       kzalloc(sizeof(struct device_mem) * CODEC_DEVICE_MEM_COUNT, GFP_KERNEL);
+                       kzalloc(sizeof(struct device_mem) * DEVICE_MEMORY_COUNT, GFP_KERNEL);
                if (!elem) {
-                       printk(KERN_ERR "Falied to allocate memory!!\n");
+                       ERROR("Falied to allocate memory!!\n");
                        return -ENOMEM;
                }
 
-               for (index = 0; index < CODEC_DEVICE_MEM_COUNT; index++) {
+               for (index = 0; index < DEVICE_MEMORY_COUNT; index++) {
                        elem[index].mem_offset = index * 0x200000;
                        elem[index].occupied = false;
                        list_add_tail(&elem[index].entry, &newcodec->avail_memblk);
                }
        }
+#endif
+       newcodec_divide_device_memory();
 
        spin_lock_init(&newcodec->lock);
 
        if ((ret = pci_enable_device(pci_dev))) {
-               printk(KERN_ERR "pci_enable_device failed\n");
+               ERROR("pci_enable_device failed\n");
                return ret;
        }
        pci_set_master(pci_dev);
@@ -824,7 +1298,7 @@ static int __devinit newcodec_probe(struct pci_dev *pci_dev,
        newcodec->mem_start = pci_resource_start(pci_dev, 0);
        newcodec->mem_size = pci_resource_len(pci_dev, 0);
        if (!newcodec->mem_start) {
-               printk(KERN_ERR "pci_resource_start failed\n");
+               ERROR("pci_resource_start failed\n");
                pci_disable_device(pci_dev);
                return -ENODEV;
        }
@@ -832,7 +1306,7 @@ static int __devinit newcodec_probe(struct pci_dev *pci_dev,
        if (!request_mem_region(newcodec->mem_start,
                                newcodec->mem_size,
                                DEVICE_NAME)) {
-               printk(KERN_ERR "request_mem_region failed\n");
+               ERROR("request_mem_region failed\n");
                pci_disable_device(pci_dev);
                return -EINVAL;
        }
@@ -840,7 +1314,7 @@ static int __devinit newcodec_probe(struct pci_dev *pci_dev,
        newcodec->io_start = pci_resource_start(pci_dev, 1);
        newcodec->io_size = pci_resource_len(pci_dev, 1);
        if (!newcodec->io_start) {
-               printk(KERN_ERR "pci_resource_start failed\n");
+               ERROR("pci_resource_start failed\n");
                release_mem_region(newcodec->mem_start, newcodec->mem_size);
                pci_disable_device(pci_dev);
                return -ENODEV;
@@ -849,7 +1323,7 @@ static int __devinit newcodec_probe(struct pci_dev *pci_dev,
        if (!request_mem_region(newcodec->io_start,
                                newcodec->io_size,
                                DEVICE_NAME)) {
-               printk(KERN_ERR "request_io_region failed\n");
+               ERROR("request_io_region failed\n");
                release_mem_region(newcodec->mem_start, newcodec->mem_size);
                pci_disable_device(pci_dev);
                return -EINVAL;
@@ -857,7 +1331,7 @@ static int __devinit newcodec_probe(struct pci_dev *pci_dev,
 
        newcodec->ioaddr = ioremap_nocache(newcodec->io_start, newcodec->io_size);
        if (!newcodec->ioaddr) {
-               printk(KERN_ERR "ioremap failed\n");
+               ERROR("ioremap failed\n");
                release_mem_region(newcodec->io_start, newcodec->io_size);
                release_mem_region(newcodec->mem_start, newcodec->mem_size);
                pci_disable_device(pci_dev);
@@ -867,7 +1341,7 @@ static int __devinit newcodec_probe(struct pci_dev *pci_dev,
        newcodec_get_device_version();
 
        if ((ret = misc_register(&codec_dev))) {
-               printk(KERN_ERR "cannot register codec as misc\n");
+               ERROR("cannot register codec as misc\n");
                iounmap(newcodec->ioaddr);
                release_mem_region(newcodec->io_start, newcodec->io_size);
                release_mem_region(newcodec->mem_start, newcodec->mem_size);
@@ -925,11 +1399,11 @@ static struct pci_driver driver = {
 
 static int __init newcodec_init(void)
 {
-       printk(KERN_INFO "%s: driver is initialized.\n", DEVICE_NAME);
+       INFO("driver is initialized.\n");
 
        newcodec_bh_workqueue = create_workqueue ("newcodec");
        if (!newcodec_bh_workqueue) {
-               printk(KERN_ERR "failed to allocate workqueue\n");
+               ERROR("failed to allocate workqueue\n");
                return -ENOMEM;
        }
 
@@ -938,7 +1412,7 @@ static int __init newcodec_init(void)
 
 static void __exit newcodec_exit(void)
 {
-       printk(KERN_INFO "device is finalized.\n");
+       INFO("driver is finalized.\n");
 
        if (newcodec_bh_workqueue) {
                destroy_workqueue (newcodec_bh_workqueue);