#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
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
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
{\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
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
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
\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
\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
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
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
\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
\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
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
//interacting with hardware done\r
wq_condition = 1;\r
\r
- \r
#ifdef IPP_TEST\r
irq_start = ktime_get();\r
#endif\r
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
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
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
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
*/\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
}\r
\r
mutex_init(&data->mutex);\r
+ mutex_init(&data->power_mutex);\r
data->enable = false;\r
\r
\r
\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
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