From: chenli Date: Tue, 28 Jun 2011 06:39:32 +0000 (+0800) Subject: rk29 IPP:IPP driver provides synchronous and asynchronous call interfaces. X-Git-Tag: firefly_0821_release~10164^2~2 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=2abd490402001c5fc1d3d45ace3244c7b86e8f92;p=firefly-linux-kernel-4.4.55.git rk29 IPP:IPP driver provides synchronous and asynchronous call interfaces. 1.In the case of synchronous call please use ipp_blit_sync function. In the case of asynchronous call please use ipp_blit_async function. The old interface ipp_do_blit is obsolete! 2.Use ipp_blit_sync instead of ipp_do_blit in rk29_fb.c and rk29_camera_oneframe.c. 3.Translate the Chinese commets into English. --- diff --git a/arch/arm/mach-rk29/include/mach/rk29-ipp.h b/arch/arm/mach-rk29/include/mach/rk29-ipp.h index 2256576afbb6..7cedaa01d63a 100755 --- a/arch/arm/mach-rk29/include/mach/rk29-ipp.h +++ b/arch/arm/mach-rk29/include/mach/rk29-ipp.h @@ -27,7 +27,6 @@ struct rk29_ipp_req { uint32_t timeout; uint32_t flag; //rotate - //chenli 0506 //deinterlace_enable 1:enable 0:disable uint8_t deinterlace_enable; //the sum of three paras should be 32,and single para should be less than 32 @@ -40,7 +39,7 @@ struct rk29_ipp_req { }; -//uint32_t format ö¾ÙÀàÐÍ +//format enum enum { IPP_XRGB_8888 = 0, @@ -118,7 +117,7 @@ typedef enum (img == IPP_XRGB_8888) )) #define HAS_ALPHA(img) (img == IPP_ARGB_8888) -int ipp_do_blit(struct rk29_ipp_req *req); + int ipp_blit_async(const struct rk29_ipp_req *req); int ipp_blit_sync(const struct rk29_ipp_req *req); #endif /*_RK29_IPP_DRIVER_H_*/ \ No newline at end of file diff --git a/drivers/media/video/rk29_camera_oneframe.c b/drivers/media/video/rk29_camera_oneframe.c index 18cab18a38c0..e76d72f7d33f 100755 --- a/drivers/media/video/rk29_camera_oneframe.c +++ b/drivers/media/video/rk29_camera_oneframe.c @@ -479,7 +479,8 @@ static void rk29_camera_capture_process(struct work_struct *work) ipp_req.timeout = 100; ipp_req.flag = IPP_ROT_0; - if (ipp_do_blit(&ipp_req)) { + //if (ipp_do_blit(&ipp_req)) { + if (ipp_blit_sync(&ipp_req)) { spin_lock_irqsave(&pcdev->lock, flags); vb->state = VIDEOBUF_ERROR; spin_unlock_irqrestore(&pcdev->lock, flags); diff --git a/drivers/staging/rk29/ipp/rk29-ipp.c b/drivers/staging/rk29/ipp/rk29-ipp.c index 4c2816cb0550..dd9ca8b39ca6 100755 --- a/drivers/staging/rk29/ipp/rk29-ipp.c +++ b/drivers/staging/rk29/ipp/rk29-ipp.c @@ -81,20 +81,20 @@ struct ipp_drvdata { struct mutex mutex; // mutex struct delayed_work power_off_work; - wait_queue_head_t ipp_wait; //pollʱµÄµÈ´ý¶ÓÁÐ + wait_queue_head_t ipp_wait; atomic_t ipp_event; - bool issync; //ÊÇͬ²½µ÷Óû¹ÊÇÒì²½µ÷Óà - bool enable; //IPPÊÇ·ñʹÄÜÁËclk - int ipp_result; //´æ·Åµ±Ç°IPP²Ù×÷µÄ½á¹û£¬0´ú±í³É¹¦ - void (*ipp_irq_callback)(int ipp_retval); //Òì²½µ÷ÓõĻص÷º¯Êý + bool issync; //sync or async + bool enable; //clk enable or disable + int ipp_result; //0:success + void (*ipp_irq_callback)(int ipp_retval); //callback function used by aync call }; static struct ipp_drvdata *drvdata = NULL; static DECLARE_WAIT_QUEUE_HEAD(hw_wait_queue); -static volatile int wq_condition = 1; //ͬӲ¼þ½»»¥Ê±1£¬Í¬Ó²¼þ½»»¥Íê³É0 +static volatile int wq_condition = 1; //0:interact with hardware static DECLARE_WAIT_QUEUE_HEAD(blit_wait_queue); -static volatile int idle_condition = 1; //ÔÊÐíÖ´ÐÐÏÂÒ»¸öÇëÇó1£¬µ±Ç°ÇëÇóÕýÔÚÖ´ÐÐ0 +static volatile int idle_condition = 1; //1:idel, 0:busy /* Context data (unique) */ @@ -290,8 +290,8 @@ int ipp_blit(const struct rk29_ipp_req *req) uint32_t pre_scale_w, pre_scale_h;//pre_scale para uint32_t post_scale_w = 0x1000; uint32_t post_scale_h = 0x1000; - uint32_t pre_scale_output_w=0, pre_scale_output_h=0;//pre_scaleµÄÊä³ö¿í¸ß - uint32_t post_scale_input_w, post_scale_input_h;//post_scaleµÄÊäÈë¿í¸ß + uint32_t pre_scale_output_w=0, pre_scale_output_h=0;//pre_scale output with&height + uint32_t post_scale_input_w, post_scale_input_h;//post_scale input width&height uint32_t dst0_YrgbMst=0,dst0_CbrMst=0; uint32_t ret = 0; uint32_t deinterlace_config = 0; @@ -304,7 +304,7 @@ int ipp_blit(const struct rk29_ipp_req *req) drvdata->ipp_result = -1; - //ͬ²½µÄÇé¿öÏÂreq->complete¶¼Ó¦¸ÃΪNULL£¬¶øÒì²½µÄÇé¿öÏÂÓû§Ì¬µ÷ÓõÄreq->completeҲΪNULL£¬ÄÚºË̬µ÷ÓõÄreq->completeÓ¦·Ç¿Õ + //When ipp_blit_async is called in kernel space req->complete should NOt be NULL, otherwise req->complete should be NULL if(req->complete) { drvdata->ipp_irq_callback = req->complete; @@ -508,7 +508,7 @@ int ipp_blit(const struct rk29_ipp_req *req) break; } - //ÏÖÔÚ¿ªÊ¼Ó²¼þ¿ªÊ¼¹¤×÷ + //we start to interact with hw now wq_condition = 0; ipp_power_on(); @@ -630,7 +630,7 @@ int ipp_blit(const struct rk29_ipp_req *req) } } - if((req->src0.w%pre_scale_w)!=0) //ÏòÉÏÈ¡Õû ceil + if((req->src0.w%pre_scale_w)!=0) //ceil { pre_scale_output_w = req->src0.w/pre_scale_w+1; } @@ -639,7 +639,7 @@ int ipp_blit(const struct rk29_ipp_req *req) pre_scale_output_w = req->src0.w/pre_scale_w; } - if((req->src0.h%pre_scale_h)!=0)//ÏòÉÏÈ¡Õû ceil + if((req->src0.h%pre_scale_h)!=0)//ceil { pre_scale_output_h = req->src0.h/pre_scale_h +1; } @@ -662,9 +662,9 @@ int ipp_blit(const struct rk29_ipp_req *req) /*Configure Post_scale*/ if((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate)) { - if (( (req->src0.h%req->dst0.w)!=0)||( (req->src0.w%req->dst0.h)!= 0)//СÊý±¶ËõС - ||((req->src0.h/req->dst0.w)>8)||((req->src0.h%req->dst0.w)>8) //ËõСϵÊý´óÓÚ8 - ||(req->dst0.w > req->src0.h) ||(req->dst0.h > req->src0.w)) //·Å´ó + if (( (req->src0.h%req->dst0.w)!=0)||( (req->src0.w%req->dst0.h)!= 0)//non-interger down-scaling + ||((req->src0.h/req->dst0.w)>8)||((req->src0.h%req->dst0.w)>8) //down-scaling ratio > 8 + ||(req->dst0.w > req->src0.h) ||(req->dst0.h > req->src0.w)) //up-scaling { post_scale = 1; @@ -676,9 +676,9 @@ int ipp_blit(const struct rk29_ipp_req *req) } else //0 180 x-flip y-flip { - if (( (req->src0.w%req->dst0.w)!=0)||( (req->src0.h%req->dst0.h)!= 0)//СÊý±¶ËõС - ||((req->src0.w/req->dst0.w)>8)||((req->src0.h%req->dst0.h)>8) //ËõСϵÊý´óÓÚ8 - ||(req->dst0.w > req->src0.w) ||(req->dst0.h > req->src0.h)) //·Å´ó + if (( (req->src0.w%req->dst0.w)!=0)||( (req->src0.h%req->dst0.h)!= 0)//non-interger down-scaling + ||((req->src0.w/req->dst0.w)>8)||((req->src0.h%req->dst0.h)>8) //down-scaling ratio > 8 + ||(req->dst0.w > req->src0.w) ||(req->dst0.h > req->src0.h)) //up-scaling { post_scale = 1; } @@ -874,7 +874,7 @@ int ipp_blit_async(const struct rk29_ipp_req *req) int ret = -1; //printk("ipp_blit_async *******************\n"); - //Èç¹û´ËʱIPPÔÚÖ´ÐÐÒ»¸öÇëÇ󣬵ȴýIPP¿ÕÏÐ + //If IPP is busy now,wait until it becomes idle mutex_lock(&drvdata->mutex); { dmac_inv_range((const void*)&idle_condition,(const void*)&idle_condition+4); @@ -900,7 +900,7 @@ int ipp_blit_sync(const struct rk29_ipp_req *req) //printk("ipp_blit_sync -------------------\n"); - //Èç¹û´ËʱIPPÔÚÖ´ÐÐÒ»¸öÇëÇ󣬵ȴýIPP¿ÕÏÐ + ////If IPP is busy now,wait until it becomes idle mutex_lock(&drvdata->mutex); { dmac_inv_range((const void*)&idle_condition,(const void*)&idle_condition+4); @@ -969,826 +969,14 @@ int ipp_blit_sync(const struct rk29_ipp_req *req) } drvdata->issync = false; - //ͬ²½µ÷ÓÃÔÚ´ËÈÏΪIPPÒѾ­¿ÕÏУ¬»½Ðѵȴý¶ÓÁÐ - //printk("ipp_blit_sync done ----------------\n"); - status = drvdata->ipp_result; - idle_condition = 1; - wake_up_interruptible_sync(&blit_wait_queue); - - return status; -} - -int ipp_do_blit(struct rk29_ipp_req *req) -{ - uint32_t rotate; - uint32_t pre_scale = 0; - uint32_t post_scale = 0; - uint32_t pre_scale_w, pre_scale_h;//pre_scale para - uint32_t post_scale_w = 0x1000; - uint32_t post_scale_h = 0x1000; - uint32_t pre_scale_output_w=0, pre_scale_output_h=0;//pre_scaleµÄÊä³ö¿í¸ß - uint32_t post_scale_input_w, post_scale_input_h;//post_scaleµÄÊäÈë¿í¸ß - uint32_t dst0_YrgbMst=0,dst0_CbrMst=0; - uint32_t ret = 0; - uint32_t deinterlace_config = 0; - int wait_ret; - - mutex_lock(&drvdata->mutex); - - if (drvdata == NULL) { /* ddl@rock-chips.com : check driver is normal or not */ - //printk(KERN_ERR, "%s drvdata is NULL, IPP driver probe is fail!!\n", __FUNCTION__); - printk("%s drvdata is NULL, IPP driver probe is fail!!\n", __FUNCTION__); - return -EPERM; - } - - - /*IPP can support up to 8191*8191 resolution in RGB format,but we limit the image size to 8190*8190 here*/ - //check src width and height - if (unlikely((req->src0.w <16) || (req->src0.w > 8190) || (req->src0.h < 16) || (req->src0.h > 8190))) { - ERR("invalid source resolution\n"); - ret = -EINVAL; - goto erorr_input; - } - - //check dst width and height - if (unlikely((req->dst0.w <16) || (req->dst0.w > 2047) || (req->dst0.h < 16) || (req->dst0.h > 2047))) { - ERR("invalid destination resolution\n"); - ret = -EINVAL; - goto erorr_input; - } - - //check src address - if (unlikely(req->src0.YrgbMst== 0) ) - { - ERR("could not retrieve src image from memory\n"); - ret = -EINVAL; - goto erorr_input; - } - - //check src address - if (unlikely(req->dst0.YrgbMst== 0) ) - { - ERR("could not retrieve dst image from memory\n"); - ret = -EINVAL; - goto erorr_input; - } - //check rotate degree - if(req->flag >= IPP_ROT_LIMIT) - { - ERR("rk29_ipp is not surpport rot degree!!!!\n"); - ret = -EINVAL; - goto erorr_input; - } - - - rotate = req->flag; - switch (rotate) { - case IPP_ROT_90: - //for rotation 90 degree - DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt); - switch(req->src0.fmt) - { - case IPP_XRGB_8888: - dst0_YrgbMst = req->dst0.YrgbMst + req->dst0.w*4; - dst0_CbrMst = req->dst0.CbrMst; - break; - - case IPP_RGB_565: - dst0_YrgbMst = req->dst0.YrgbMst + req->dst0.w*2; - dst0_CbrMst = req->dst0.CbrMst; - break; - - case IPP_Y_CBCR_H1V1: - dst0_YrgbMst = req->dst0.YrgbMst + req->dst0.w; - dst0_CbrMst = req->dst0.CbrMst + req->dst0.w*2; - break; - - case IPP_Y_CBCR_H2V1: - dst0_YrgbMst = req->dst0.YrgbMst + req->dst0.w; - dst0_CbrMst = req->dst0.CbrMst + req->dst0.w*2; - break; - - case IPP_Y_CBCR_H2V2: - dst0_YrgbMst = req->dst0.YrgbMst+ req->dst0.w; - dst0_CbrMst = req->dst0.CbrMst + req->dst0.w; - break; - - default: - - break; - } - break; - - case IPP_ROT_180: - //for rotation 180 degree - DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt); - switch(req->src0.fmt) - { - case IPP_XRGB_8888: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*4+req->dst0.w*4; - dst0_CbrMst = req->dst0.CbrMst; - break; - - case IPP_RGB_565: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*2+req->dst0.w*2; - dst0_CbrMst = req->dst0.CbrMst; - break; - - case IPP_Y_CBCR_H1V1: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w; - dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2+req->dst0.w*2; - break; - - case IPP_Y_CBCR_H2V1: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w; - dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w; - break; - - case IPP_Y_CBCR_H2V2: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w+req->dst0.w; - dst0_CbrMst = req->dst0.CbrMst+((req->dst0.h/2)-1)*req->dst_vir_w+req->dst0.w; - break; - - default: - break; - } - break; - - case IPP_ROT_270: - DBG("rotate %d, src0.fmt %d \n",rotate,req->src0.fmt); - switch(req->src0.fmt) - { - case IPP_XRGB_8888: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*4; - dst0_CbrMst = req->dst0.CbrMst; - break; - - case IPP_RGB_565: - dst0_YrgbMst = req->dst0.YrgbMst +(req->dst0.h-1)*req->dst_vir_w*2; - dst0_CbrMst = req->dst0.CbrMst; - break; - - case IPP_Y_CBCR_H1V1: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w; - dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2; - break; - - case IPP_Y_CBCR_H2V1: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w; - dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2; - break; - - case IPP_Y_CBCR_H2V2: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w; - dst0_CbrMst = req->dst0.CbrMst+((req->dst0.h/2)-1)*req->dst_vir_w; - break; - - default: - break; - } - break; - - case IPP_ROT_X_FLIP: - DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt); - switch(req->src0.fmt) - { - case IPP_XRGB_8888: - dst0_YrgbMst = req->dst0.YrgbMst+req->dst0.w*4; - dst0_CbrMst = req->dst0.CbrMst; - break; - - case IPP_RGB_565: - dst0_YrgbMst = req->dst0.YrgbMst+req->dst0.w*2; - dst0_CbrMst = req->dst0.CbrMst; - break; - - case IPP_Y_CBCR_H1V1: - dst0_YrgbMst = req->dst0.YrgbMst+req->dst0.w; - dst0_CbrMst = req->dst0.CbrMst+req->dst0.w*2; - break; - - case IPP_Y_CBCR_H2V1: - dst0_YrgbMst = req->dst0.YrgbMst+req->dst0.w; - dst0_CbrMst = req->dst0.CbrMst+req->dst0.w; - break; - - case IPP_Y_CBCR_H2V2: - dst0_YrgbMst = req->dst0.YrgbMst+req->dst0.w; - dst0_CbrMst = req->dst0.CbrMst+req->dst0.w; - break; - - default: - break; - } - - break; - - case IPP_ROT_Y_FLIP: - DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt); - switch(req->src0.fmt) - { - case IPP_XRGB_8888: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*4; - dst0_CbrMst = req->dst0.CbrMst; - break; - - case IPP_RGB_565: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w*2; - dst0_CbrMst = req->dst0.CbrMst; - break; - - case IPP_Y_CBCR_H1V1: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w; - dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w*2; - break; - - case IPP_Y_CBCR_H2V1: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w; - dst0_CbrMst = req->dst0.CbrMst+(req->dst0.h-1)*req->dst_vir_w; - break; - - case IPP_Y_CBCR_H2V2: - dst0_YrgbMst = req->dst0.YrgbMst+(req->dst0.h-1)*req->dst_vir_w; - dst0_CbrMst = req->dst0.CbrMst+((req->dst0.h/2)-1)*req->dst_vir_w; - break; - - default: - break; - } - - break; - case IPP_ROT_0: - //for 0 degree - DBG("rotate %d, src0.fmt %d",rotate,req->src0.fmt); - dst0_YrgbMst = req->dst0.YrgbMst; - dst0_CbrMst = req->dst0.CbrMst; - break; - - default: - ERR("ipp is not surpport degree!!\n" ); - break; - } - - //enable clk - if(drvdata->pd_display) - { - clk_enable(drvdata->pd_display); - } - else - { - printk("pd_display is null \n"); - ret = -EINVAL; - goto error_pd_display; - } - - if(drvdata->aclk_lcdc) - { - clk_enable(drvdata->aclk_lcdc); - } - else - { - printk("aclk_lcdc is null \n"); - ret = -EINVAL; - goto error_aclk_lcdc; - } - - if(drvdata->hclk_lcdc) - { - clk_enable(drvdata->hclk_lcdc); - } - else - { - printk("hclk_lcdc is null \n"); - ret = -EINVAL; - goto error_hclk_lcdc; - } - - if(drvdata->aclk_ddr_lcdc) - { - clk_enable(drvdata->aclk_ddr_lcdc); - } - else - { - printk("aclk_ddr_lcdc is null \n"); - ret = -EINVAL; - goto error_aclk_ddr_lcdc; - } - - if(drvdata->hclk_cpu_display) - { - clk_enable(drvdata->hclk_cpu_display); - } - else - { - printk("hclk_cpu_display is null \n"); - ret = -EINVAL; - goto error_hclk_cpu_display; - } - - if(drvdata->aclk_disp_matrix) - { - clk_enable(drvdata->aclk_disp_matrix); - } - else - { - printk("aclk_disp_matrix is null \n"); - ret = -EINVAL; - goto error_aclk_disp_matrix; - } - - if(drvdata->hclk_disp_matrix) - { - clk_enable(drvdata->hclk_disp_matrix); - } - else - { - printk("hclk_disp_matrix is null \n"); - ret = -EINVAL; - goto error_hclk_disp_matrix; - } - - if(drvdata->axi_clk) - { - clk_enable(drvdata->axi_clk); - } - else - { - printk("axi_clk is null \n"); - ret = -EINVAL; - goto error_axi_clk; - } - - if(drvdata->ahb_clk) - { - clk_enable(drvdata->ahb_clk); - } - else - { - printk("ahb_clk is null \n"); - ret = -EINVAL; - goto error_ahb_clk; - } - //enable clk end - - //check if IPP is idle - if(((ipp_read(IPP_INT)>>6)&0x3) !=0)// idle - { - printk("IPP staus is not idle,can noe set register\n"); - goto error_status; - } - - - /* Configure source image */ - DBG("src YrgbMst 0x%x , CbrMst0x%x, %dx%d, fmt = %d\n", req->src0.YrgbMst,req->src0.CbrMst, - req->src0.w, req->src0.h, req->src0.fmt); - - ipp_write(req->src0.YrgbMst, IPP_SRC0_Y_MST); - if(IS_YCRCB(req->src0.fmt)) - { - ipp_write(req->src0.CbrMst, IPP_SRC0_CBR_MST); - } - ipp_write(req->src0.h<<16|req->src0.w, IPP_SRC_IMG_INFO); - ipp_write((ipp_read(IPP_CONFIG)&(~0x7))|req->src0.fmt, IPP_CONFIG); - - /* Configure destination image */ - DBG("dst YrgbMst 0x%x , CbrMst0x%x, %dx%d\n", dst0_YrgbMst,dst0_CbrMst, - req->dst0.w, req->dst0.h); - - ipp_write(dst0_YrgbMst, IPP_DST0_Y_MST); - - if(IS_YCRCB(req->src0.fmt)) - { - ipp_write(dst0_CbrMst, IPP_DST0_CBR_MST); - } - - ipp_write(req->dst0.h<<16|req->dst0.w, IPP_DST_IMG_INFO); - - /*Configure Pre_scale*/ - if((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate)) - { - pre_scale = ((req->dst0.w < req->src0.h) ? 1 : 0)||((req->dst0.h < req->src0.w) ? 1 : 0); - } - else //other degree - { - pre_scale = ((req->dst0.w < req->src0.w) ? 1 : 0)||((req->dst0.h < req->src0.h) ? 1 : 0); - } - - if(pre_scale) - { - if(((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate))) - { - - if((req->src0.w>req->dst0.h)) - { - pre_scale_w = (uint32_t)( req->src0.w/req->dst0.h);//floor - } - else - { - pre_scale_w = 1; - } - if((req->src0.h>req->dst0.w)) - { - pre_scale_h = (uint32_t)( req->src0.h/req->dst0.w);//floor - } - else - { - pre_scale_h = 1; - } - - DBG("!!!!!pre_scale_h %d,pre_scale_w %d \n",pre_scale_h,pre_scale_w); - } - else//0 180 x ,y - { - - if((req->src0.w>req->dst0.w)) - { - pre_scale_w = (uint32_t)( req->src0.w/req->dst0.w);//floor - } - else - { - pre_scale_w = 1; - } - - if((req->src0.h>req->dst0.h)) - { - pre_scale_h = (uint32_t)( req->src0.h/req->dst0.h);//floor - } - else - { - pre_scale_h = 1; - } - DBG("!!!!!pre_scale_h %d,pre_scale_w %d \n",pre_scale_h,pre_scale_w); - } - - //pre_scale only support 1/2 to 1/8 time - if(pre_scale_w > 8) - { - if(pre_scale_w < 16) - { - pre_scale_w = 8; - } - else - { - printk("invalid pre_scale operation! pre_scale_w should not be more than 8!\n"); - goto error_scale; - } - } - if(pre_scale_h > 8) - { - if(pre_scale_h < 16) - { - pre_scale_h = 8; - } - else - { - printk("invalid pre_scale operation! pre_scale_h should not be more than 8!\n"); - goto error_scale; - } - } - - if((req->src0.w%pre_scale_w)!=0) //ÏòÉÏÈ¡Õû ceil - { - pre_scale_output_w = req->src0.w/pre_scale_w+1; - } - else - { - pre_scale_output_w = req->src0.w/pre_scale_w; - } - - if((req->src0.h%pre_scale_h)!=0)//ÏòÉÏÈ¡Õû ceil - { - pre_scale_output_h = req->src0.h/pre_scale_h +1; - } - else - { - pre_scale_output_h = req->src0.h/pre_scale_h; - } - - ipp_write((ipp_read(IPP_CONFIG)&0xffffffef)|PRE_SCALE, IPP_CONFIG); //enable pre_scale - ipp_write((pre_scale_h-1)<<3|(pre_scale_w-1),IPP_PRE_SCL_PARA); - ipp_write(((pre_scale_output_h)<<16)|(pre_scale_output_w), IPP_PRE_IMG_INFO); - - } - else//no pre_scale - { - ipp_write(0,IPP_PRE_SCL_PARA); - ipp_write((req->src0.h<<16)|req->src0.w, IPP_PRE_IMG_INFO); - } - - /*Configure Post_scale*/ - if((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate)) - { - if (( (req->src0.h%req->dst0.w)!=0)||( (req->src0.w%req->dst0.h)!= 0)//СÊý±¶ËõС - ||((req->src0.h/req->dst0.w)>8)||((req->src0.h%req->dst0.w)>8) //ËõСϵÊý´óÓÚ8 - ||(req->dst0.w > req->src0.h) ||(req->dst0.h > req->src0.w)) //·Å´ó - - { - post_scale = 1; - } - else - { - post_scale = 0; - } - } - else //0 180 x-flip y-flip - { - if (( (req->src0.w%req->dst0.w)!=0)||( (req->src0.h%req->dst0.h)!= 0)//СÊý±¶ËõС - ||((req->src0.w/req->dst0.w)>8)||((req->src0.h%req->dst0.h)>8) //ËõСϵÊý´óÓÚ8 - ||(req->dst0.w > req->src0.w) ||(req->dst0.h > req->src0.h)) //·Å´ó - { - post_scale = 1; - } - else - { - post_scale = 0; - } - } - - if(post_scale) - { - if(pre_scale) - { - post_scale_input_w = pre_scale_output_w; - post_scale_input_h = pre_scale_output_h; - } - else - { - post_scale_input_w = req->src0.w; - post_scale_input_h = req->src0.h; - } - - if((IPP_ROT_90 == rotate) || (IPP_ROT_270 == rotate)) - { - DBG("post_scale_input_w %d ,post_scale_input_h %d !!!\n",post_scale_input_w,post_scale_input_h); - - switch(req->src0.fmt) - { - case IPP_XRGB_8888: - case IPP_RGB_565: - case IPP_Y_CBCR_H1V1: - //In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer - if(((4096*(post_scale_input_w-1))%(req->dst0.h-1))==0) - { - post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.h-1))-1; - } - else - { - post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.h-1)); - } - break; - - case IPP_Y_CBCR_H2V1: - case IPP_Y_CBCR_H2V2: - //In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer - if(((4096*(post_scale_input_w/2-1))%(req->dst0.h/2-1))==0) - { - post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.h/2-1))-1; - } - else - { - post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.h/2-1)); - } - break; - - default: - break; - } - post_scale_h = (uint32_t)(4096*(post_scale_input_h -1)/(req->dst0.w-1)); - - DBG("1111 post_scale_w %x,post_scale_h %x!!! \n",post_scale_w,post_scale_h); - } - else// 0 180 x-flip y-flip - { - switch(req->src0.fmt) - { - case IPP_XRGB_8888: - case IPP_RGB_565: - case IPP_Y_CBCR_H1V1: - //In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer - if(((4096*(post_scale_input_w-1))%(req->dst0.w-1))==0) - { - post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.w-1))-1; - } - else - { - post_scale_w = (uint32_t)(4096*(post_scale_input_w-1)/(req->dst0.w-1)); - } - break; - - case IPP_Y_CBCR_H2V1: - case IPP_Y_CBCR_H2V2: - ////In horiaontial scale case, the factor must be minus 1 if the result of the factor is integer - if(((4096*(post_scale_input_w/2-1))%(req->dst0.w/2-1))==0) - { - post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.w/2-1))-1; - } - else - { - post_scale_w = (uint32_t)(4096*(post_scale_input_w/2-1)/(req->dst0.w/2-1)); - } - break; - - default: - break; - } - post_scale_h = (uint32_t)(4096*(post_scale_input_h -1)/(req->dst0.h-1)); - - } - if(!((req->src0.fmt != IPP_Y_CBCR_H2V1)&&(req->src0.w == 176)&&(req->src0.h == 144)&&(req->dst0.w == 480)&&(req->dst0.h == 800))) - { - //only support 1/2 to 4 times scaling,but 176*144->480*800 can pass - if(post_scale_w<0x3ff || post_scale_w>0x1fff || post_scale_h<0x400 || post_scale_h>0x2000 ) - { - printk("invalid post_scale para!\n"); - goto error_scale; - } - } - ipp_write((ipp_read(IPP_CONFIG)&0xfffffff7)|POST_SCALE, IPP_CONFIG); //enable post_scale - ipp_write((post_scale_h<<16)|post_scale_w, IPP_POST_SCL_PARA); - } - else //no post_scale - { - DBG("no post_scale !!!!!! \n"); - ipp_write(ipp_read(IPP_CONFIG)&(~POST_SCALE), IPP_CONFIG); //disable post_scale - ipp_write((post_scale_h<<16)|post_scale_w, IPP_POST_SCL_PARA); - } - - /* Configure rotation */ - - if(IPP_ROT_0 == req->flag) - { - ipp_write(ipp_read(IPP_CONFIG)&(~ROT_ENABLE), IPP_CONFIG); - } - else - { - ipp_write(ipp_read(IPP_CONFIG)|ROT_ENABLE, IPP_CONFIG); - ipp_write(ipp_read(IPP_CONFIG)|rotate<<5, IPP_CONFIG); - } - - /*Configure deinterlace*/ - if(req->deinterlace_enable == 1) - { - //only support YUV format - if(IS_YCRCB(req->src0.fmt)) - { - //If pre_scale is enable, Deinterlace is done by scale filter - if(!pre_scale) - { - //check the deinterlace parameters - if((req->deinterlace_para0 < 32) && (req->deinterlace_para1 < 32) && (req->deinterlace_para2 < 32) - && ((req->deinterlace_para0 + req->deinterlace_para1 + req->deinterlace_para2) == 32)) - { - deinterlace_config = (req->deinterlace_enable<<24) | (req->deinterlace_para0<<19) | (req->deinterlace_para1<<14) | (req->deinterlace_para2<<9); - DBG("para0 %d, para1 %d, para2 %d,deinterlace_config %x\n",req->deinterlace_para0,req->deinterlace_para1,req->deinterlace_para2,deinterlace_config); - ipp_write((ipp_read(IPP_CONFIG)&0xFE0001FF)|deinterlace_config, IPP_CONFIG); - - //printk("IPP_CONFIG2 = 0x%x\n",ipp_read(IPP_CONFIG)); - } - else - { - ERR("invalid deinterlace parameters!\n"); - } - } - } - else - { - ERR("only support YUV format!\n"); - } - } - - /*Configure other*/ - ipp_write((req->dst_vir_w<<16)|req->src_vir_w, IPP_IMG_VIR); - - if((req->src0.w%4) !=0) - ipp_write(ipp_read(IPP_CONFIG)|(1<<26), IPP_CONFIG);//store clip mode - - /* Start the operation */ - - ipp_write(8, IPP_INT);// - - //msleep(5000);//debug use - - wq_condition = 0; - dsb(); -#ifdef IPP_TEST - memset(&hw_set,0,sizeof(struct timeval)); - memset(&irq_ret,0,sizeof(struct timeval)); - memset(&irq_done,0,sizeof(struct timeval)); - memset(&wait_done,0,sizeof(struct timeval)); - do_gettimeofday(&hw_set); -#endif - - ipp_write(1, IPP_PROCESS_ST); - //Important!Without msleep,ipp driver may occupy too much CPU,this can lead the ipp interrupt to timeout - msleep(1); - - wait_ret = wait_event_interruptible_timeout(hw_wait_queue, wq_condition, msecs_to_jiffies(req->timeout)); - -#ifdef IPP_TEST - do_gettimeofday(&wait_done); - if ((((irq_ret.tv_sec - hw_set.tv_sec) * 1000 + (irq_ret.tv_usec - hw_set.tv_usec) / 1000) > 10) || - (((wait_done.tv_sec - irq_done.tv_sec) * 1000 + (wait_done.tv_usec - irq_done.tv_usec) / 1000) > 10)) { - printk("hw time: %8d irq time %8d\n", - ((irq_ret.tv_sec - hw_set.tv_sec) * 1000 + (irq_ret.tv_usec - hw_set.tv_usec) / 1000), - ((wait_done.tv_sec - irq_done.tv_sec) * 1000 + (wait_done.tv_usec - irq_done.tv_usec) / 1000)); - } -#endif - - - if (wait_ret <= 0) - { - printk("%s wait_event_timeout \n",__FUNCTION__); - -#ifdef IPP_TEST - //print all register's value - printk("wait_ret: %d\n", wait_ret); - printk("wq_condition: %d\n", wq_condition); - printk("IPP_CONFIG: %x\n",ipp_read(IPP_CONFIG)); - printk("IPP_SRC_IMG_INFO: %x\n",ipp_read(IPP_SRC_IMG_INFO)); - printk("IPP_DST_IMG_INFO: %x\n",ipp_read(IPP_DST_IMG_INFO)); - printk("IPP_IMG_VIR: %x\n",ipp_read(IPP_IMG_VIR)); - printk("IPP_INT: %x\n",ipp_read(IPP_INT)); - printk("IPP_SRC0_Y_MST: %x\n",ipp_read(IPP_SRC0_Y_MST)); - printk("IPP_SRC0_CBR_MST: %x\n",ipp_read(IPP_SRC0_CBR_MST)); - printk("IPP_SRC1_Y_MST: %x\n",ipp_read(IPP_SRC1_Y_MST)); - printk("IPP_SRC1_CBR_MST: %x\n",ipp_read(IPP_SRC1_CBR_MST)); - printk("IPP_DST0_Y_MST: %x\n",ipp_read(IPP_DST0_Y_MST)); - printk("IPP_DST0_CBR_MST: %x\n",ipp_read(IPP_DST0_CBR_MST)); - printk("IPP_DST1_Y_MST: %x\n",ipp_read(IPP_DST1_Y_MST)); - printk("IPP_DST1_CBR_MST: %x\n",ipp_read(IPP_DST1_CBR_MST)); - printk("IPP_PRE_SCL_PARA: %x\n",ipp_read(IPP_PRE_SCL_PARA)); - printk("IPP_POST_SCL_PARA: %x\n",ipp_read(IPP_POST_SCL_PARA)); - printk("IPP_SWAP_CTRL: %x\n",ipp_read(IPP_SWAP_CTRL)); - printk("IPP_PRE_IMG_INFO: %x\n",ipp_read(IPP_PRE_IMG_INFO)); - printk("IPP_AXI_ID: %x\n",ipp_read(IPP_AXI_ID)); - printk("IPP_SRESET: %x\n",ipp_read(IPP_SRESET)); - printk("IPP_PROCESS_ST: %x\n",ipp_read(IPP_PROCESS_ST)); - - while(1) - { - - } -#endif - - wq_condition = 0; - if(!drvdata) - { - printk("close clk 0! \n"); - ret = -EINVAL; - goto error_null; - } - ret = -EAGAIN; - goto error_timeout; - } - - - if(!drvdata) - { - printk("close clk! \n"); - ret = -EINVAL; - goto error_null; - } - - if(((ipp_read(IPP_INT)>>6)&0x3) ==0)// idle - { - goto error_noerror; - } - else - { - printk("rk29 ipp status is error!!!\n"); - ret = -EINVAL; - goto error_timeout; - } + //IPP is idle, wake up the wait queue + //printk("ipp_blit_sync done ----------------\n"); + status = drvdata->ipp_result; + idle_condition = 1; + wake_up_interruptible_sync(&blit_wait_queue); -error_status: -error_scale: -error_null: -error_timeout: - //soft rest - ipp_soft_reset(); -error_noerror: - clk_disable(drvdata->ahb_clk); -error_ahb_clk: - clk_disable(drvdata->axi_clk); -error_axi_clk: - clk_disable(drvdata->hclk_disp_matrix); -error_hclk_disp_matrix: - clk_disable(drvdata->aclk_disp_matrix); -error_aclk_disp_matrix: - clk_disable(drvdata->hclk_cpu_display); -error_hclk_cpu_display: - clk_disable(drvdata->aclk_ddr_lcdc); -error_aclk_ddr_lcdc: - clk_disable(drvdata->hclk_lcdc); -error_hclk_lcdc: - clk_disable(drvdata->aclk_lcdc); -error_aclk_lcdc: - clk_disable(drvdata->pd_display); -error_pd_display: -erorr_input: - mutex_unlock(&drvdata->mutex); - return ret; + return status; } static int stretch_blit(/*struct ipp_context *ctx,*/ unsigned long arg ,unsigned int cmd) @@ -1875,7 +1063,9 @@ static int ipp_release(struct inode *inode, struct file *file) { atomic_set(&drvdata->ipp_event, 0); } - //Èç¹ûÓ¦ÓòãÏ·¢ÇëÇóºóûÓÐÀ´get result£¬idle_conditionΪ0»áµ¼ÖÂÒÔºóµÄÇëÇóÎÞ·¨Ö´ÐÐ + + //If app has not got the result after sending the request,the situation of idle_condition equals 1 will block the next request. + //so we must set idle_condition 1 here. idle_condition = 1; wq_condition = 0; @@ -1906,7 +1096,7 @@ static irqreturn_t rk29_ipp_irq(int irq, void *dev_id) drvdata->ipp_result = -EAGAIN; } - //´ú±íÓ²¼þͬӲ¼þ½»»¥Íê³É + //interacting with hardware done wq_condition = 1; @@ -1926,7 +1116,9 @@ static irqreturn_t rk29_ipp_irq(int irq, void *dev_id) drvdata->ipp_irq_callback(drvdata->ipp_result); //drvdata->ipp_irq_callback(temp); - //Èç¹ûÊÇÄÚºË̬µÄÒì²½µ÷Óã¬ÔòÔڴ˾ͻ½Ðѵȴý¶ÓÁУ»Èç¹ûÊÇÓû§Ì¬µÄÒì²½µ÷Óã¬Òªµ½get_resultÍê³Éºó²ÅÄÜ»½ÐÑ + + //In the case of async call in kernel space,we wake up the wait queue here + //In the case of async call in user space, we will wake up the wait queue until app get the result if(drvdata->ipp_irq_callback != ipp_blit_complete) { idle_condition = 1; @@ -1942,9 +1134,10 @@ static irqreturn_t rk29_ipp_irq(int irq, void *dev_id) static int ipp_suspend(struct platform_device *pdev, pm_message_t state) { //printk("ipp_suspend\n"); - //ÑÓʱ20msÈ·±£Ó²¼þ¹¤×÷Íê³É + //delay 20ms to wait hardware work completed mdelay(20); - //È¡Ïûpower_offµÄ¹¤×÷¶ÓÁУ¬Á¢¼´poweroff + + //cancel the delay work, power off right now cancel_delayed_work_sync(&drvdata->power_off_work); ipp_power_off(NULL); @@ -1954,7 +1147,7 @@ static int ipp_suspend(struct platform_device *pdev, pm_message_t state) static int ipp_resume(struct platform_device *pdev) { //printk("ipp_resume\n"); - //Èç¹ûsuspandǰ´¦ÓÚ¹¤×÷״̬£¬Ôòresumeºópower on + //If IPP is woring before suspending, we power it on now if (!wq_condition) { drvdata->enable = false; @@ -2094,21 +1287,22 @@ uint32_t size = 8*1024*1024; printk("test ipp_blit_async over!!!\n"); */ - /*3.Á¬ÐøÏ·¢Á½¸öÒì²½ÇëÇ󣬵ڶþ´ÎµÄÇëÇóÒªÔÚµÚÒ»´Î·µ»Øºó²Å»áÖ´ÐС£²¢ÇÒÁ½´ÎÇëÇóÈ¡»ØµÄÊǸ÷×ԵĽá¹û*/ + /*3.two async req,get the rigt result respectively*/ + /* [ 10.253532] ipp_blit_async [ 10.256210] ipp_blit_async2 [ 10.259000] ipp_blit_async [ 10.261700] ipp_test_complete retval=0 [ 10.282832] ipp_blit_async2 - [ 10.284304] ipp_test_complete retval=1 Á½´ÎÇëÇó·Ö±ðÈ¡»ØÁ˲»Í¬µÄ½á¹û£¬ÄÚºËÖÐÁ½¸öÓ¦ÓÃͬʱÒì²½µ÷ÓÃok + [ 10.284304] ipp_test_complete retval=1 */ /* ret1 = ipp_blit_async(&ipp_req); ret2 = ipp_blit_async(&ipp_req); */ - /*4 Á¬ÐøÏ·¢Á½¸öͬ²½ÇëÇó,µÚ¶þ´ÎµÄÇëÇóÔÚµÚÒ»´Î½áÊøºó²ÅÖ´ÐÐ,²¢ÇÒÁ½´ÎÇëÇóÈ¡»ØÁ˸÷×ԵĽá¹û*/ + /*4 two sync req,get the rigt result respectively*/ /* [ 10.703628] ipp_blit_async [ 10.711211] wait_event_interruptible waitret= 0 @@ -2124,7 +1318,7 @@ uint32_t size = 8*1024*1024; ret1 = ipp_blit_sync(&ipp_req); ret2 = ipp_blit_sync(&ipp_req);*/ - /*5.ÏÈÒì²½ºóͬ²½*/ + /*5*/ /* ret1 = ipp_blit_async(&ipp_req); ret2 = ipp_blit_sync(&ipp_req); @@ -2132,7 +1326,7 @@ uint32_t size = 8*1024*1024; ret2 = ipp_blit_async(&ipp_req); */ - /*6.ÄÚºËͬ²½µ÷Óã¬ÅäºÏÓû§Ì¬Òì²½µ÷ÓÃ*/ + /*6.call IPP driver in the kernel space and the user space at the same time*/ do {