[Title] Upgrade codec module as async i/o and modify source according to coding conve...
authorKitae Kim <kt920.kim@samsung.com>
Wed, 8 Aug 2012 06:24:41 +0000 (15:24 +0900)
committerKitae Kim <kt920.kim@samsung.com>
Wed, 8 Aug 2012 06:24:41 +0000 (15:24 +0900)
[Type] enhancement
[Module] emulator / codec
[Priority] major
[CQ#]
[Redmine#] Interal Issue.
[Problem] While testing HTML5 VideoTag, emulator could be locked up.
[Cause] sychronous i/o and use fixed offset for mapped memory.
[Solution] async i/o and flexible offset.
[TestCase]

drivers/maru/maru_codec.c

index ade6dd73a1fd9382f1f24b4ab8fd915510f3b54f..a3bb2bdfc625cf48f26c705f3021b55e8b7e03dd 100644 (file)
  * - S-Core Co., Ltd
  *
  */
-
-#include <linux/init.h>
-#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/fs.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
 #include <linux/kernel.h>
-#include <linux/device.h>
+#include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/err.h>
 #include <linux/types.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
+#include <linux/sched.h>
 #include <linux/semaphore.h>
 #include <linux/workqueue.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#define DRIVER_NAME     "codec"
-#define CODEC_MAJOR     240
+#define DRIVER_NAME     "codec"
+#define CODEC_MAJOR     240
 
 MODULE_DESCRIPTION("Virtual Codec Device Driver");
 MODULE_AUTHOR("Kitae KIM <kt920.kim@samsung.com");
 MODULE_LICENSE("GPL2");
 
-#define USABLE_MMAP_MAX_SIZE    4
-#define CODEC_ERR_LOG(fmt, ...) \
-       printk(KERN_ERR "%s: " fmt, DRIVER_NAME, ##__VA_ARGS__)
+#define USABLE_MMAP_MAX_SIZE   20
+#define CODEC_LOG(log_level, fmt, ...) \
+       printk(log_level "%s: " fmt, DRIVER_NAME, ##__VA_ARGS__)
+
+#define CODEC_IRQ 0x7f
 
+/* Clean up source. : _param, svcodec_param_offset, paramindex */
 
-struct _param {
-    uint32_t apiIndex;
-    uint32_t ctxIndex;
-    uint32_t mmapOffset;
-    uint32_t inArgsNum;
-    uint32_t inArgs[20];
-    uint32_t ret;
+struct codec_param {
+       uint32_t apiIndex;
+       uint32_t ctxIndex;
+       uint32_t mmapOffset;
+       uint32_t ret;
 };
 
-enum svodec_param_offset {
-    CODEC_API_INDEX = 0,
-    CODEC_IN_PARAM,
-    CODEC_RETURN_VALUE,
-    CODEC_CONTEXT_INDEX,
-    CODEC_MMAP_OFFSET,
-    CODEC_FILE_INDEX,
-    CODEC_CLOSED,
+enum codec_io_cmd {
+       CODEC_API_INDEX = 0,
+       CODEC_QUERY_STATE,
+       CODEC_CONTEXT_INDEX,
+       CODEC_MMAP_OFFSET,
+       CODEC_FILE_INDEX,
+       CODEC_CLOSED,
 };
 
-enum svcodec_param_apiindex {
-    EMUL_AV_REGISTER_ALL = 1,
-    EMUL_AVCODEC_ALLOC_CONTEXT,
-    EMUL_AVCODEC_ALLOC_FRAME,
-    EMUL_AVCODEC_OPEN,
-    EMUL_AVCODEC_CLOSE,
-    EMUL_AV_FREE_CONTEXT,
-    EMUL_AV_FREE_PICTURE,
-    EMUL_AV_FREE_PALCTRL,
-    EMUL_AV_FREE_EXTRADATA,
-    EMUL_AVCODEC_FLUSH_BUFFERS,
-    EMUL_AVCODEC_DECODE_VIDEO,
-    EMUL_AVCODEC_ENCODE_VIDEO,
-    EMUL_AVCODEC_DECODE_AUDIO,
-    EMUL_AVCODEC_ENCODE_AUDIO,
-    EMUL_AV_PICTURE_COPY,
-    EMUL_AV_PARSER_INIT,
-    EMUL_AV_PARSER_PARSE,
-    EMUL_AV_PARSER_CLOSE,
-    EMUL_GET_MMAP_INDEX,
-    EMUL_GET_CODEC_VER = 50,
+enum codec_api_index {
+       EMUL_AV_REGISTER_ALL = 1,
+       EMUL_AVCODEC_ALLOC_CONTEXT,
+       EMUL_AVCODEC_ALLOC_FRAME,
+       EMUL_AVCODEC_OPEN,
+       EMUL_AVCODEC_CLOSE,
+       EMUL_AV_FREE,
+       EMUL_AVCODEC_FLUSH_BUFFERS,
+       EMUL_AVCODEC_DECODE_VIDEO,
+       EMUL_AVCODEC_ENCODE_VIDEO,
+       EMUL_AVCODEC_DECODE_AUDIO,
+       EMUL_AVCODEC_ENCODE_AUDIO,
+       EMUL_AV_PICTURE_COPY,
+       EMUL_AV_PARSER_INIT,
+       EMUL_AV_PARSER_PARSE,
+       EMUL_AV_PARSER_CLOSE,
+       EMUL_GET_MMAP_INDEX,
+       EMUL_GET_CODEC_VER = 50,
 };
 
-typedef struct _svcodec_dev {
-    struct pci_dev *dev;
+struct svcodec_device {
+       struct pci_dev *dev;
+
+       /* I/O and Memory Region */
+       unsigned int *ioaddr;
+       unsigned int *memaddr;
 
-    volatile unsigned int *ioaddr;
-    volatile unsigned int *memaddr;
+       resource_size_t io_start;
+       resource_size_t io_size;
+       resource_size_t mem_start;
+       resource_size_t mem_size;
 
-    resource_size_t io_start;
-    resource_size_t io_size;
-    resource_size_t mem_start;
-    resource_size_t mem_size;
+       /* irq handler */
+       wait_queue_head_t codec_wq;
+       spinlock_t lock;
+       int sleep_flag;
 
-    uint8_t useMmap[USABLE_MMAP_MAX_SIZE + 1];
-} svcodec_dev;
+       uint8_t useMmap[USABLE_MMAP_MAX_SIZE + 1];
+};
 
-static svcodec_dev *svcodec;
+static struct svcodec_device *svcodec;
 DEFINE_MUTEX(codec_mutex);
 
-static struct pci_device_id svcodec_pci_table[] __devinitdata = {
-    {
-    .vendor     = PCI_VENDOR_ID_TIZEN,
-    .device     = PCI_DEVICE_ID_VIRTUAL_CODEC,
-    .subvendor  = PCI_ANY_ID,
-    .subdevice  = PCI_ANY_ID,
-    },
-};
-MODULE_DEVICE_TABLE(pci, svcodec_pci_table);
+static ssize_t svcodec_read(struct file *file, char __user *buf,
+                       size_t count, loff_t *fops)
+{
+       CODEC_LOG(KERN_INFO, "do nothing in the read operation.\n");
+       return 0;
+}
 
 /* Another way to copy data between guest and host. */
 /* Copy data between guest and host using mmap operation. */
 static ssize_t svcodec_write (struct file *file, const char __user *buf,
-                              size_t count, loff_t *fops)
+                       size_t count, loff_t *fops)
 {
-    struct _param paramInfo;
-
-    mutex_lock(&codec_mutex);
-
-    if (!svcodec) {
-        CODEC_ERR_LOG("fail to get codec device info\n");
-        return -EINVAL;
-    }
-
-    if (copy_from_user(&paramInfo, buf, sizeof(struct _param))) {
-        CODEC_ERR_LOG("fail to get codec parameter info from user\n");
-    }
-
-    if (paramInfo.apiIndex == EMUL_GET_MMAP_INDEX) {
-        int i = 0;
-        int max_size = USABLE_MMAP_MAX_SIZE;
-        int *mmapIndex = (int*)paramInfo.ret;
-        uint8_t *useMmapSize = &svcodec->useMmap[max_size];
-
-        printk(KERN_DEBUG "%s: before available useMmap count:%d\n", DRIVER_NAME, (max_size - *useMmapSize));
-
-        for (; i < max_size; i++) {
-            if (svcodec->useMmap[i] == 1) {
-                svcodec->useMmap[i] = 0;
-                (*useMmapSize)++;
-                file->private_data = &svcodec->useMmap[i];
-                printk(KERN_DEBUG "%s: useMmap[%d]=%d\n", DRIVER_NAME, i, svcodec->useMmap[i]);
-                printk(KERN_DEBUG "%s: file:%p private_data:%p\n", DRIVER_NAME, file, file->private_data);
-                printk(KERN_DEBUG "%s: after available useMmap count:%d\n", DRIVER_NAME, (max_size - *useMmapSize));
-                printk(KERN_DEBUG "%s: return %d as the index of mmap\n", DRIVER_NAME, i);
-                break;
-            }
-        }
-
-        if (i == max_size) {
-            printk(KERN_DEBUG "%s: Usable mmap is none! struct file:%p\n", DRIVER_NAME, file);
-            i = -1;
-        }
-
-        if (copy_to_user((void*)mmapIndex, &i, sizeof(int))) {
-            printk(KERN_ERR "%s: fail to copy the index value to user.\n", DRIVER_NAME);
-        }
-        mutex_unlock(&codec_mutex);
-
-        return 0;
-    }
-
-    if (paramInfo.apiIndex == EMUL_AVCODEC_ALLOC_CONTEXT) {
-        writel((uint32_t)file, svcodec->ioaddr + CODEC_FILE_INDEX);
-    }
-
-    writel((uint32_t)paramInfo.ctxIndex, svcodec->ioaddr + CODEC_CONTEXT_INDEX);
-    writel((uint32_t)paramInfo.mmapOffset, svcodec->ioaddr + CODEC_MMAP_OFFSET);
-    writel((uint32_t)paramInfo.apiIndex, svcodec->ioaddr + CODEC_API_INDEX);
-
-    mutex_unlock(&codec_mutex);
-     
-    return 0;
+       struct codec_param paramInfo;
+
+       mutex_lock(&codec_mutex);
+
+       if (!svcodec) {
+               CODEC_LOG(KERN_ERR, "failed to get codec device info\n");
+               return -EINVAL;
+       }
+
+       if (copy_from_user(&paramInfo, buf, sizeof(struct codec_param)))
+               CODEC_LOG(KERN_ERR,
+                       "failed to get codec parameter info from user\n");
+
+
+       if (paramInfo.apiIndex == EMUL_GET_MMAP_INDEX) {
+               int i = 0;
+               int max_size = USABLE_MMAP_MAX_SIZE;
+               int *mmapIndex = (int *)paramInfo.ret;
+               uint8_t *useMmapSize = &svcodec->useMmap[max_size];
+
+               CODEC_LOG(KERN_DEBUG, "before available useMmap count:%d\n",
+                       (max_size - *useMmapSize));
+
+       for (; i < max_size; i++) {
+               if (svcodec->useMmap[i] == 1) {
+                       svcodec->useMmap[i] = 0;
+                       (*useMmapSize)++;
+                       file->private_data = &svcodec->useMmap[i];
+                       CODEC_LOG(KERN_DEBUG,
+                               "useMmap[%d]=%d\n", i, svcodec->useMmap[i]);
+                       CODEC_LOG(KERN_DEBUG,
+                               "file:%p private_data:%p\n",
+                               file, file->private_data);
+                       CODEC_LOG(KERN_DEBUG,
+                               "after available useMmap count:%d\n",
+                               (max_size - *useMmapSize));
+                       CODEC_LOG(KERN_DEBUG,
+                               "return %d as the index of mmap\n", i);
+                       break;
+               }
+       }
+
+       if (i == max_size) {
+               CODEC_LOG(KERN_DEBUG,
+                       "Usable mmap is none! struct file:%p\n", file);
+               i = -1;
+       }
+
+       if (copy_to_user((void *)mmapIndex, &i, sizeof(int)))
+               CODEC_LOG(KERN_ERR,
+                       "failed to copy the index value to user.\n");
+               mutex_unlock(&codec_mutex);
+               return 0;
+       }
+
+       if (paramInfo.apiIndex == EMUL_AVCODEC_ALLOC_CONTEXT)
+               writel((uint32_t)file, svcodec->ioaddr + CODEC_FILE_INDEX);
+
+       writel((uint32_t)paramInfo.ctxIndex,
+               svcodec->ioaddr + CODEC_CONTEXT_INDEX);
+       writel((uint32_t)paramInfo.mmapOffset,
+               svcodec->ioaddr + CODEC_MMAP_OFFSET);
+       writel((uint32_t)paramInfo.apiIndex,
+               svcodec->ioaddr + CODEC_API_INDEX);
+
+       /* wait decoding or encoding job */
+       if (paramInfo.apiIndex >= EMUL_AVCODEC_DECODE_VIDEO &&
+               paramInfo.apiIndex <= EMUL_AVCODEC_ENCODE_AUDIO) {
+               wait_event_interruptible(svcodec->codec_wq,
+                                       svcodec->sleep_flag != 0);
+               svcodec->sleep_flag = 0;
+       }
+
+       mutex_unlock(&codec_mutex);
+
+       return 0;
 }
 
-static ssize_t svcodec_read (struct file *file, char __user *buf,
-                             size_t count, loff_t *fops)
+static int svcodec_mmap(struct file *file, struct vm_area_struct *vm)
 {
-    printk(KERN_INFO "%s: do nothing in the read operation \n", DRIVER_NAME);
-    return 0;
+       unsigned long off;
+       unsigned long phys_addr;
+       unsigned long size;
+       int ret = -1;
+
+       off = vm->vm_pgoff << PAGE_SHIFT;
+       phys_addr = (PAGE_ALIGN(svcodec->mem_start) + off) >> PAGE_SHIFT;
+       size = vm->vm_end - vm->vm_start;
+
+       if (size > svcodec->mem_size) {
+               CODEC_LOG(KERN_ERR, "over mapping size\n");
+               return -EINVAL;
+       }
+
+       ret = remap_pfn_range(vm, vm->vm_start, phys_addr,
+                       size, vm->vm_page_prot);
+       if (ret < 0) {
+               CODEC_LOG(KERN_ERR, "failed to remap page range\n");
+               return -EAGAIN;
+       }
+
+       vm->vm_flags |= VM_IO;
+       vm->vm_flags |= VM_RESERVED;
+
+       return 0;
 }
 
-static int svcodec_mmap (struct file *file, struct vm_area_struct *vm)
+static irqreturn_t svcodec_irq_handler (int irq, void *dev_id)
 {
-    unsigned long off;
-    unsigned long phys_addr;
-    unsigned long size;
-    int ret = -1;
-
-    off = vm->vm_pgoff << PAGE_SHIFT;
-    phys_addr = (PAGE_ALIGN(svcodec->mem_start) + off) >> PAGE_SHIFT;
-    size = vm->vm_end - vm->vm_start;
-
-    if (size > svcodec->mem_size) {
-        CODEC_ERR_LOG("over mapping size\n");
-        return -EINVAL;
-    }
-
-    ret = remap_pfn_range(vm, vm->vm_start, phys_addr, size, vm->vm_page_prot);
-    if (ret < 0) {
-        CODEC_ERR_LOG("failed to remap page range\n");
-        return -EAGAIN;
-    }
-
-    vm->vm_flags |= VM_IO;
-    vm->vm_flags |= VM_RESERVED;
-
-    return 0;
-}
+       struct svcodec_device *dev = (struct svcodec_device *)dev_id;
+       int val = 0;
+       unsigned long flags;
 
-static int svcodec_open (struct inode *inode, struct file *file)
-{
-    int i;
-    int max_size = USABLE_MMAP_MAX_SIZE;
+       val = readl(dev->ioaddr + CODEC_QUERY_STATE);
+       if (!(val & CODEC_IRQ)) {
+               CODEC_LOG(KERN_DEBUG, "this irq is not for this module.\n");
+               return IRQ_NONE;
+       }
+
+       spin_lock_irqsave(&dev->lock, flags);
 
-    mutex_lock(&codec_mutex);
+       CODEC_LOG(KERN_DEBUG, "irq is for this module.\n");
+       writel(0, dev->ioaddr + CODEC_QUERY_STATE);
 
-    printk(KERN_DEBUG "%s: open! struct file:%p\n", DRIVER_NAME, file);
-    if (svcodec->useMmap[max_size] == 0) {
-        for (i = 0; i < max_size; i++) {
-            svcodec->useMmap[i] = 1;
-            printk(KERN_DEBUG "%s: reset useMmap[%d]=%d\n", DRIVER_NAME, i, svcodec->useMmap[i]);
-        }
-    }
+       spin_lock_irqsave(&dev->lock, flags);
 
-    try_module_get(THIS_MODULE);
-    mutex_unlock(&codec_mutex);
+       dev->sleep_flag = 1;
+       wake_up_interruptible(&dev->codec_wq);
 
-    return 0;
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+static int svcodec_open(struct inode *inode, struct file *file)
+{
+       int i, max_size = USABLE_MMAP_MAX_SIZE;
+
+       mutex_lock(&codec_mutex);
+       CODEC_LOG(KERN_DEBUG, "open! struct file:%p\n", file);
+
+       svcodec->sleep_flag = 0;
+
+       CODEC_LOG(KERN_DEBUG, "register irq handler\n");
+       /* register interrupt handler */
+       if (request_irq(svcodec->dev->irq, svcodec_irq_handler,
+               IRQF_SHARED, DRIVER_NAME, svcodec)) {
+               CODEC_LOG(KERN_ERR, "failed to register irq handle\n");
+               return -EBUSY;
+       }
+
+       /* reset useMmap array */
+       if (svcodec->useMmap[max_size] == 0) {
+               for (i = 0; i < max_size; i++) {
+                       svcodec->useMmap[i] = 1;
+                       CODEC_LOG(KERN_DEBUG, "reset useMmap[%d]=%d\n",
+                               i, svcodec->useMmap[i]);
+               }
+       }
+
+       try_module_get(THIS_MODULE);
+       mutex_unlock(&codec_mutex);
+
+       return 0;
 }
 
 static int svcodec_release (struct inode *inode, struct file *file)
 {
-    int max_size = USABLE_MMAP_MAX_SIZE;
-    uint8_t *useMmap;
+       int max_size = USABLE_MMAP_MAX_SIZE;
+       uint8_t *useMmap;
+
+       mutex_lock(&codec_mutex);
 
-    mutex_lock(&codec_mutex);
+       /* free irq */
+       if (svcodec->dev->irq) {
+               CODEC_LOG(KERN_DEBUG, "free registered irq\n");
+               free_irq(svcodec->dev->irq, svcodec);
+       }
 
-    useMmap  = (uint8_t*)file->private_data;
-    printk(KERN_DEBUG "%s: close!! struct file:%p, priv_data:%p\n", DRIVER_NAME, file, useMmap);
+       /* manage codec context */
+       useMmap  = (uint8_t *)file->private_data;
+       CODEC_LOG(KERN_DEBUG,
+               "close! struct file:%p, priv_data:%p\n", file, useMmap);
 
-    if (file && file->private_data) {
-        if (svcodec->useMmap[max_size] > 0) {
-            (svcodec->useMmap[max_size])--;
-        }
-        *useMmap = 1;
-        printk(KERN_DEBUG "%s: available useMmap count:%d\n",
-                DRIVER_NAME, (max_size - svcodec->useMmap[max_size]));
+       if (file && file->private_data) {
+               if (svcodec->useMmap[max_size] > 0)
+                       (svcodec->useMmap[max_size])--;
+               *useMmap = 1;
+               CODEC_LOG(KERN_DEBUG, "available useMmap count:%d\n",
+                       (max_size - svcodec->useMmap[max_size]));
 
-        /* notify closing codec device of qemu. */
-        writel((uint32_t)file, svcodec->ioaddr + CODEC_CLOSED);
-    }
+               /* notify closing codec device of qemu. */
+               writel((uint32_t)file, svcodec->ioaddr + CODEC_CLOSED);
+       }
 
 #ifdef CODEC_DEBUG
-    int i;
-    for (i = 0; i < max_size; i++) {
-        printk(KERN_DEBUG "%s: useMmap[%d]=%d\n", DRIVER_NAME, i, svcodec->useMmap[i]);
-    }
+       int i;
+       for (i = 0; i < max_size; i++)
+               CODEC_LOG(KERN_DEBUG, "useMmap[%d]=%d\n",
+                       i, svcodec->useMmap[i]);
 #endif
-    module_put(THIS_MODULE);
-    mutex_unlock(&codec_mutex);
+       module_put(THIS_MODULE);
+       mutex_unlock(&codec_mutex);
 
-    return 0;
+       return 0;
 }
 
+/* define file opertion for CODEC */
 struct file_operations svcodec_fops = {
-    .owner      = THIS_MODULE,
-    .read       = svcodec_read,
-    .write      = svcodec_write,
-    .open       = svcodec_open,
-    .mmap       = svcodec_mmap,
-    .release    = svcodec_release,
+       .owner   = THIS_MODULE,
+       .read    = svcodec_read,
+       .write   = svcodec_write,
+       .open    = svcodec_open,
+       .mmap    = svcodec_mmap,
+       .release = svcodec_release,
 };
 
-static void __devinit svcodec_remove (struct pci_dev *pci_dev)
+static int __devinit svcodec_probe(struct pci_dev *pci_dev,
+       const struct pci_device_id *pci_id)
 {
-    if (svcodec) {
-        if (svcodec->ioaddr) {
-            iounmap(svcodec->ioaddr);
-            svcodec->ioaddr = 0;
-        }
-
-#if 0
-        if (svcodec->memaddr) {
-            iounmap(svcodec->memaddr);
-            svcodec->memaddr = 0;
-        }
-#endif
-
-        if (svcodec->io_start) {
-            release_mem_region(svcodec->io_start, svcodec->io_size);
-            svcodec->io_start = 0;
-        }
+       svcodec = kmalloc(sizeof(struct svcodec_device), GFP_KERNEL);
+       memset(svcodec, 0x00, sizeof(struct svcodec_device));
 
-        if (svcodec->mem_start) {
-            release_mem_region(svcodec->mem_start, svcodec->mem_size);
-            svcodec->mem_start = 0;
-        }
+       init_waitqueue_head(&svcodec->codec_wq);
+       spin_lock_init(&svcodec->lock);
 
-        kfree(svcodec);
-    }
-    pci_disable_device(pci_dev);
-}
-
-static int __devinit svcodec_probe (struct pci_dev *pci_dev,
-                                    const struct pci_device_id *pci_id)
-{
-    svcodec = (svcodec_dev*)kmalloc(sizeof(svcodec_dev), GFP_KERNEL);
-    memset(svcodec, 0x00, sizeof(svcodec_dev));
+       svcodec->dev = pci_dev;
 
-    svcodec->dev = pci_dev;
+       if (pci_enable_device(pci_dev)) {
+               CODEC_LOG(KERN_ERR, "pci_enable_device failed\n");
+               goto err_rel;
+       }
 
-    if (pci_enable_device(pci_dev)) {
-        CODEC_ERR_LOG("pci_enable_device failed\n");
-        goto err_rel;
-    }
+       pci_set_master(pci_dev);
 
-    pci_set_master(pci_dev);
+       svcodec->mem_start = pci_resource_start(pci_dev, 0);
+       svcodec->mem_size = pci_resource_len(pci_dev, 0);
 
-    svcodec->mem_start = pci_resource_start(pci_dev, 0);
-    svcodec->mem_size = pci_resource_len(pci_dev, 0);
+       if (!svcodec->mem_start) {
+               CODEC_LOG(KERN_ERR, "pci_resource_start failed\n");
+               goto err_out;
+       }
 
-    if (!svcodec->mem_start) {
-        CODEC_ERR_LOG("pci_resource_start failed\n");
-        goto err_out;
-    }
-    
-    if (!request_mem_region(svcodec->mem_start, svcodec->mem_size, DRIVER_NAME)) {
-        CODEC_ERR_LOG("request_mem_region failed\n");
-        goto err_out;
-    }
+       if (!request_mem_region(svcodec->mem_start,
+                               svcodec->mem_size,
+                               DRIVER_NAME)) {
+               CODEC_LOG(KERN_ERR, "request_mem_region failed\n");
+               goto err_out;
+       }
 
-    svcodec->io_start = pci_resource_start(pci_dev, 1);
-    svcodec->io_size = pci_resource_len(pci_dev, 1);
+       svcodec->io_start = pci_resource_start(pci_dev, 1);
+       svcodec->io_size = pci_resource_len(pci_dev, 1);
 
-    if (!svcodec->io_start) {
-        CODEC_ERR_LOG("pci_resource_start failed\n");
-        goto err_mem_region;
-    }
+       if (!svcodec->io_start) {
+               CODEC_LOG(KERN_ERR, "pci_resource_start failed\n");
+               goto err_mem_region;
+       }
 
-    if (!request_mem_region(svcodec->io_start, svcodec->io_size, DRIVER_NAME)) {
-        CODEC_ERR_LOG("request_io_region failed\n");
-        goto err_mem_region;
-    }
+       if (!request_mem_region(svcodec->io_start,
+                               svcodec->io_size,
+                               DRIVER_NAME)) {
+               CODEC_LOG(KERN_ERR, "request_io_region failed\n");
+               goto err_mem_region;
+       }
 
 #if 0
-    svcodec->memaddr = ioremap(svcodec->mem_start, svcodec->mem_size);
-    if (!svcodec->memaddr) {
-        CODEC_ERR_LOG( "[%s] : ioremap failed\n", __func__);
-        goto err_io_region;
-    }
+       svcodec->memaddr = ioremap(svcodec->mem_start, svcodec->mem_size);
+       if (!svcodec->memaddr) {
+               CODEC_LOG(KERN_ERR, "[%s] : ioremap failed\n", __func__);
+               goto err_io_region;
+       }
 #endif
 
-    svcodec->ioaddr = ioremap_nocache(svcodec->io_start, svcodec->io_size);
-    if (!svcodec->ioaddr) {
-        CODEC_ERR_LOG("ioremap failed\n");
-        goto err_io_region;
-    }
-    if (register_chrdev(CODEC_MAJOR, DRIVER_NAME, &svcodec_fops)) {
-        CODEC_ERR_LOG("register_chrdev failed\n");
-        goto err_io_unmap;
-    }
+       svcodec->ioaddr = ioremap_nocache(svcodec->io_start, svcodec->io_size);
+       if (!svcodec->ioaddr) {
+               CODEC_LOG(KERN_ERR, "ioremap failed\n");
+               goto err_io_region;
+       }
 
-    return 0;
+       /* register chrdev */
+       if (register_chrdev(CODEC_MAJOR, DRIVER_NAME, &svcodec_fops)) {
+               CODEC_LOG(KERN_ERR, "register_chrdev failed\n");
+               goto err_io_unmap;
+       }
+
+       return 0;
 
 err_io_unmap:
-    iounmap(svcodec->ioaddr);
+       iounmap(svcodec->ioaddr);
 #if 0
 err_mem_unmap:
-    iounmap(svcodec->memaddr);
+       iounmap(svcodec->memaddr);
 #endif
 err_io_region:
-    release_mem_region(svcodec->io_start, svcodec->io_size);
+       release_mem_region(svcodec->io_start, svcodec->io_size);
 err_mem_region:
-    release_mem_region(svcodec->mem_start, svcodec->mem_size);
+       release_mem_region(svcodec->mem_start, svcodec->mem_size);
 err_out:
-    pci_disable_device(pci_dev);
+       pci_disable_device(pci_dev);
 err_rel:
-    return -EIO;
+       return -EIO;
+}
+
+static void __devinit svcodec_remove(struct pci_dev *pci_dev)
+{
+       if (svcodec) {
+               if (svcodec->ioaddr) {
+                       iounmap(svcodec->ioaddr);
+                       svcodec->ioaddr = 0;
+               }
+
+#if 0
+               if (svcodec->memaddr) {
+                       iounmap(svcodec->memaddr);
+                       svcodec->memaddr = 0;
+               }
+#endif
+
+               if (svcodec->io_start) {
+                       release_mem_region(svcodec->io_start,
+                                       svcodec->io_size);
+                       svcodec->io_start = 0;
+               }
+
+               if (svcodec->mem_start) {
+                       release_mem_region(svcodec->mem_start,
+                                       svcodec->mem_size);
+                       svcodec->mem_start = 0;
+               }
+
+               kfree(svcodec);
+       }
+       pci_disable_device(pci_dev);
 }
 
+static struct pci_device_id svcodec_pci_table[] __devinitdata = {
+       {
+               .vendor = PCI_VENDOR_ID_TIZEN,
+               .device = PCI_DEVICE_ID_VIRTUAL_CODEC,
+               .subvendor = PCI_ANY_ID,
+               .subdevice = PCI_ANY_ID,
+       },
+};
+MODULE_DEVICE_TABLE(pci, svcodec_pci_table);
+
+/* define PCI Driver for CODEC */
 static struct pci_driver driver = {
-    .name       = DRIVER_NAME,
-    .id_table   = svcodec_pci_table,
-    .probe      = svcodec_probe,
-    .remove     = svcodec_remove,
+       .name = DRIVER_NAME,
+       .id_table = svcodec_pci_table,
+       .probe = svcodec_probe,
+       .remove = svcodec_remove,
 };
 
 static int __init svcodec_init (void)
 {
-    printk(KERN_INFO "%s: device is initialized.\n", DRIVER_NAME);
-    return pci_register_driver(&driver);
+       CODEC_LOG(KERN_INFO, "device is initialized.\n");
+       return pci_register_driver(&driver);
 }
 
 static void __exit svcodec_exit (void)
 {
-    pci_unregister_driver(&driver);
+       pci_unregister_driver(&driver);
 }
 module_init(svcodec_init);
 module_exit(svcodec_exit);