video/rockchip: rga2: use axi safe reset
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / rga2 / rga2_drv.c
index 009681854fee5ee77bc0889a9f42cabd4a7b1091..936411d895cda3f874e71dc814b114a5f5459c1f 100644 (file)
@@ -59,7 +59,7 @@
 #define RGA2_TEST_FLUSH_TIME 0
 #define RGA2_INFO_BUS_ERROR 1
 #define RGA2_POWER_OFF_DELAY   4*HZ /* 4s */
 #define RGA2_TEST_FLUSH_TIME 0
 #define RGA2_INFO_BUS_ERROR 1
 #define RGA2_POWER_OFF_DELAY   4*HZ /* 4s */
-#define RGA2_TIMEOUT_DELAY     2*HZ /* 2s */
+#define RGA2_TIMEOUT_DELAY     (HZ / 10) /* 100ms */
 #define RGA2_MAJOR             255
 #define RGA2_RESET_TIMEOUT     1000
 
 #define RGA2_MAJOR             255
 #define RGA2_RESET_TIMEOUT     1000
 
@@ -91,6 +91,7 @@ struct rga2_drvdata_t {
        struct clk *rga2;
 
        struct ion_client * ion_client;
        struct clk *rga2;
 
        struct ion_client * ion_client;
+       char version[16];
 };
 
 struct rga2_drvdata_t *rga2_drvdata;
 };
 
 struct rga2_drvdata_t *rga2_drvdata;
@@ -148,12 +149,46 @@ static inline u32 rga2_read(u32 r)
        return *((volatile unsigned int *)(rga2_drvdata->rga_base + r));
 }
 
        return *((volatile unsigned int *)(rga2_drvdata->rga_base + r));
 }
 
+static inline int rga2_init_version(void)
+{
+       struct rga2_drvdata_t *rga = rga2_drvdata;
+       u32 major_version, minor_version;
+       u32 reg_version;
+
+       if (!rga) {
+               pr_err("rga2_drvdata is null\n");
+               return -EINVAL;
+       }
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
+       pm_runtime_get_sync(rga2_drvdata->dev);
+#endif
+
+       clk_prepare_enable(rga2_drvdata->aclk_rga2);
+       clk_prepare_enable(rga2_drvdata->hclk_rga2);
+
+       reg_version = rga2_read(0x028);
+
+       clk_disable_unprepare(rga2_drvdata->aclk_rga2);
+       clk_disable_unprepare(rga2_drvdata->hclk_rga2);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
+       pm_runtime_put(rga2_drvdata->dev);
+#endif
+
+       major_version = (reg_version & RGA2_MAJOR_VERSION_MASK) >> 24;
+       minor_version = (reg_version & RGA2_MINOR_VERSION_MASK) >> 20;
+
+       sprintf(rga->version, "%d.%02d", major_version, minor_version);
+
+       return 0;
+}
+
 static void rga2_soft_reset(void)
 {
        u32 i;
        u32 reg;
 
 static void rga2_soft_reset(void)
 {
        u32 i;
        u32 reg;
 
-       rga2_write((1 << 3) | (1 << 4), RGA2_SYS_CTRL); //RGA_SYS_CTRL
+       rga2_write((1 << 3) | (1 << 4) | (1 << 6), RGA2_SYS_CTRL);
 
        for(i = 0; i < RGA2_RESET_TIMEOUT; i++)
        {
 
        for(i = 0; i < RGA2_RESET_TIMEOUT; i++)
        {
@@ -878,9 +913,14 @@ static int rga2_blit_async(rga2_session *session, struct rga2_req *req)
 
 static int rga2_blit_sync(rga2_session *session, struct rga2_req *req)
 {
 
 static int rga2_blit_sync(rga2_session *session, struct rga2_req *req)
 {
+       struct rga2_req req_bak;
+       int try = 10;
        int ret = -1;
        int ret_timeout = 0;
 
        int ret = -1;
        int ret_timeout = 0;
 
+       memcpy(&req_bak, req, sizeof(req_bak));
+retry:
+
 #if RGA2_TEST_MSG
        if (1) {//req->bitblt_mode == 0x2) {
                print_info(req);
 #if RGA2_TEST_MSG
        if (1) {//req->bitblt_mode == 0x2) {
                print_info(req);
@@ -922,17 +962,26 @@ static int rga2_blit_sync(rga2_session *session, struct rga2_req *req)
        rga2_end = ktime_sub(rga2_end, rga2_start);
        printk("sync one cmd end time %d\n", (int)ktime_to_us(rga2_end));
 #endif
        rga2_end = ktime_sub(rga2_end, rga2_start);
        printk("sync one cmd end time %d\n", (int)ktime_to_us(rga2_end));
 #endif
+       if (ret == -ETIMEDOUT && try--) {
+               memcpy(req, &req_bak, sizeof(req_bak));
+               goto retry;
+       }
 
        return ret;
        }
 
 static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
 {
 
        return ret;
        }
 
 static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
 {
+       struct rga2_drvdata_t *rga = rga2_drvdata;
        struct rga2_req req, req_first;
        struct rga_req req_rga;
        int ret = 0;
        rga2_session *session;
 
        struct rga2_req req, req_first;
        struct rga_req req_rga;
        int ret = 0;
        rga2_session *session;
 
+       if (!rga) {
+               pr_err("rga2_drvdata is null, rga2 is not init\n");
+               return -ENODEV;
+       }
        memset(&req, 0x0, sizeof(req));
 
        mutex_lock(&rga2_service.mutex);
        memset(&req, 0x0, sizeof(req));
 
        mutex_lock(&rga2_service.mutex);
@@ -1039,8 +1088,7 @@ static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
                        break;
                case RGA_GET_VERSION:
                case RGA2_GET_VERSION:
                        break;
                case RGA_GET_VERSION:
                case RGA2_GET_VERSION:
-                       ret = copy_to_user((void *)arg, RGA2_VERSION, sizeof(RGA2_VERSION));
-                       //ret = 0;
+                       ret = copy_to_user((void *)arg, rga->version, 16);
                        break;
                default:
                        ERR("unknown ioctl cmd!\n");
                        break;
                default:
                        ERR("unknown ioctl cmd!\n");
@@ -1056,11 +1104,16 @@ static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
 #ifdef CONFIG_COMPAT
 static long compat_rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
 {
 #ifdef CONFIG_COMPAT
 static long compat_rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
 {
+       struct rga2_drvdata_t *rga = rga2_drvdata;
        struct rga2_req req, req_first;
        struct rga_req_32 req_rga;
        int ret = 0;
        rga2_session *session;
 
        struct rga2_req req, req_first;
        struct rga_req_32 req_rga;
        int ret = 0;
        rga2_session *session;
 
+       if (!rga) {
+               pr_err("rga2_drvdata is null, rga2 is not init\n");
+               return -ENODEV;
+       }
        memset(&req, 0x0, sizeof(req));
 
        mutex_lock(&rga2_service.mutex);
        memset(&req, 0x0, sizeof(req));
 
        mutex_lock(&rga2_service.mutex);
@@ -1172,8 +1225,7 @@ static long compat_rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
                        break;
                case RGA_GET_VERSION:
                case RGA2_GET_VERSION:
                        break;
                case RGA_GET_VERSION:
                case RGA2_GET_VERSION:
-                       ret = copy_to_user((void *)arg, RGA2_VERSION, sizeof(RGA2_VERSION));
-                       //ret = 0;
+                       ret = copy_to_user((void *)arg, rga->version, 16);
                        break;
                default:
                        ERR("unknown ioctl cmd!\n");
                        break;
                default:
                        ERR("unknown ioctl cmd!\n");
@@ -1378,12 +1430,11 @@ static int rga2_drv_probe(struct platform_device *pdev)
                ERR("cannot register miscdev (%d)\n", ret);
                goto err_misc_register;
        }
                ERR("cannot register miscdev (%d)\n", ret);
                goto err_misc_register;
        }
-
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
        pm_runtime_enable(&pdev->dev);
 #endif
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
        pm_runtime_enable(&pdev->dev);
 #endif
-
-       pr_info("Driver loaded succesfully\n");
+       rga2_init_version();
+       pr_info("Driver loaded successfully ver:%s\n", rga2_drvdata->version);
 
        return 0;
 
 
        return 0;