struct mutex mutex; // mutex\r
\r
struct delayed_work power_off_work;\r
- wait_queue_head_t ipp_wait; //pollʱµÄµÈ´ý¶ÓÁÐ\r
+ wait_queue_head_t ipp_wait; \r
atomic_t ipp_event;\r
- bool issync; //ÊÇͬ²½µ÷Óû¹ÊÇÒì²½µ÷ÓÃ\r
- bool enable; //IPPÊÇ·ñʹÄÜÁËclk\r
- int ipp_result; //´æ·Åµ±Ç°IPP²Ù×÷µÄ½á¹û£¬0´ú±í³É¹¦\r
- void (*ipp_irq_callback)(int ipp_retval); //Òì²½µ÷ÓõĻص÷º¯Êý\r
+ bool issync; //sync or async\r
+ bool enable; //clk enable or disable\r
+ int ipp_result; //0:success\r
+ void (*ipp_irq_callback)(int ipp_retval); //callback function used by aync call\r
};\r
\r
static struct ipp_drvdata *drvdata = NULL;\r
\r
static DECLARE_WAIT_QUEUE_HEAD(hw_wait_queue);\r
-static volatile int wq_condition = 1; //ͬӲ¼þ½»»¥Ê±1£¬Í¬Ó²¼þ½»»¥Íê³É0\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£¬µ±Ç°ÇëÇóÕýÔÚÖ´ÐÐ0\r
+static volatile int idle_condition = 1; //1:idel, 0:busy\r
\r
/* Context data (unique) */\r
\r
uint32_t pre_scale_w, pre_scale_h;//pre_scale para\r
uint32_t post_scale_w = 0x1000;\r
uint32_t post_scale_h = 0x1000;\r
- uint32_t pre_scale_output_w=0, pre_scale_output_h=0;//pre_scaleµÄÊä³ö¿í¸ß\r
- uint32_t post_scale_input_w, post_scale_input_h;//post_scaleµÄÊäÈë¿í¸ß\r
+ uint32_t pre_scale_output_w=0, pre_scale_output_h=0;//pre_scale output with&height\r
+ uint32_t post_scale_input_w, post_scale_input_h;//post_scale input width&height\r
uint32_t dst0_YrgbMst=0,dst0_CbrMst=0;\r
uint32_t ret = 0;\r
uint32_t deinterlace_config = 0;\r
\r
drvdata->ipp_result = -1;\r
\r
- //ͬ²½µÄÇé¿öÏÂreq->complete¶¼Ó¦¸ÃΪNULL£¬¶øÒì²½µÄÇé¿öÏÂÓû§Ì¬µ÷ÓõÄreq->completeҲΪNULL£¬ÄÚºË̬µ÷ÓõÄreq->completeÓ¦·Ç¿Õ\r
+ //When ipp_blit_async is called in kernel space req->complete should NOt be NULL, otherwise req->complete should be NULL\r
if(req->complete)\r
{\r
drvdata->ipp_irq_callback = req->complete;\r
break;\r
}\r
\r
- //ÏÖÔÚ¿ªÊ¼Ó²¼þ¿ªÊ¼¹¤×÷\r
+ //we start to interact with hw now\r
wq_condition = 0;\r
\r
ipp_power_on();\r
}\r
}\r
\r
- if((req->src0.w%pre_scale_w)!=0) //ÏòÉÏÈ¡Õû ceil\r
+ if((req->src0.w%pre_scale_w)!=0) //ceil\r
{\r
pre_scale_output_w = req->src0.w/pre_scale_w+1;\r
}\r
pre_scale_output_w = req->src0.w/pre_scale_w;\r
}\r
\r
- if((req->src0.h%pre_scale_h)!=0)//ÏòÉÏÈ¡Õû ceil\r
+ if((req->src0.h%pre_scale_h)!=0)//ceil\r
{\r
pre_scale_output_h = req->src0.h/pre_scale_h +1;\r
}\r
/*Configure Post_scale*/\r
if((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate))\r
{\r
- if (( (req->src0.h%req->dst0.w)!=0)||( (req->src0.w%req->dst0.h)!= 0)//СÊý±¶ËõС\r
- ||((req->src0.h/req->dst0.w)>8)||((req->src0.h%req->dst0.w)>8) //ËõСϵÊý´óÓÚ8\r
- ||(req->dst0.w > req->src0.h) ||(req->dst0.h > req->src0.w)) //·Å´ó\r
+ if (( (req->src0.h%req->dst0.w)!=0)||( (req->src0.w%req->dst0.h)!= 0)//non-interger down-scaling \r
+ ||((req->src0.h/req->dst0.w)>8)||((req->src0.h%req->dst0.w)>8) //down-scaling ratio > 8\r
+ ||(req->dst0.w > req->src0.h) ||(req->dst0.h > req->src0.w)) //up-scaling\r
\r
{\r
post_scale = 1;\r
}\r
else //0 180 x-flip y-flip\r
{\r
- if (( (req->src0.w%req->dst0.w)!=0)||( (req->src0.h%req->dst0.h)!= 0)//СÊý±¶ËõС\r
- ||((req->src0.w/req->dst0.w)>8)||((req->src0.h%req->dst0.h)>8) //ËõСϵÊý´óÓÚ8\r
- ||(req->dst0.w > req->src0.w) ||(req->dst0.h > req->src0.h)) //·Å´ó\r
+ if (( (req->src0.w%req->dst0.w)!=0)||( (req->src0.h%req->dst0.h)!= 0)//non-interger down-scaling \r
+ ||((req->src0.w/req->dst0.w)>8)||((req->src0.h%req->dst0.h)>8) //down-scaling ratio > 8\r
+ ||(req->dst0.w > req->src0.w) ||(req->dst0.h > req->src0.h)) //up-scaling\r
{\r
post_scale = 1;\r
}\r
int ret = -1;\r
//printk("ipp_blit_async *******************\n");\r
\r
- //Èç¹û´ËʱIPPÔÚÖ´ÐÐÒ»¸öÇëÇ󣬵ȴýIPP¿ÕÏÐ\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
//printk("ipp_blit_sync -------------------\n");\r
\r
\r
- //Èç¹û´ËʱIPPÔÚÖ´ÐÐÒ»¸öÇëÇ󣬵ȴýIPP¿ÕÏÐ\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
}\r
drvdata->issync = false;\r
\r
- //ͬ²½µ÷ÓÃÔÚ´ËÈÏΪIPPÒѾ¿ÕÏУ¬»½Ðѵȴý¶ÓÁÐ \r
- //printk("ipp_blit_sync done ----------------\n");\r
- status = drvdata->ipp_result;\r
- idle_condition = 1;\r
- wake_up_interruptible_sync(&blit_wait_queue);\r
- \r
- return status;\r
-}\r
-\r
-int ipp_do_blit(struct rk29_ipp_req *req)\r
-{\r
- uint32_t rotate;\r
- uint32_t pre_scale = 0;\r
- uint32_t post_scale = 0;\r
- uint32_t pre_scale_w, pre_scale_h;//pre_scale para\r
- uint32_t post_scale_w = 0x1000;\r
- uint32_t post_scale_h = 0x1000;\r
- uint32_t pre_scale_output_w=0, pre_scale_output_h=0;//pre_scaleµÄÊä³ö¿í¸ß\r
- uint32_t post_scale_input_w, post_scale_input_h;//post_scaleµÄÊäÈë¿í¸ß\r
- uint32_t dst0_YrgbMst=0,dst0_CbrMst=0;\r
- uint32_t ret = 0;\r
- uint32_t deinterlace_config = 0;\r
- int wait_ret;\r
-\r
- mutex_lock(&drvdata->mutex);\r
- \r
- if (drvdata == NULL) { /* ddl@rock-chips.com : check driver is normal or not */\r
- //printk(KERN_ERR, "%s drvdata is NULL, IPP driver probe is fail!!\n", __FUNCTION__);\r
- printk("%s drvdata is NULL, IPP driver probe is fail!!\n", __FUNCTION__);\r
- return -EPERM;\r
- }\r
-\r
-\r
- /*IPP can support up to 8191*8191 resolution in RGB format,but we limit the image size to 8190*8190 here*/\r
- //check src width and height\r
- if (unlikely((req->src0.w <16) || (req->src0.w > 8190) || (req->src0.h < 16) || (req->src0.h > 8190))) {\r
- ERR("invalid source resolution\n");\r
- ret = -EINVAL;\r
- goto erorr_input;\r
- }\r
-\r
- //check dst width and height\r
- if (unlikely((req->dst0.w <16) || (req->dst0.w > 2047) || (req->dst0.h < 16) || (req->dst0.h > 2047))) {\r
- ERR("invalid destination resolution\n");\r
- ret = -EINVAL;\r
- goto erorr_input;\r
- }\r
-\r
- //check src address\r
- if (unlikely(req->src0.YrgbMst== 0) )\r
- {\r
- ERR("could not retrieve src image from memory\n");\r
- ret = -EINVAL;\r
- goto erorr_input;\r
- }\r
-\r
- //check src address\r
- if (unlikely(req->dst0.YrgbMst== 0) )\r
- {\r
- ERR("could not retrieve dst image from memory\n");\r
- ret = -EINVAL;\r
- goto erorr_input;\r
- }\r
- //check rotate degree\r
- if(req->flag >= IPP_ROT_LIMIT)\r
- {\r
- ERR("rk29_ipp is not surpport rot degree!!!!\n");\r
- ret = -EINVAL;\r
- goto erorr_input;\r
- }\r
-\r
- \r
- rotate = req->flag;\r
- switch (rotate) {\r
- case IPP_ROT_90:\r
- //for rotation 90 degree\r
- DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt);\r
- switch(req->src0.fmt)\r
- {\r
- case IPP_XRGB_8888:\r
- dst0_YrgbMst = req->dst0.YrgbMst + req->dst0.w*4;\r
- dst0_CbrMst = req->dst0.CbrMst;\r
- break;\r
-\r
- case IPP_RGB_565:\r
- dst0_YrgbMst = req->dst0.YrgbMst + req->dst0.w*2;\r
- dst0_CbrMst = req->dst0.CbrMst;\r
- break;\r
-\r
- case IPP_Y_CBCR_H1V1:\r
- dst0_YrgbMst = req->dst0.YrgbMst + req->dst0.w;\r
- dst0_CbrMst = req->dst0.CbrMst + req->dst0.w*2;\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V1:\r
- dst0_YrgbMst = req->dst0.YrgbMst + req->dst0.w;\r
- dst0_CbrMst = req->dst0.CbrMst + req->dst0.w*2;\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V2:\r
- dst0_YrgbMst = req->dst0.YrgbMst+ req->dst0.w;\r
- dst0_CbrMst = req->dst0.CbrMst + req->dst0.w;\r
- break;\r
-\r
- default:\r
-\r
- break;\r
- }\r
- break;\r
-\r
- case IPP_ROT_180:\r
- //for rotation 180 degree\r
- DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt);\r
- switch(req->src0.fmt)\r
- {\r
- case IPP_XRGB_8888:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*4+req->dst0.w*4;\r
- dst0_CbrMst = req->dst0.CbrMst;\r
- break;\r
-\r
- case IPP_RGB_565:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*2+req->dst0.w*2;\r
- dst0_CbrMst = req->dst0.CbrMst;\r
- break;\r
-\r
- case IPP_Y_CBCR_H1V1:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w;\r
- dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2+req->dst0.w*2;\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V1:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w;\r
- dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w;\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V2:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w;\r
- dst0_CbrMst = req->dst0.CbrMst+((req->dst0.h/2)-1)*req->dst_vir_w+req->dst0.w;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- break;\r
-\r
- case IPP_ROT_270:\r
- DBG("rotate %d, src0.fmt %d \n",rotate,req->src0.fmt);\r
- switch(req->src0.fmt)\r
- {\r
- case IPP_XRGB_8888:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*4;\r
- dst0_CbrMst = req->dst0.CbrMst;\r
- break;\r
-\r
- case IPP_RGB_565:\r
- dst0_YrgbMst = req->dst0.YrgbMst +(req->dst0.h-1)*req->dst_vir_w*2;\r
- dst0_CbrMst = req->dst0.CbrMst;\r
- break;\r
-\r
- case IPP_Y_CBCR_H1V1:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;\r
- dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2;\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V1:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;\r
- dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2;\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V2:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;\r
- dst0_CbrMst = req->dst0.CbrMst+((req->dst0.h/2)-1)*req->dst_vir_w;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- break;\r
-\r
- case IPP_ROT_X_FLIP:\r
- DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt);\r
- switch(req->src0.fmt)\r
- {\r
- case IPP_XRGB_8888:\r
- dst0_YrgbMst = req->dst0.YrgbMst+req->dst0.w*4;\r
- dst0_CbrMst = req->dst0.CbrMst;\r
- break;\r
-\r
- case IPP_RGB_565:\r
- dst0_YrgbMst = req->dst0.YrgbMst+req->dst0.w*2;\r
- dst0_CbrMst = req->dst0.CbrMst;\r
- break;\r
-\r
- case IPP_Y_CBCR_H1V1:\r
- dst0_YrgbMst = req->dst0.YrgbMst+req->dst0.w;\r
- dst0_CbrMst = req->dst0.CbrMst+req->dst0.w*2;\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V1:\r
- dst0_YrgbMst = req->dst0.YrgbMst+req->dst0.w;\r
- dst0_CbrMst = req->dst0.CbrMst+req->dst0.w;\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V2:\r
- dst0_YrgbMst = req->dst0.YrgbMst+req->dst0.w;\r
- dst0_CbrMst = req->dst0.CbrMst+req->dst0.w;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- break;\r
-\r
- case IPP_ROT_Y_FLIP:\r
- DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt);\r
- switch(req->src0.fmt)\r
- {\r
- case IPP_XRGB_8888:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*4;\r
- dst0_CbrMst = req->dst0.CbrMst;\r
- break;\r
-\r
- case IPP_RGB_565:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*2;\r
- dst0_CbrMst = req->dst0.CbrMst;\r
- break;\r
-\r
- case IPP_Y_CBCR_H1V1:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;\r
- dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2;\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V1:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;\r
- dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w;\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V2:\r
- dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w;\r
- dst0_CbrMst = req->dst0.CbrMst+((req->dst0.h/2)-1)*req->dst_vir_w;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- break;\r
- case IPP_ROT_0:\r
- //for 0 degree\r
- DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt);\r
- dst0_YrgbMst = req->dst0.YrgbMst;\r
- dst0_CbrMst = req->dst0.CbrMst;\r
- break;\r
-\r
- default:\r
- ERR("ipp is not surpport degree!!\n" );\r
- break;\r
- }\r
-\r
- //enable clk\r
- if(drvdata->pd_display)\r
- {\r
- clk_enable(drvdata->pd_display);\r
- }\r
- else\r
- {\r
- printk("pd_display is null \n");\r
- ret = -EINVAL;\r
- goto error_pd_display;\r
- }\r
- \r
- if(drvdata->aclk_lcdc)\r
- {\r
- clk_enable(drvdata->aclk_lcdc);\r
- }\r
- else\r
- {\r
- printk("aclk_lcdc is null \n");\r
- ret = -EINVAL;\r
- goto error_aclk_lcdc;\r
- }\r
-\r
- if(drvdata->hclk_lcdc)\r
- {\r
- clk_enable(drvdata->hclk_lcdc);\r
- }\r
- else\r
- {\r
- printk("hclk_lcdc is null \n");\r
- ret = -EINVAL;\r
- goto error_hclk_lcdc;\r
- }\r
-\r
- if(drvdata->aclk_ddr_lcdc)\r
- {\r
- clk_enable(drvdata->aclk_ddr_lcdc);\r
- }\r
- else\r
- {\r
- printk("aclk_ddr_lcdc is null \n");\r
- ret = -EINVAL;\r
- goto error_aclk_ddr_lcdc;\r
- }\r
- \r
- if(drvdata->hclk_cpu_display)\r
- {\r
- clk_enable(drvdata->hclk_cpu_display);\r
- }\r
- else\r
- {\r
- printk("hclk_cpu_display is null \n");\r
- ret = -EINVAL;\r
- goto error_hclk_cpu_display;\r
- }\r
- \r
- if(drvdata->aclk_disp_matrix)\r
- {\r
- clk_enable(drvdata->aclk_disp_matrix);\r
- }\r
- else\r
- {\r
- printk("aclk_disp_matrix is null \n");\r
- ret = -EINVAL;\r
- goto error_aclk_disp_matrix;\r
- }\r
-\r
- if(drvdata->hclk_disp_matrix)\r
- {\r
- clk_enable(drvdata->hclk_disp_matrix);\r
- }\r
- else\r
- {\r
- printk("hclk_disp_matrix is null \n");\r
- ret = -EINVAL;\r
- goto error_hclk_disp_matrix;\r
- }\r
- \r
- if(drvdata->axi_clk)\r
- {\r
- clk_enable(drvdata->axi_clk);\r
- }\r
- else\r
- {\r
- printk("axi_clk is null \n");\r
- ret = -EINVAL;\r
- goto error_axi_clk;\r
- }\r
-\r
- if(drvdata->ahb_clk)\r
- {\r
- clk_enable(drvdata->ahb_clk);\r
- }\r
- else\r
- {\r
- printk("ahb_clk is null \n");\r
- ret = -EINVAL;\r
- goto error_ahb_clk;\r
- }\r
- //enable clk end\r
-\r
- //check if IPP is idle\r
- if(((ipp_read(IPP_INT)>>6)&0x3) !=0)// idle\r
- {\r
- printk("IPP staus is not idle,can noe set register\n");\r
- goto error_status;\r
- }\r
-\r
-\r
- /* Configure source image */\r
- DBG("src YrgbMst 0x%x , CbrMst0x%x, %dx%d, fmt = %d\n", req->src0.YrgbMst,req->src0.CbrMst,\r
- req->src0.w, req->src0.h, req->src0.fmt);\r
-\r
- ipp_write(req->src0.YrgbMst, IPP_SRC0_Y_MST);\r
- if(IS_YCRCB(req->src0.fmt))\r
- {\r
- ipp_write(req->src0.CbrMst, IPP_SRC0_CBR_MST);\r
- }\r
- ipp_write(req->src0.h<<16|req->src0.w, IPP_SRC_IMG_INFO);\r
- ipp_write((ipp_read(IPP_CONFIG)&(~0x7))|req->src0.fmt, IPP_CONFIG);\r
-\r
- /* Configure destination image */\r
- DBG("dst YrgbMst 0x%x , CbrMst0x%x, %dx%d\n", dst0_YrgbMst,dst0_CbrMst,\r
- req->dst0.w, req->dst0.h);\r
-\r
- ipp_write(dst0_YrgbMst, IPP_DST0_Y_MST);\r
-\r
- if(IS_YCRCB(req->src0.fmt))\r
- {\r
- ipp_write(dst0_CbrMst, IPP_DST0_CBR_MST);\r
- }\r
-\r
- ipp_write(req->dst0.h<<16|req->dst0.w, IPP_DST_IMG_INFO);\r
-\r
- /*Configure Pre_scale*/\r
- if((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate))\r
- {\r
- pre_scale = ((req->dst0.w < req->src0.h) ? 1 : 0)||((req->dst0.h < req->src0.w) ? 1 : 0);\r
- }\r
- else //other degree\r
- {\r
- pre_scale = ((req->dst0.w < req->src0.w) ? 1 : 0)||((req->dst0.h < req->src0.h) ? 1 : 0);\r
- }\r
-\r
- if(pre_scale)\r
- {\r
- if(((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate)))\r
- {\r
-\r
- if((req->src0.w>req->dst0.h))\r
- {\r
- pre_scale_w = (uint32_t)( req->src0.w/req->dst0.h);//floor\r
- }\r
- else\r
- {\r
- pre_scale_w = 1;\r
- }\r
- if((req->src0.h>req->dst0.w))\r
- {\r
- pre_scale_h = (uint32_t)( req->src0.h/req->dst0.w);//floor\r
- }\r
- else\r
- {\r
- pre_scale_h = 1;\r
- }\r
-\r
- DBG("!!!!!pre_scale_h %d,pre_scale_w %d \n",pre_scale_h,pre_scale_w);\r
- }\r
- else//0 180 x ,y\r
- {\r
-\r
- if((req->src0.w>req->dst0.w))\r
- {\r
- pre_scale_w = (uint32_t)( req->src0.w/req->dst0.w);//floor\r
- }\r
- else\r
- {\r
- pre_scale_w = 1;\r
- }\r
-\r
- if((req->src0.h>req->dst0.h))\r
- {\r
- pre_scale_h = (uint32_t)( req->src0.h/req->dst0.h);//floor\r
- }\r
- else\r
- {\r
- pre_scale_h = 1;\r
- }\r
- DBG("!!!!!pre_scale_h %d,pre_scale_w %d \n",pre_scale_h,pre_scale_w);\r
- }\r
-\r
- //pre_scale only support 1/2 to 1/8 time\r
- if(pre_scale_w > 8)\r
- {\r
- if(pre_scale_w < 16)\r
- {\r
- pre_scale_w = 8;\r
- }\r
- else\r
- {\r
- printk("invalid pre_scale operation! pre_scale_w should not be more than 8!\n");\r
- goto error_scale;\r
- }\r
- }\r
- if(pre_scale_h > 8)\r
- {\r
- if(pre_scale_h < 16)\r
- {\r
- pre_scale_h = 8;\r
- }\r
- else\r
- {\r
- printk("invalid pre_scale operation! pre_scale_h should not be more than 8!\n");\r
- goto error_scale;\r
- }\r
- }\r
- \r
- if((req->src0.w%pre_scale_w)!=0) //ÏòÉÏÈ¡Õû ceil\r
- {\r
- pre_scale_output_w = req->src0.w/pre_scale_w+1;\r
- }\r
- else\r
- {\r
- pre_scale_output_w = req->src0.w/pre_scale_w;\r
- }\r
-\r
- if((req->src0.h%pre_scale_h)!=0)//ÏòÉÏÈ¡Õû ceil\r
- {\r
- pre_scale_output_h = req->src0.h/pre_scale_h +1;\r
- }\r
- else\r
- {\r
- pre_scale_output_h = req->src0.h/pre_scale_h;\r
- }\r
- \r
- ipp_write((ipp_read(IPP_CONFIG)&0xffffffef)|PRE_SCALE, IPP_CONFIG); //enable pre_scale\r
- ipp_write((pre_scale_h-1)<<3|(pre_scale_w-1),IPP_PRE_SCL_PARA);\r
- ipp_write(((pre_scale_output_h)<<16)|(pre_scale_output_w), IPP_PRE_IMG_INFO);\r
-\r
- }\r
- else//no pre_scale\r
- {\r
- ipp_write(0,IPP_PRE_SCL_PARA);\r
- ipp_write((req->src0.h<<16)|req->src0.w, IPP_PRE_IMG_INFO);\r
- }\r
-\r
- /*Configure Post_scale*/\r
- if((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate))\r
- {\r
- if (( (req->src0.h%req->dst0.w)!=0)||( (req->src0.w%req->dst0.h)!= 0)//СÊý±¶ËõС\r
- ||((req->src0.h/req->dst0.w)>8)||((req->src0.h%req->dst0.w)>8) //ËõСϵÊý´óÓÚ8\r
- ||(req->dst0.w > req->src0.h) ||(req->dst0.h > req->src0.w)) //·Å´ó\r
- \r
- {\r
- post_scale = 1;\r
- }\r
- else\r
- {\r
- post_scale = 0;\r
- }\r
- }\r
- else //0 180 x-flip y-flip\r
- {\r
- if (( (req->src0.w%req->dst0.w)!=0)||( (req->src0.h%req->dst0.h)!= 0)//СÊý±¶ËõС\r
- ||((req->src0.w/req->dst0.w)>8)||((req->src0.h%req->dst0.h)>8) //ËõСϵÊý´óÓÚ8\r
- ||(req->dst0.w > req->src0.w) ||(req->dst0.h > req->src0.h)) //·Å´ó\r
- {\r
- post_scale = 1;\r
- }\r
- else\r
- {\r
- post_scale = 0;\r
- }\r
- }\r
-\r
- if(post_scale)\r
- {\r
- if(pre_scale)\r
- {\r
- post_scale_input_w = pre_scale_output_w;\r
- post_scale_input_h = pre_scale_output_h;\r
- }\r
- else\r
- {\r
- post_scale_input_w = req->src0.w;\r
- post_scale_input_h = req->src0.h;\r
- }\r
- \r
- if((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate))\r
- {\r
- DBG("post_scale_input_w %d ,post_scale_input_h %d !!!\n",post_scale_input_w,post_scale_input_h);\r
-\r
- switch(req->src0.fmt)\r
- {\r
- case IPP_XRGB_8888:\r
- case IPP_RGB_565:\r
- case IPP_Y_CBCR_H1V1:\r
- //In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer\r
- if(((4096*(post_scale_input_w-1))%(req->dst0.h-1))==0)\r
- {\r
- post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.h-1))-1;\r
- }\r
- else\r
- {\r
- post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.h-1));\r
- }\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V1:\r
- case IPP_Y_CBCR_H2V2:\r
- //In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer\r
- if(((4096*(post_scale_input_w/2-1))%(req->dst0.h/2-1))==0)\r
- {\r
- post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.h/2-1))-1;\r
- }\r
- else\r
- {\r
- post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.h/2-1));\r
- }\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- post_scale_h = (uint32_t)(4096*(post_scale_input_h -1)/(req->dst0.w-1));\r
-\r
- DBG("1111 post_scale_w %x,post_scale_h %x!!! \n",post_scale_w,post_scale_h);\r
- }\r
- else// 0 180 x-flip y-flip\r
- {\r
- switch(req->src0.fmt)\r
- {\r
- case IPP_XRGB_8888:\r
- case IPP_RGB_565:\r
- case IPP_Y_CBCR_H1V1:\r
- //In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer\r
- if(((4096*(post_scale_input_w-1))%(req->dst0.w-1))==0)\r
- {\r
- post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.w-1))-1;\r
- }\r
- else\r
- {\r
- post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.w-1));\r
- }\r
- break;\r
-\r
- case IPP_Y_CBCR_H2V1:\r
- case IPP_Y_CBCR_H2V2:\r
- ////In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer\r
- if(((4096*(post_scale_input_w/2-1))%(req->dst0.w/2-1))==0)\r
- {\r
- post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.w/2-1))-1;\r
- }\r
- else\r
- {\r
- post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.w/2-1));\r
- }\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- post_scale_h = (uint32_t)(4096*(post_scale_input_h -1)/(req->dst0.h-1));\r
-\r
- }\r
\r
- if(!((req->src0.fmt != IPP_Y_CBCR_H2V1)&&(req->src0.w == 176)&&(req->src0.h == 144)&&(req->dst0.w == 480)&&(req->dst0.h == 800)))\r
- { \r
- //only support 1/2 to 4 times scaling,but 176*144->480*800 can pass\r
- if(post_scale_w<0x3ff || post_scale_w>0x1fff || post_scale_h<0x400 || post_scale_h>0x2000 )\r
- {\r
- printk("invalid post_scale para!\n");\r
- goto error_scale;\r
- }\r
- }\r
- ipp_write((ipp_read(IPP_CONFIG)&0xfffffff7)|POST_SCALE, IPP_CONFIG); //enable post_scale\r
- ipp_write((post_scale_h<<16)|post_scale_w, IPP_POST_SCL_PARA);\r
- }\r
- else //no post_scale\r
- {\r
- DBG("no post_scale !!!!!! \n");\r
- ipp_write(ipp_read(IPP_CONFIG)&(~POST_SCALE), IPP_CONFIG); //disable post_scale\r
- ipp_write((post_scale_h<<16)|post_scale_w, IPP_POST_SCL_PARA);\r
- }\r
-\r
- /* Configure rotation */\r
-\r
- if(IPP_ROT_0 == req->flag)\r
- {\r
- ipp_write(ipp_read(IPP_CONFIG)&(~ROT_ENABLE), IPP_CONFIG);\r
- }\r
- else\r
- {\r
- ipp_write(ipp_read(IPP_CONFIG)|ROT_ENABLE, IPP_CONFIG);\r
- ipp_write(ipp_read(IPP_CONFIG)|rotate<<5, IPP_CONFIG);\r
- }\r
-\r
- /*Configure deinterlace*/\r
- if(req->deinterlace_enable == 1)\r
- {\r
- //only support YUV format\r
- if(IS_YCRCB(req->src0.fmt))\r
- {\r
- //If pre_scale is enable, Deinterlace is done by scale filter\r
- if(!pre_scale)\r
- {\r
- //check the deinterlace parameters\r
- if((req->deinterlace_para0 < 32) && (req->deinterlace_para1 < 32) && (req->deinterlace_para2 < 32) \r
- && ((req->deinterlace_para0 + req->deinterlace_para1 + req->deinterlace_para2) == 32))\r
- {\r
- deinterlace_config = (req->deinterlace_enable<<24) | (req->deinterlace_para0<<19) | (req->deinterlace_para1<<14) | (req->deinterlace_para2<<9);\r
- DBG("para0 %d, para1 %d, para2 %d,deinterlace_config %x\n",req->deinterlace_para0,req->deinterlace_para1,req->deinterlace_para2,deinterlace_config);\r
- ipp_write((ipp_read(IPP_CONFIG)&0xFE0001FF)|deinterlace_config, IPP_CONFIG);\r
-\r
- //printk("IPP_CONFIG2 = 0x%x\n",ipp_read(IPP_CONFIG));\r
- }\r
- else\r
- {\r
- ERR("invalid deinterlace parameters!\n");\r
- }\r
- }\r
- }\r
- else\r
- {\r
- ERR("only support YUV format!\n");\r
- }\r
- }\r
-\r
- /*Configure other*/\r
- ipp_write((req->dst_vir_w<<16)|req->src_vir_w, IPP_IMG_VIR);\r
-\r
- if((req->src0.w%4) !=0)\r
- ipp_write(ipp_read(IPP_CONFIG)|(1<<26), IPP_CONFIG);//store clip mode\r
-\r
- /* Start the operation */\r
-\r
- ipp_write(8, IPP_INT);//\r
-\r
- //msleep(5000);//debug use\r
-\r
- wq_condition = 0;\r
- dsb();\r
-#ifdef IPP_TEST\r
- memset(&hw_set,0,sizeof(struct timeval));\r
- memset(&irq_ret,0,sizeof(struct timeval));\r
- memset(&irq_done,0,sizeof(struct timeval));\r
- memset(&wait_done,0,sizeof(struct timeval));\r
- do_gettimeofday(&hw_set);\r
-#endif\r
-\r
- ipp_write(1, IPP_PROCESS_ST);\r
- //Important!Without msleep,ipp driver may occupy too much CPU,this can lead the ipp interrupt to timeout\r
- msleep(1);\r
-\r
- wait_ret = wait_event_interruptible_timeout(hw_wait_queue, wq_condition, msecs_to_jiffies(req->timeout));\r
-\r
-#ifdef IPP_TEST\r
- do_gettimeofday(&wait_done);\r
- if ((((irq_ret.tv_sec - hw_set.tv_sec) * 1000 + (irq_ret.tv_usec - hw_set.tv_usec) / 1000) > 10) ||\r
- (((wait_done.tv_sec - irq_done.tv_sec) * 1000 + (wait_done.tv_usec - irq_done.tv_usec) / 1000) > 10)) {\r
- printk("hw time: %8d irq time %8d\n",\r
- ((irq_ret.tv_sec - hw_set.tv_sec) * 1000 + (irq_ret.tv_usec - hw_set.tv_usec) / 1000),\r
- ((wait_done.tv_sec - irq_done.tv_sec) * 1000 + (wait_done.tv_usec - irq_done.tv_usec) / 1000));\r
- }\r
-#endif\r
- \r
-\r
- if (wait_ret <= 0)\r
- {\r
- printk("%s wait_event_timeout \n",__FUNCTION__);\r
-\r
-#ifdef IPP_TEST\r
- //print all register's value\r
- printk("wait_ret: %d\n", wait_ret);\r
- printk("wq_condition: %d\n", wq_condition);\r
- printk("IPP_CONFIG: %x\n",ipp_read(IPP_CONFIG));\r
- printk("IPP_SRC_IMG_INFO: %x\n",ipp_read(IPP_SRC_IMG_INFO));\r
- printk("IPP_DST_IMG_INFO: %x\n",ipp_read(IPP_DST_IMG_INFO));\r
- printk("IPP_IMG_VIR: %x\n",ipp_read(IPP_IMG_VIR));\r
- printk("IPP_INT: %x\n",ipp_read(IPP_INT));\r
- printk("IPP_SRC0_Y_MST: %x\n",ipp_read(IPP_SRC0_Y_MST));\r
- printk("IPP_SRC0_CBR_MST: %x\n",ipp_read(IPP_SRC0_CBR_MST));\r
- printk("IPP_SRC1_Y_MST: %x\n",ipp_read(IPP_SRC1_Y_MST));\r
- printk("IPP_SRC1_CBR_MST: %x\n",ipp_read(IPP_SRC1_CBR_MST));\r
- printk("IPP_DST0_Y_MST: %x\n",ipp_read(IPP_DST0_Y_MST));\r
- printk("IPP_DST0_CBR_MST: %x\n",ipp_read(IPP_DST0_CBR_MST));\r
- printk("IPP_DST1_Y_MST: %x\n",ipp_read(IPP_DST1_Y_MST));\r
- printk("IPP_DST1_CBR_MST: %x\n",ipp_read(IPP_DST1_CBR_MST));\r
- printk("IPP_PRE_SCL_PARA: %x\n",ipp_read(IPP_PRE_SCL_PARA));\r
- printk("IPP_POST_SCL_PARA: %x\n",ipp_read(IPP_POST_SCL_PARA));\r
- printk("IPP_SWAP_CTRL: %x\n",ipp_read(IPP_SWAP_CTRL));\r
- printk("IPP_PRE_IMG_INFO: %x\n",ipp_read(IPP_PRE_IMG_INFO));\r
- printk("IPP_AXI_ID: %x\n",ipp_read(IPP_AXI_ID));\r
- printk("IPP_SRESET: %x\n",ipp_read(IPP_SRESET));\r
- printk("IPP_PROCESS_ST: %x\n",ipp_read(IPP_PROCESS_ST));\r
-\r
- while(1)\r
- {\r
-\r
- }\r
-#endif\r
- \r
- wq_condition = 0;\r
- if(!drvdata)\r
- {\r
- printk("close clk 0! \n");\r
- ret = -EINVAL;\r
- goto error_null;\r
- }\r
- ret = -EAGAIN;\r
- goto error_timeout;\r
- }\r
-\r
-\r
- if(!drvdata)\r
- {\r
- printk("close clk! \n");\r
- ret = -EINVAL;\r
- goto error_null;\r
- }\r
-\r
- if(((ipp_read(IPP_INT)>>6)&0x3) ==0)// idle\r
- {\r
- goto error_noerror;\r
- }\r
- else\r
- {\r
- printk("rk29 ipp status is error!!!\n");\r
- ret = -EINVAL;\r
- goto error_timeout;\r
- }\r
+ //IPP is idle, wake up the wait queue\r
+ //printk("ipp_blit_sync done ----------------\n");\r
+ status = drvdata->ipp_result;\r
+ idle_condition = 1;\r
+ wake_up_interruptible_sync(&blit_wait_queue);\r
\r
-error_status:\r
-error_scale:\r
-error_null:\r
-error_timeout:\r
- //soft rest\r
- ipp_soft_reset();\r
-error_noerror:\r
- clk_disable(drvdata->ahb_clk);\r
-error_ahb_clk:\r
- clk_disable(drvdata->axi_clk);\r
-error_axi_clk: \r
- clk_disable(drvdata->hclk_disp_matrix);\r
-error_hclk_disp_matrix:\r
- clk_disable(drvdata->aclk_disp_matrix);\r
-error_aclk_disp_matrix:\r
- clk_disable(drvdata->hclk_cpu_display);\r
-error_hclk_cpu_display:\r
- clk_disable(drvdata->aclk_ddr_lcdc);\r
-error_aclk_ddr_lcdc:\r
- clk_disable(drvdata->hclk_lcdc);\r
-error_hclk_lcdc:\r
- clk_disable(drvdata->aclk_lcdc);\r
-error_aclk_lcdc: \r
- clk_disable(drvdata->pd_display);\r
-error_pd_display:\r
-erorr_input:\r
- mutex_unlock(&drvdata->mutex);\r
- return ret;\r
+ return status;\r
}\r
\r
static int stretch_blit(/*struct ipp_context *ctx,*/ unsigned long arg ,unsigned int cmd)\r
{\r
atomic_set(&drvdata->ipp_event, 0);\r
}\r
- //Èç¹ûÓ¦ÓòãÏ·¢ÇëÇóºóûÓÐÀ´get result£¬idle_conditionΪ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
\r
drvdata->ipp_result = -EAGAIN;\r
}\r
\r
- //´ú±íÓ²¼þͬӲ¼þ½»»¥Íê³É\r
+ //interacting with hardware done\r
wq_condition = 1;\r
\r
\r
drvdata->ipp_irq_callback(drvdata->ipp_result);\r
//drvdata->ipp_irq_callback(temp);\r
\r
- //Èç¹ûÊÇÄÚºË̬µÄÒì²½µ÷Óã¬ÔòÔڴ˾ͻ½Ðѵȴý¶ÓÁУ»Èç¹ûÊÇÓû§Ì¬µÄÒì²½µ÷Óã¬Òªµ½get_resultÍê³Éºó²ÅÄÜ»½ÐÑ\r
+\r
+ //In the case of async call in kernel space,we wake up the wait queue here\r
+ //In the case of async call in user space, we will wake up the wait queue until app get the result\r
if(drvdata->ipp_irq_callback != ipp_blit_complete)\r
{\r
idle_condition = 1;\r
static int ipp_suspend(struct platform_device *pdev, pm_message_t state)\r
{\r
//printk("ipp_suspend\n");\r
- //ÑÓʱ20msÈ·±£Ó²¼þ¹¤×÷Íê³É\r
+ //delay 20ms to wait hardware work completed\r
mdelay(20);\r
- //È¡Ïûpower_offµÄ¹¤×÷¶ÓÁУ¬Á¢¼´poweroff\r
+\r
+ //cancel the delay work, power off right now\r
cancel_delayed_work_sync(&drvdata->power_off_work);\r
ipp_power_off(NULL);\r
\r
static int ipp_resume(struct platform_device *pdev)\r
{\r
//printk("ipp_resume\n");\r
- //Èç¹ûsuspandǰ´¦ÓÚ¹¤×÷״̬£¬Ôòresumeºópower on\r
+ //If IPP is woring before suspending, we power it on now\r
if (!wq_condition) \r
{\r
drvdata->enable = false;\r
printk("test ipp_blit_async over!!!\n");\r
*/\r
\r
- /*3.Á¬ÐøÏ·¢Á½¸öÒì²½ÇëÇ󣬵ڶþ´ÎµÄÇëÇóÒªÔÚµÚÒ»´Î·µ»Øºó²Å»áÖ´ÐС£²¢ÇÒÁ½´ÎÇëÇóÈ¡»ØµÄÊǸ÷×ԵĽá¹û*/\r
+ /*3.two async req,get the rigt result respectively*/\r
+ \r
/*\r
[ 10.253532] ipp_blit_async\r
[ 10.256210] ipp_blit_async2\r
[ 10.259000] ipp_blit_async\r
[ 10.261700] ipp_test_complete retval=0\r
[ 10.282832] ipp_blit_async2\r
- [ 10.284304] ipp_test_complete retval=1 Á½´ÎÇëÇó·Ö±ðÈ¡»ØÁ˲»Í¬µÄ½á¹û£¬ÄÚºËÖÐÁ½¸öÓ¦ÓÃͬʱÒì²½µ÷ÓÃok\r
+ [ 10.284304] ipp_test_complete retval=1 \r
*/\r
/*\r
ret1 = ipp_blit_async(&ipp_req);\r
ret2 = ipp_blit_async(&ipp_req);\r
*/\r
\r
- /*4 Á¬ÐøÏ·¢Á½¸öͬ²½ÇëÇó,µÚ¶þ´ÎµÄÇëÇóÔÚµÚÒ»´Î½áÊøºó²ÅÖ´ÐÐ,²¢ÇÒÁ½´ÎÇëÇóÈ¡»ØÁ˸÷×ԵĽá¹û*/\r
+ /*4 two sync req,get the rigt result respectively*/\r
/*\r
[ 10.703628] ipp_blit_async\r
[ 10.711211] wait_event_interruptible waitret= 0\r
ret1 = ipp_blit_sync(&ipp_req);\r
ret2 = ipp_blit_sync(&ipp_req);*/\r
\r
- /*5.ÏÈÒì²½ºóͬ²½*/\r
+ /*5*/\r
/*\r
ret1 = ipp_blit_async(&ipp_req);\r
ret2 = ipp_blit_sync(&ipp_req); \r
ret2 = ipp_blit_async(&ipp_req);\r
*/\r
\r
- /*6.ÄÚºËͬ²½µ÷Óã¬ÅäºÏÓû§Ì¬Òì²½µ÷ÓÃ*/\r
+ /*6.call IPP driver in the kernel space and the user space at the same time*/\r
\r
do\r
{\r