rk3368: iep driver compatible for both 32bits and 64bits userspace application.
authorAlpha Lin <alpha.lin@rock-chips.com>
Tue, 6 Jan 2015 06:24:01 +0000 (14:24 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Tue, 13 Jan 2015 01:21:04 +0000 (09:21 +0800)
Signed-off-by: Alpha Lin <alpha.lin@rock-chips.com>
drivers/video/rockchip/iep/iep.h
drivers/video/rockchip/iep/iep_drv.c

index 4f46de9d30fc0f6f4780bf67809462af81a14a72..8f5554fb5ce17d0d92926597228fc7bf3e67778d 100644 (file)
@@ -3,20 +3,50 @@
 
 #define IEP_IOC_MAGIC 'i'
 
-#define IEP_SET_PARAMETER_REQ                          _IOW(IEP_IOC_MAGIC, 1, unsigned long)
-#define IEP_SET_PARAMETER_DEINTERLACE                  _IOW(IEP_IOC_MAGIC, 2, unsigned long)
-#define IEP_SET_PARAMETER_ENHANCE                      _IOW(IEP_IOC_MAGIC, 3, unsigned long)
-#define IEP_SET_PARAMETER_CONVERT                      _IOW(IEP_IOC_MAGIC, 4, unsigned long)
-#define IEP_SET_PARAMETER_SCALE                                _IOW(IEP_IOC_MAGIC, 5, unsigned long)
-#define IEP_GET_RESULT_SYNC                            _IOW(IEP_IOC_MAGIC, 6, unsigned long)
-#define IEP_GET_RESULT_ASYNC                           _IOW(IEP_IOC_MAGIC, 7, unsigned long)
-#define IEP_SET_PARAMETER                              _IOW(IEP_IOC_MAGIC, 8, unsigned long)
-#define IEP_RELEASE_CURRENT_TASK                       _IOW(IEP_IOC_MAGIC, 9, unsigned long)
+#define IEP_SET_PARAMETER_REQ          _IOW(IEP_IOC_MAGIC, 1, unsigned long)
+#define IEP_SET_PARAMETER_DEINTERLACE  _IOW(IEP_IOC_MAGIC, 2, unsigned long)
+#define IEP_SET_PARAMETER_ENHANCE      _IOW(IEP_IOC_MAGIC, 3, unsigned long)
+#define IEP_SET_PARAMETER_CONVERT      _IOW(IEP_IOC_MAGIC, 4, unsigned long)
+#define IEP_SET_PARAMETER_SCALE                _IOW(IEP_IOC_MAGIC, 5, unsigned long)
+#define IEP_GET_RESULT_SYNC            _IOW(IEP_IOC_MAGIC, 6, unsigned long)
+#define IEP_GET_RESULT_ASYNC           _IOW(IEP_IOC_MAGIC, 7, unsigned long)
+#define IEP_SET_PARAMETER              _IOW(IEP_IOC_MAGIC, 8, unsigned long)
+#define IEP_RELEASE_CURRENT_TASK       _IOW(IEP_IOC_MAGIC, 9, unsigned long)
+
+#ifdef CONFIG_COMPAT
+#define COMPAT_IEP_SET_PARAMETER_REQ           _IOW(IEP_IOC_MAGIC, 1, u32)
+#define COMPAT_IEP_SET_PARAMETER_DEINTERLACE   _IOW(IEP_IOC_MAGIC, 2, u32)
+#define COMPAT_IEP_SET_PARAMETER_ENHANCE       _IOW(IEP_IOC_MAGIC, 3, u32)
+#define COMPAT_IEP_SET_PARAMETER_CONVERT       _IOW(IEP_IOC_MAGIC, 4, u32)
+#define COMPAT_IEP_SET_PARAMETER_SCALE         _IOW(IEP_IOC_MAGIC, 5, u32)
+#define COMPAT_IEP_GET_RESULT_SYNC             _IOW(IEP_IOC_MAGIC, 6, u32)
+#define COMPAT_IEP_GET_RESULT_ASYNC            _IOW(IEP_IOC_MAGIC, 7, u32)
+#define COMPAT_IEP_SET_PARAMETER               _IOW(IEP_IOC_MAGIC, 8, u32)
+#define COMPAT_IEP_RELEASE_CURRENT_TASK                _IOW(IEP_IOC_MAGIC, 9, u32)
+#endif
 
 /* Driver information */
 #define DRIVER_DESC            "IEP Device Driver"
 #define DRIVER_NAME            "iep"
 
+#define DEBUG
+#ifdef DEBUG
+#define iep_debug(level, fmt, args...)                         \
+       do {                                                    \
+               if (debug >= level)                             \
+                       pr_info("%s:%d: " fmt,                  \
+                                __func__, __LINE__, ##args);   \
+       } while (0)
+#else
+#define iep_debug(level, fmt, args...)
+#endif
+
+#define iep_debug_enter() vpu_debug(4, "enter\n")
+#define iep_debug_leave() vpu_debug(4, "leave\n")
+
+#define iep_err(fmt, args...)                          \
+               pr_err("%s:%d: " fmt, __func__, __LINE__, ##args)
+
 /* Logging */
 #define IEP_DEBUG 0
 #if IEP_DEBUG
@@ -120,22 +150,22 @@ enum {
 
 struct iep_img
 {
-       unsigned short act_w;         // act_width
-       unsigned short act_h;         // act_height
-       signed short   x_off;         // x offset for the vir,word unit
-       signed short   y_off;         // y offset for the vir,word unit
-
-       unsigned short vir_w;         //unit :pix 
-       unsigned short vir_h;         //unit :pix
-       unsigned int   format;
-       unsigned int  *mem_addr;
-       unsigned int  *uv_addr;
-       unsigned int  *v_addr;
-
-       unsigned char   rb_swap;//not be used
-       unsigned char   uv_swap;//not be used
-
-       unsigned char   alpha_swap;//not be used
+       u16 act_w;      /* act_width */
+       u16 act_h;      /* act_height */
+       s16 x_off;      /* x offset for the vir,word unit */
+       s16 y_off;      /* y offset for the vir,word unit */
+
+       u16 vir_w;      /* unit :pix */
+       u16 vir_h;      /* unit :pix */
+       u32 format;
+       u32 mem_addr;
+       u32 uv_addr;
+       u32 v_addr;
+
+       u8 rb_swap;     /* not be used */
+       u8 uv_swap;     /* not be used */
+
+       u8 alpha_swap;  /* not be used */
 };
 
 
@@ -164,20 +194,20 @@ struct IEP_MSG {
        u8 yuv2rgb_clip_en;
 
        u8 lcdc_path_en;
-       int off_x;
-       int off_y;
-       int width;
-       int height;
-       int layer;
+       s32 off_x;
+       s32 off_y;
+       s32 width;
+       s32 height;
+       s32 layer;
 
        u8 yuv_3D_denoise_en;
 
        /* yuv color enhance */
        u8 yuv_enhance_en;
-       int sat_con_int;
-       int contrast_int;
-       int cos_hue_int;
-       int sin_hue_int;
+       s32 sat_con_int;
+       s32 contrast_int;
+       s32 cos_hue_int;
+       s32 sin_hue_int;
        s8 yuv_enh_brightness;  /*-32<brightness<31*/
        u8 video_mode;          /*0-3*/
        u8 color_bar_y; /*0-127*/
@@ -188,19 +218,19 @@ struct IEP_MSG {
        u8 rgb_enhance_en;/*i don't konw what is used*/
 
        u8 rgb_color_enhance_en;/*sw_rgb_color_enh_en*/
-       unsigned int rgb_enh_coe;
+       u32 rgb_enh_coe;
 
        u8 rgb_enhance_mode;/*sw_rgb_enh_sel,dde sel*/
 
        u8 rgb_cg_en;/*sw_rgb_con_gam_en*/
-       unsigned int cg_tab[192];
+       u32 cg_tab[192];
 
        /*sw_con_gam_order;0 cg prior to dde,1 dde prior to cg*/
        u8 rgb_contrast_enhance_mode;
 
-       int enh_threshold; 
-       int enh_alpha;
-       int enh_radius;
+       s32 enh_threshold;
+       s32 enh_alpha;
+       s32 enh_radius;
 
        u8 scale_up_mode;
 
index f6c7309a846c1f87c948bc5d466494c1a46b5627..2e93cf2a67acf8eb571b87556fcd48f88cab56c7 100644 (file)
 
 #define IEP_MAJOR              255
 #define IEP_CLK_ENABLE
-//#define IEP_TEST_CASE
+/*#define IEP_TEST_CASE*/
 
-//#undef dmac_flush_range
-//#define dmac_flush_range dma_cache_wback_inv
+static int debug;
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug,
+                "Debug level - higher value produces more verbose messages");
 
 #define RK_IEP_SIZE            0x1000
 #define IEP_TIMEOUT_DELAY      2*HZ
@@ -219,7 +221,8 @@ static void iep_power_on(void)
        /* iep_soft_rst(iep_drvdata1->iep_base); */
 
 #ifdef IEP_CLK_ENABLE
-       clk_prepare_enable(iep_drvdata1->pd_iep);
+       if (iep_drvdata1->pd_iep)
+               clk_prepare_enable(iep_drvdata1->pd_iep);
        clk_prepare_enable(iep_drvdata1->aclk_iep);
        clk_prepare_enable(iep_drvdata1->hclk_iep);
 #endif
@@ -262,7 +265,8 @@ static void iep_power_off(void)
 #ifdef IEP_CLK_ENABLE
        clk_disable_unprepare(iep_drvdata1->aclk_iep);
        clk_disable_unprepare(iep_drvdata1->hclk_iep);
-       clk_disable_unprepare(iep_drvdata1->pd_iep);
+       if (iep_drvdata1->pd_iep)
+               clk_disable_unprepare(iep_drvdata1->pd_iep);
 #endif
 
        wake_unlock(&iep_drvdata1->wake_lock);
@@ -791,12 +795,88 @@ static long iep_ioctl(struct file *filp, uint32_t cmd, unsigned long arg)
        return ret;
 }
 
+#ifdef CONFIG_COMPAT
+static long compat_iep_ioctl(struct file *filp, uint32_t cmd,
+                            unsigned long arg)
+{
+       int ret = 0;
+       iep_session *session = (iep_session *)filp->private_data;
+
+       if (NULL == session) {
+               IEP_ERR("%s [%d] iep thread session is null\n",
+                       __func__, __LINE__);
+               return -EINVAL;
+       }
+
+       mutex_lock(&iep_service.mutex);
+
+       switch (cmd) {
+       case COMPAT_IEP_SET_PARAMETER:
+               {
+                       struct IEP_MSG *msg;
+
+                       msg = kzalloc(sizeof(*msg), GFP_KERNEL);
+
+                       if (msg) {
+                               if (copy_from_user
+                                   (msg, compat_ptr((compat_uptr_t)arg),
+                                    sizeof(struct IEP_MSG))) {
+                                       IEP_ERR("copy_from_user failure\n");
+                                       ret = -EFAULT;
+                               }
+                       }
+
+                       if (ret == 0) {
+                               if (atomic_read(&iep_service.waitcnt) < 10) {
+#if defined(CONFIG_IEP_IOMMU)
+                                       iep_power_on();
+#endif
+                                       iep_config(session, msg);
+                                       atomic_inc(&iep_service.waitcnt);
+                               } else {
+                                       IEP_ERR("iep task queue full\n");
+                                       ret = -EFAULT;
+                               }
+                       }
+
+                       /** REGISTER CONFIG must accord to Timing When DPI mode
+                        *  enable */
+                       if (!iep_drvdata1->dpi_mode)
+                               iep_try_set_reg();
+                       kfree(msg);
+               }
+               break;
+       case COMPAT_IEP_GET_RESULT_SYNC:
+               if (0 > iep_get_result_sync(session))
+                       ret = -ETIMEDOUT;
+               break;
+       case COMPAT_IEP_GET_RESULT_ASYNC:
+               iep_get_result_async(session);
+               break;
+       case COMPAT_IEP_RELEASE_CURRENT_TASK:
+               iep_del_running_list_timeout();
+               iep_try_set_reg();
+               iep_try_start_frm();
+               break;
+       default:
+               IEP_ERR("unknown ioctl cmd!\n");
+               ret = -EINVAL;
+       }
+       mutex_unlock(&iep_service.mutex);
+
+       return ret;
+}
+#endif
+
 struct file_operations iep_fops = {
        .owner          = THIS_MODULE,
        .open           = iep_open,
        .release        = iep_release,
        .poll           = iep_poll,
        .unlocked_ioctl = iep_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = compat_iep_ioctl,
+#endif
 };
 
 static struct miscdevice iep_dev = {
@@ -909,7 +989,7 @@ static int iep_drv_probe(struct platform_device *pdev)
        data->pd_iep = devm_clk_get(&pdev->dev, "pd_iep");
        if (IS_ERR(data->pd_iep)) {
                IEP_ERR("failed to find iep power down clock source.\n");
-               goto err_clock;
+               data->pd_iep = NULL;
        }
 
        data->aclk_iep = devm_clk_get(&pdev->dev, "aclk_iep");
@@ -1013,7 +1093,9 @@ err_irq:
        }
 err_ioremap:
        wake_lock_destroy(&data->wake_lock);
+#ifdef IEP_CLK_ENABLE
 err_clock:
+#endif
        return ret;
 }