IPP V1.002:fix power off bug in rk29_ipp_release
authorchenli <chenli@rock-chips.com>
Mon, 12 Nov 2012 09:37:39 +0000 (17:37 +0800)
committerchenli <chenli@rock-chips.com>
Mon, 12 Nov 2012 09:37:39 +0000 (17:37 +0800)
drivers/staging/rk29/ipp/rk29-ipp.c

index 718bfacb3c6b22487a764fda3014c0450eaf94c4..1d35cbc497de08fe32931ef22aae49900926aa22 100644 (file)
 #include <linux/slab.h>\r
 \r
 #ifdef CONFIG_ARCH_RK29\r
-#define IPP_VERSION "rk29-ipp 1.001"\r
+#define IPP_VERSION "rk29-ipp 1.002"\r
 #endif\r
 \r
 #ifdef CONFIG_ARCH_RK30\r
-#define IPP_VERSION "rk30-ipp 1.001"\r
+#define IPP_VERSION "rk30-ipp 1.002"\r
 #endif\r
 \r
 //#define IPP_TEST\r
@@ -88,7 +88,7 @@ struct ipp_drvdata {
        struct clk *ahb_clk;\r
        \r
        struct mutex    mutex;  // mutex\r
-       \r
+       struct mutex    power_mutex;    // mutex\r
        struct delayed_work power_off_work;\r
        wait_queue_head_t ipp_wait;                 \r
        atomic_t ipp_event;\r
@@ -104,18 +104,8 @@ static struct ipp_drvdata *drvdata = NULL;
 static DECLARE_WAIT_QUEUE_HEAD(hw_wait_queue);\r
 static volatile int wq_condition = 1;                //0:interact with hardware\r
 static DECLARE_WAIT_QUEUE_HEAD(blit_wait_queue);     \r
-static volatile int idle_condition = 1;              //1:idel, 0:busy\r
-\r
-/* Context data (unique) */\r
+static volatile int idle_condition = 1;              //1:idle, 0:busy\r
 \r
-struct ipp_context\r
-{\r
-       struct ipp_drvdata      *data;  // driver data\r
-       struct rk29_ipp_req     *blit;  // blit request\r
-       uint32_t                        rot;    // rotation mode\r
-       struct file                     *srcf;  // source file (for PMEM)\r
-       struct file                     *dstf;  // destination file (for PMEM)\r
-};\r
 \r
 #define IPP_MAJOR              232\r
 \r
@@ -179,8 +169,15 @@ static void ipp_power_on(void)
 {\r
        //printk("ipp_power_on\n");\r
        cancel_delayed_work_sync(&drvdata->power_off_work);\r
+       \r
+       mutex_lock(&drvdata->power_mutex);\r
+       \r
        if (drvdata->enable)\r
+       {\r
+               mutex_unlock(&drvdata->power_mutex);\r
                return;\r
+       }\r
+       \r
        clk_enable(drvdata->pd_ipp);\r
 #ifdef CONFIG_ARCH_RK29\r
        clk_enable(drvdata->aclk_lcdc);\r
@@ -194,14 +191,22 @@ static void ipp_power_on(void)
        clk_enable(drvdata->ahb_clk);\r
 \r
        drvdata->enable = true;\r
+       \r
+       mutex_unlock(&drvdata->power_mutex);\r
 }\r
 \r
 \r
 static void ipp_power_off(struct work_struct *work)\r
 {\r
        //printk("ipp_power_off\n");\r
+       \r
+       mutex_lock(&drvdata->power_mutex);\r
+       \r
        if(!drvdata->enable)\r
+       {\r
+               mutex_unlock(&drvdata->power_mutex);\r
                return;\r
+       }\r
        \r
 #ifdef CONFIG_ARCH_RK29\r
        clk_disable(drvdata->aclk_lcdc);\r
@@ -216,6 +221,8 @@ static void ipp_power_off(struct work_struct *work)
        clk_disable(drvdata->pd_ipp);\r
        \r
        drvdata->enable = false;\r
+\r
+       mutex_unlock(&drvdata->power_mutex);\r
 }\r
 \r
 static unsigned int ipp_poll(struct file *filep, poll_table *wait)\r
@@ -244,17 +251,15 @@ static void ipp_blit_complete(int retval)
 \r
 static int ipp_get_result(unsigned long arg)\r
 {\r
-       //printk("ipp_get_result %d\n",drvdata->ipp_result);\r
        int ret =0;\r
        \r
+       //printk("ipp_get_result %d\n",drvdata->ipp_result);\r
        if (unlikely(copy_to_user((void __user *)arg, &drvdata->ipp_async_result, sizeof(int)))) {\r
                        printk("copy_to_user failed\n");\r
                        ERR("copy_to_user failed\n");\r
                        ret =  -EFAULT; \r
                }\r
-       //idle_condition = 1;\r
-       //dmac_clean_range((const void*)&idle_condition,(const void*)&idle_condition+4);\r
-       //wake_up_interruptible_sync(&blit_wait_queue);\r
+       \r
        return ret;\r
 }\r
 \r
@@ -978,7 +983,7 @@ static int ipp_blit_sync_real(const struct rk29_ipp_req *req)
 \r
        //printk("ipp_blit_sync -------------------\n");\r
 \r
-       ////If IPP is busy now,wait until it becomes idle\r
+       //If IPP is busy now,wait until it becomes idle\r
        mutex_lock(&drvdata->mutex);\r
        {\r
                dmac_inv_range((const void*)&idle_condition,(const void*)&idle_condition+4);\r
@@ -1003,7 +1008,7 @@ static int ipp_blit_sync_real(const struct rk29_ipp_req *req)
                hw_end = ktime_sub(hw_end,hw_start);\r
                if((((int)ktime_to_us(hw_end)/1000)>10)||(((int)ktime_to_us(irq_end)/1000)>10))\r
                {\r
-                       printk("hw time: %d ms, irq time: %d ms\n",(int)ktime_to_us(hw_end)/1000,(int)ktime_to_us(irq_end)/1000);\r
+                       //printk("hw time: %d ms, irq time: %d ms\n",(int)ktime_to_us(hw_end)/1000,(int)ktime_to_us(irq_end)/1000);\r
                }\r
 #endif                         \r
                if (wait_ret <= 0)\r
@@ -1053,7 +1058,7 @@ static int ipp_blit_sync_real(const struct rk29_ipp_req *req)
        return status;\r
 }\r
 \r
-static int stretch_blit(/*struct ipp_context *ctx,*/  unsigned long arg ,unsigned int cmd)\r
+static int stretch_blit(unsigned long arg ,unsigned int cmd)\r
 {\r
        struct rk29_ipp_req req;\r
        int ret = 0;\r
@@ -1097,14 +1102,13 @@ err_noput:
 \r
 static long ipp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)\r
 {\r
-\r
-       //struct ipp_context *ctx = (struct ipp_context *)file->private_data;\r
        int ret = 0;\r
+       \r
        switch (cmd)\r
        {\r
                case IPP_BLIT_SYNC:\r
                case IPP_BLIT_ASYNC:\r
-                       ret = stretch_blit(/*ctx, */arg, cmd);\r
+                       ret = stretch_blit(arg, cmd);\r
                        break;\r
                case IPP_GET_RESULT:\r
                        ret = ipp_get_result(arg);\r
@@ -1119,6 +1123,7 @@ static long ipp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 \r
 static int rk29_ipp_open(struct inode *inode, struct file *file)\r
 {\r
+#if 0\r
    struct ipp_context *ctx;\r
 \r
     ctx = kmalloc(sizeof(struct ipp_context), GFP_KERNEL);\r
@@ -1133,32 +1138,32 @@ static int rk29_ipp_open(struct inode *inode, struct file *file)
        file->private_data = ctx;\r
 \r
        DBG("device opened\n");\r
-\r
+#endif\r
        return 0;\r
 }\r
 \r
 static int ipp_release(struct inode *inode, struct file *file)\r
 {\r
-    struct ipp_context *ctx = (struct ipp_context *)file->private_data;\r
        //printk("ipp_release\n");\r
 \r
-       //clear event\r
+       //clear event if app forget to get result\r
        if(atomic_read(&drvdata->ipp_event))\r
        {\r
                atomic_set(&drvdata->ipp_event, 0);\r
        }\r
-\r
+       \r
+//chenli: all these work has been done in the rk29_ipp_irq, they should not be done again!\r
+#if 0\r
+       \r
        //If app has not got the result after sending the request,the situation of idle_condition equals 1 will block the next request.\r
        //so we must set idle_condition 1 here.\r
        idle_condition = 1;\r
-       wq_condition = 0;\r
+       wq_condition = 1;\r
        \r
        //delay 20ms to wait HW completed\r
        schedule_delayed_work(&drvdata->power_off_work, msecs_to_jiffies(20));\r
-       \r
-       kfree(ctx);\r
+#endif\r
 \r
-       DBG("device released\n");\r
        return 0;\r
 }\r
 \r
@@ -1182,7 +1187,6 @@ static irqreturn_t rk29_ipp_irq(int irq,  void *dev_id)
        //interacting with hardware done\r
        wq_condition = 1;\r
        \r
-       \r
 #ifdef IPP_TEST\r
        irq_start = ktime_get();\r
 #endif\r
@@ -1195,7 +1199,7 @@ static irqreturn_t rk29_ipp_irq(int irq,  void *dev_id)
        else//async\r
        {\r
                //power off\r
-               schedule_delayed_work(&drvdata->power_off_work, msecs_to_jiffies(1000));\r
+               schedule_delayed_work(&drvdata->power_off_work, msecs_to_jiffies(50));\r
                        \r
                drvdata->ipp_irq_callback(drvdata->ipp_result);\r
                \r
@@ -1228,7 +1232,7 @@ static int ipp_suspend(struct platform_device *pdev, pm_message_t state)
 static int ipp_resume(struct platform_device *pdev)\r
 {\r
        //printk("ipp_resume\n");\r
-       //If IPP is woring before suspending, we power it on now\r
+       //If IPP is working before suspending, we power it on now\r
        if (!wq_condition) \r
        {\r
                drvdata->enable = false;\r
@@ -1263,46 +1267,37 @@ static void ipp_test_work_handler(struct work_struct *work)
                 uint32_t dst_addr;\r
                 uint8_t *p;\r
                 pm_message_t pm;\r
-#if 0\r
-//test lzg's bug\r
-uint32_t size = 8*1024*1024;\r
-\r
-#define PMEM_VPU_BASE 0x76000000\r
-#define PMEM_VPU_SIZE  0x4000000\r
-       //      srcY = ioremap_cached(PMEM_VPU_BASE, PMEM_VPU_SIZE);\r
-\r
+#if 1\r
+//test WIMO bug\r
+#define CAMERA_MEM 0x90400000\r
 \r
-       //      srcUV = srcY + size;\r
-       //      dstY = srcUV + size;\r
-       //      dstUV = dstY + size;\r
-               //src_addr = virt_to_phys(srcY);\r
-               //dst_addr = virt_to_phys(dstY);\r
-               src_addr = PMEM_VPU_BASE;\r
-               dst_addr = PMEM_VPU_BASE + size*2;\r
+               src_addr = CAMERA_MEM;\r
+               dst_addr = CAMERA_MEM + 1280*800*4;\r
                printk("src_addr: %x-%x, dst_addr: %x-%x\n",srcY,src_addr,dstY,dst_addr);\r
 \r
                ipp_req.src0.YrgbMst = src_addr;\r
-               ipp_req.src0.CbrMst = src_addr + size;\r
-               ipp_req.src0.w = 2048;\r
-               ipp_req.src0.h = 1440;\r
-               ipp_req.src0.fmt = IPP_Y_CBCR_H2V2;\r
+               //ipp_req.src0.CbrMst = src_addr + 1280*800;\r
+               ipp_req.src0.w = 1280;\r
+               ipp_req.src0.h = 800;\r
+               ipp_req.src0.fmt = IPP_XRGB_8888;\r
                \r
                ipp_req.dst0.YrgbMst = dst_addr;\r
-               ipp_req.dst0.CbrMst = dst_addr + size;\r
-               ipp_req.dst0.w = 2048;\r
-               ipp_req.dst0.h = 1440;\r
+               //ipp_req.dst0.CbrMst = dst_addr + 1024*768;\r
+               ipp_req.dst0.w = 1280;\r
+               ipp_req.dst0.h = 800;\r
        \r
-               ipp_req.src_vir_w = 2048;\r
-               ipp_req.dst_vir_w = 2048;\r
-               ipp_req.timeout = 500;\r
-               ipp_req.flag = IPP_ROT_0;\r
-               \r
-               ret = ipp_do_blit(&ipp_req);\r
-#undef PMEM_VPU_BASE\r
-#undef PMEM_VPU_SIZE\r
+               ipp_req.src_vir_w = 1280;\r
+               ipp_req.dst_vir_w = 1280;\r
+               ipp_req.timeout = 100;\r
+               ipp_req.flag = IPP_ROT_90;\r
 \r
+               while(ret==0)\r
+               {\r
+                       ret = ipp_blit_sync_real(&ipp_req);\r
+                       msleep(10);\r
+               }\r
 #endif\r
-\r
+/*\r
 //test zyc's bug                \r
 \r
                uint32_t size = 800*480;\r
@@ -1337,7 +1332,7 @@ uint32_t size = 8*1024*1024;
                ipp_req.deinterlace_para2 = 0;\r
 \r
                ipp_req.complete = ipp_test_complete;\r
-\r
+*/\r
                /*0 test whether IPP_CONFIG is set correctly*/\r
                /*\r
                ipp_blit_sync(&ipp_req);\r
@@ -1499,12 +1494,14 @@ uint32_t size = 8*1024*1024;
                */\r
 \r
                /*9 test rotate config*/\r
+/*\r
                ipp_req.flag = IPP_ROT_180;\r
                ipp_blit_sync(&ipp_req);\r
                ipp_req.flag = IPP_ROT_270;\r
                ipp_blit_sync(&ipp_req);\r
                \r
                free_pages(srcY, 9);\r
+*/\r
 //test deinterlace\r
 #if 0\r
                uint32_t size = 16*16;\r
@@ -1744,6 +1741,7 @@ static int __devinit ipp_drv_probe(struct platform_device *pdev)
        }\r
 \r
        mutex_init(&data->mutex);\r
+       mutex_init(&data->power_mutex);\r
        data->enable = false;\r
 \r
 \r
@@ -1769,7 +1767,7 @@ static int __devinit ipp_drv_probe(struct platform_device *pdev)
 \r
 #ifdef IPP_TEST\r
        INIT_DELAYED_WORK(&d_work, ipp_test_work_handler);\r
-       schedule_delayed_work(&d_work, msecs_to_jiffies(15000));\r
+       schedule_delayed_work(&d_work, msecs_to_jiffies(35000));\r
 #endif\r
 \r
        return 0;\r
@@ -1862,7 +1860,7 @@ static int __init rk29_ipp_init(void)
        INFO("Module initialized.\n");\r
        printk("IPP init, version %s\n",IPP_VERSION);\r
        return 0;\r
-}\r
+}      \r
 \r
 static void __exit rk29_ipp_exit(void)\r
 {\r