X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fvideo%2Frockchip%2Frga%2Frga_drv.c;h=b8e38f5328dd5b95c18747d7c5762ffdf5f1014f;hb=60a0eae1758576317b5b474dfb223c99df2e87df;hp=4b4def59b8c12449ea32e38e06b768de1571f461;hpb=5c7f38813e488fa5db761d8b536949261ab71226;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/video/rockchip/rga/rga_drv.c b/drivers/video/rockchip/rga/rga_drv.c index 4b4def59b8c1..b8e38f5328dd 100755 --- a/drivers/video/rockchip/rga/rga_drv.c +++ b/drivers/video/rockchip/rga/rga_drv.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2012 ROCKCHIP, Inc. * * This software is licensed under the terms of the GNU General Public @@ -9,9 +9,10 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * */ +#define pr_fmt(fmt) "rga: " fmt #include #include #include @@ -26,11 +27,10 @@ #include #include #include -#include -#include +//#include +//#include #include #include -#include #include #include #include @@ -39,9 +39,13 @@ #include #include #include -#include #include #include +#include + +#if defined(CONFIG_ION_ROCKCHIP) +#include +#endif #include "rga.h" @@ -49,6 +53,8 @@ #include "rga_mmu_info.h" #include "RGA_API.h" +#define RGA_TEST_CASE 0 + #define RGA_TEST 0 #define RGA_TEST_TIME 0 #define RGA_TEST_FLUSH_TIME 0 @@ -61,42 +67,53 @@ #define RGA_MAJOR 255 -#define RK30_RGA_PHYS 0x10114000 -#define RK30_RGA_SIZE SZ_8K +#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) +#define RK30_RGA_PHYS RK2928_RGA_PHYS +#define RK30_RGA_SIZE RK2928_RGA_SIZE +#endif #define RGA_RESET_TIMEOUT 1000 /* Driver information */ #define DRIVER_DESC "RGA Device Driver" #define DRIVER_NAME "rga" +#define RGA_VERSION "1.003" + ktime_t rga_start; ktime_t rga_end; -int rga_num = 0; +rga_session rga_session_global; struct rga_drvdata { struct miscdevice miscdev; struct device dev; void *rga_base; - int irq0; - + int irq; + struct delayed_work power_off_work; void (*rga_irq_callback)(int rga_retval); //callback function used by aync call -}; + struct wake_lock wake_lock; + struct clk *pd_rga; + struct clk *aclk_rga; + struct clk *hclk_rga; -static struct rga_drvdata *drvdata = NULL; -rga_service_info rga_service; + //#if defined(CONFIG_ION_ROCKCHIP) + struct ion_client * ion_client; + //#endif +}; -static struct clk *aclk_rga; -static struct clk *hclk_rga; -static struct clk *pd_rga; +static struct rga_drvdata *drvdata; +rga_service_info rga_service; +#if defined(CONFIG_ION_ROCKCHIP) +extern struct ion_client *rockchip_ion_client_create(const char * name); +#endif static int rga_blit_async(rga_session *session, struct rga_req *req); static void rga_del_running_list(void); static void rga_del_running_list_timeout(void); -static void rga_try_set_reg(uint32_t num); +static void rga_try_set_reg(void); /* Logging */ @@ -113,6 +130,30 @@ static void rga_try_set_reg(uint32_t num); #define INFO(format, args...) #endif +#if RGA_TEST +static void print_info(struct rga_req *req) +{ + printk("src : yrgb_addr = %.8x, src.uv_addr = %.8x, src.v_addr = %.8x, format = %d\n", + req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr, req->src.format); + printk("src : act_w = %d, act_h = %d, vir_w = %d, vir_h = %d\n", + req->src.act_w, req->src.act_h, req->src.vir_w, req->src.vir_h); + printk("src : x_off = %.8x y_off = %.8x\n", req->src.x_offset, req->src.y_offset); + + printk("dst : yrgb_addr = %.8x, dst.uv_addr = %.8x, dst.v_addr = %.8x\n", + req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr); + printk("dst : x_off = %.8x y_off = %.8x\n", req->dst.x_offset, req->dst.y_offset); + printk("dst : act_w = %d, act_h = %d, vir_w = %d, vir_h = %d\n", + req->dst.act_w, req->dst.act_h, req->dst.vir_w, req->dst.vir_h); + + printk("clip.xmin = %d, clip.xmax = %d. clip.ymin = %d, clip.ymax = %d\n", + req->clip.xmin, req->clip.xmax, req->clip.ymin, req->clip.ymax); + + //printk("alpha_rop_flag = %.8x\n", req->alpha_rop_flag); + //printk("alpha_rop_mode = %.8x\n", req->alpha_rop_mode); + //printk("PD_mode = %.8x\n", req->PD_mode); +} +#endif + static inline void rga_write(u32 b, u32 r) { @@ -131,8 +172,8 @@ static void rga_soft_reset(void) rga_write(1, RGA_SYS_CTRL); //RGA_SYS_CTRL - for(i = 0; i < RGA_RESET_TIMEOUT; i++) - { + for(i = 0; i < RGA_RESET_TIMEOUT; i++) + { reg = rga_read(RGA_SYS_CTRL) & 1; //RGA_SYS_CTRL if(reg == 0) @@ -148,17 +189,19 @@ static void rga_soft_reset(void) static void rga_dump(void) { int running; - int num_done; struct rga_reg *reg, *reg_tmp; - rga_session *session, *session_tmp; - struct list_head *next; + rga_session *session, *session_tmp; running = atomic_read(&rga_service.total_running); printk("rga total_running %d\n", running); + #if 0 + /* Dump waiting list info */ if (!list_empty(&rga_service.waiting)) - { + { + list_head *next; + next = &rga_service.waiting; printk("rga_service dump waiting list\n"); @@ -168,120 +211,135 @@ static void rga_dump(void) reg = list_entry(next->next, struct rga_reg, status_link); running = atomic_read(®->session->task_running); num_done = atomic_read(®->session->num_done); - printk("rga session pid %d, done %d, running %d\n", reg->session->pid, num_done, running); + printk("rga session pid %d, done %d, running %d\n", reg->session->pid, num_done, running); next = next->next; } - while(!list_empty(next)); + while(!list_empty(next)); } /* Dump running list info */ if (!list_empty(&rga_service.running)) { printk("rga_service dump running list\n"); - + + list_head *next; + next = &rga_service.running; do { reg = list_entry(next->next, struct rga_reg, status_link); running = atomic_read(®->session->task_running); num_done = atomic_read(®->session->num_done); - printk("rga session pid %d, done %d, running %d:\n", reg->session->pid, num_done, running); + printk("rga session pid %d, done %d, running %d:\n", reg->session->pid, num_done, running); next = next->next; } - while(!list_empty(next)); + while(!list_empty(next)); } - - list_for_each_entry_safe(session, session_tmp, &rga_service.session, list_session) + #endif + + list_for_each_entry_safe(session, session_tmp, &rga_service.session, list_session) { printk("session pid %d:\n", session->pid); running = atomic_read(&session->task_running); printk("task_running %d\n", running); - list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) + list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) { printk("waiting register set 0x%.8x\n", (unsigned int)reg); } - list_for_each_entry_safe(reg, reg_tmp, &session->running, session_link) + list_for_each_entry_safe(reg, reg_tmp, &session->running, session_link) { printk("running register set 0x%.8x\n", (unsigned int)reg); } } } +static inline void rga_queue_power_off_work(void) +{ + queue_delayed_work(system_nrt_wq, &drvdata->power_off_work, RGA_POWER_OFF_DELAY); +} +/* Caller must hold rga_service.lock */ static void rga_power_on(void) { - //printk("rga_power_on\n"); - //cancel_delayed_work_sync(&drvdata->power_off_work); - spin_lock_bh(&rga_service.lock_power); + static ktime_t last; + ktime_t now = ktime_get(); + + if (ktime_to_ns(ktime_sub(now, last)) > NSEC_PER_SEC) { + cancel_delayed_work_sync(&drvdata->power_off_work); + rga_queue_power_off_work(); + last = now; + } if (rga_service.enable) - goto out; + return; - clk_enable(aclk_rga); - clk_enable(hclk_rga); - clk_enable(pd_rga); + clk_prepare_enable(drvdata->aclk_rga); + clk_prepare_enable(drvdata->hclk_rga); + //clk_prepare_enable(drvdata->pd_rga); + wake_lock(&drvdata->wake_lock); rga_service.enable = true; -out: - spin_unlock_bh(&rga_service.lock_power); } - -static void rga_power_off(struct work_struct *work) +/* Caller must hold rga_service.lock */ +static void rga_power_off(void) { - int total_running; + int total_running; - spin_lock_bh(&rga_service.lock_power); - if(!rga_service.enable) - { - spin_unlock_bh(&rga_service.lock_power); + if (!rga_service.enable) { return; } - rga_service.enable = false; - - printk("rga_power_off\n"); - - total_running = atomic_read(&rga_service.total_running); + total_running = atomic_read(&rga_service.total_running); if (total_running) { - pr_err("power off when %d task running!!\n", total_running); + pr_err("power off when %d task running!!\n", total_running); mdelay(50); - pr_err("delay 50 ms for running task\n"); - rga_dump(); + pr_err("delay 50 ms for running task\n"); + rga_dump(); + } + + //clk_disable_unprepare(drvdata->pd_rga); + clk_disable_unprepare(drvdata->aclk_rga); + clk_disable_unprepare(drvdata->hclk_rga); + wake_unlock(&drvdata->wake_lock); + rga_service.enable = false; +} + +static void rga_power_off_work(struct work_struct *work) +{ + if (mutex_trylock(&rga_service.lock)) { + rga_power_off(); + mutex_unlock(&rga_service.lock); + } else { + /* Come back later if the device is busy... */ + rga_queue_power_off_work(); } - - clk_disable(pd_rga); - clk_disable(aclk_rga); - clk_disable(hclk_rga); - spin_unlock_bh(&rga_service.lock_power); - } static int rga_flush(rga_session *session, unsigned long arg) -{ +{ int ret = 0; int ret_timeout; - unsigned long flag; - + #if RGA_TEST_FLUSH_TIME ktime_t start; ktime_t end; start = ktime_get(); #endif - ret_timeout = wait_event_interruptible_timeout(session->wait, atomic_read(&session->done), RGA_TIMEOUT_DELAY); - + ret_timeout = wait_event_timeout(session->wait, atomic_read(&session->done), RGA_TIMEOUT_DELAY); + if (unlikely(ret_timeout < 0)) { - pr_err("flush pid %d wait task ret %d\n", session->pid, ret); - spin_lock_irqsave(&rga_service.lock, flag); + //pr_err("flush pid %d wait task ret %d\n", session->pid, ret); + mutex_lock(&rga_service.lock); rga_del_running_list(); - spin_unlock_irqrestore(&rga_service.lock, flag); - ret = -ETIMEDOUT; + mutex_unlock(&rga_service.lock); + ret = ret_timeout; } else if (0 == ret_timeout) { - pr_err("flush pid %d wait %d task done timeout\n", session->pid, atomic_read(&session->task_running)); - printk("bus = %.8x\n", rga_read(RGA_INT)); - spin_lock_irqsave(&rga_service.lock, flag); + //pr_err("flush pid %d wait %d task done timeout\n", session->pid, atomic_read(&session->task_running)); + //printk("bus = %.8x\n", rga_read(RGA_INT)); + mutex_lock(&rga_service.lock); rga_del_running_list_timeout(); - spin_unlock_irqrestore(&rga_service.lock, flag); - rga_try_set_reg(1); + rga_try_set_reg(); + mutex_unlock(&rga_service.lock); ret = -ETIMEDOUT; } @@ -290,7 +348,7 @@ static int rga_flush(rga_session *session, unsigned long arg) end = ktime_sub(end, start); printk("one flush wait time %d\n", (int)ktime_to_us(end)); #endif - + return ret; } @@ -298,17 +356,16 @@ static int rga_flush(rga_session *session, unsigned long arg) static int rga_get_result(rga_session *session, unsigned long arg) { //printk("rga_get_result %d\n",drvdata->rga_result); - + int ret = 0; int num_done; num_done = atomic_read(&session->num_done); - + if (unlikely(copy_to_user((void __user *)arg, &num_done, sizeof(int)))) { printk("copy_to_user failed\n"); - ERR("copy_to_user failed\n"); - ret = -EFAULT; + ret = -EFAULT; } return ret; } @@ -321,52 +378,55 @@ static int rga_check_param(const struct rga_req *req) if(!((req->render_mode == color_fill_mode) || (req->render_mode == line_point_drawing_mode))) { - if (unlikely((req->src.act_w <= 0) || (req->src.act_w > 8191) || (req->src.act_h <= 0) || (req->src.act_h > 8191))) + if (unlikely((req->src.act_w <= 0) || (req->src.act_w > 8191) || (req->src.act_h <= 0) || (req->src.act_h > 8191))) { - ERR("invalid source resolution act_w = %d, act_h = %d\n", req->src.act_w, req->src.act_h); + printk("invalid source resolution act_w = %d, act_h = %d\n", req->src.act_w, req->src.act_h); return -EINVAL; } } if(!((req->render_mode == color_fill_mode) || (req->render_mode == line_point_drawing_mode))) { - if (unlikely((req->src.vir_w <= 0) || (req->src.vir_w > 8191) || (req->src.vir_h <= 0) || (req->src.vir_h > 8191))) + if (unlikely((req->src.vir_w <= 0) || (req->src.vir_w > 8191) || (req->src.vir_h <= 0) || (req->src.vir_h > 8191))) { - ERR("invalid source resolution vir_w = %d, vir_h = %d\n", req->src.vir_w, req->src.vir_h); + printk("invalid source resolution vir_w = %d, vir_h = %d\n", req->src.vir_w, req->src.vir_h); return -EINVAL; } } //check dst width and height - if (unlikely((req->dst.act_w <= 0) || (req->dst.act_w > 2048) || (req->dst.act_h <= 0) || (req->dst.act_h > 2048))) + if (unlikely((req->dst.act_w <= 0) || (req->dst.act_w > 2048) || (req->dst.act_h <= 0) || (req->dst.act_h > 2048))) { - ERR("invalid destination resolution act_w = %d, act_h = %d\n", req->dst.act_w, req->dst.act_h); + printk("invalid destination resolution act_w = %d, act_h = %d\n", req->dst.act_w, req->dst.act_h); return -EINVAL; } - if (unlikely((req->dst.vir_w <= 0) || (req->dst.vir_w > 2048) || (req->dst.vir_h <= 0) || (req->dst.vir_h > 2048))) + if (unlikely((req->dst.vir_w <= 0) || (req->dst.vir_w > 4096) || (req->dst.vir_h <= 0) || (req->dst.vir_h > 2048))) { - ERR("invalid destination resolution vir_w = %d, vir_h = %d\n", req->dst.vir_w, req->dst.vir_h); + printk("invalid destination resolution vir_w = %d, vir_h = %d\n", req->dst.vir_w, req->dst.vir_h); return -EINVAL; } //check src_vir_w if(unlikely(req->src.vir_w < req->src.act_w)){ - ERR("invalid src_vir_w act_w = %d, vir_w = %d\n", req->src.act_w, req->src.vir_w); + printk("invalid src_vir_w act_w = %d, vir_w = %d\n", req->src.act_w, req->src.vir_w); return -EINVAL; } //check dst_vir_w if(unlikely(req->dst.vir_w < req->dst.act_w)){ - ERR("invalid dst_vir_w act_h = %d, vir_h = %d\n", req->dst.act_w, req->dst.vir_w); - return -EINVAL; + if(req->rotate_mode != 1) + { + printk("invalid dst_vir_w act_h = %d, vir_h = %d\n", req->dst.act_w, req->dst.vir_w); + return -EINVAL; + } } - + return 0; } static void rga_copy_reg(struct rga_reg *reg, uint32_t offset) -{ +{ uint32_t i; uint32_t *cmd_buf; uint32_t *reg_p; @@ -375,10 +435,10 @@ static void rga_copy_reg(struct rga_reg *reg, uint32_t offset) { printk(KERN_ERR "task_running is no zero\n"); } - + atomic_add(1, &rga_service.cmd_num); - atomic_add(1, ®->session->task_running); - + atomic_add(1, ®->session->task_running); + cmd_buf = (uint32_t *)rga_service.cmd_buff + offset*28; reg_p = (uint32_t *)reg->cmd_reg; @@ -386,14 +446,13 @@ static void rga_copy_reg(struct rga_reg *reg, uint32_t offset) { cmd_buf[i] = reg_p[i]; } - + dsb(); } static struct rga_reg * rga_reg_init(rga_session *session, struct rga_req *req) { - unsigned long flag; uint32_t ret; struct rga_reg *reg = kzalloc(sizeof(struct rga_reg), GFP_KERNEL); if (NULL == reg) { @@ -405,21 +464,19 @@ static struct rga_reg * rga_reg_init(rga_session *session, struct rga_req *req) INIT_LIST_HEAD(®->session_link); INIT_LIST_HEAD(®->status_link); - //memcpy(®->req, req, sizeof(struct rga_req)); - reg->MMU_base = NULL; - + if (req->mmu_info.mmu_en) { ret = rga_set_mmu_info(reg, req); - if(ret < 0) + if(ret < 0) { printk("%s, [%d] set mmu info error \n", __FUNCTION__, __LINE__); - if(reg != NULL) - { + if(reg != NULL) + { kfree(reg); } - return NULL; + return NULL; } } @@ -428,22 +485,21 @@ static struct rga_reg * rga_reg_init(rga_session *session, struct rga_req *req) printk("gen reg info error\n"); if(reg != NULL) { - kfree(reg); + kfree(reg); } return NULL; } - spin_lock_irqsave(&rga_service.lock, flag); + mutex_lock(&rga_service.lock); list_add_tail(®->status_link, &rga_service.waiting); list_add_tail(®->session_link, &session->waiting); - spin_unlock_irqrestore(&rga_service.lock, flag); + mutex_unlock(&rga_service.lock); return reg; } static struct rga_reg * rga_reg_init_2(rga_session *session, struct rga_req *req0, struct rga_req *req1) { - unsigned long flag; uint32_t ret; struct rga_reg *reg0, *reg1; @@ -452,7 +508,7 @@ static struct rga_reg * rga_reg_init_2(rga_session *session, struct rga_req *req reg1 = NULL; do - { + { reg0 = kzalloc(sizeof(struct rga_reg), GFP_KERNEL); if (NULL == reg0) { pr_err("%s [%d] kmalloc fail in rga_reg_init\n", __FUNCTION__, __LINE__); @@ -465,7 +521,7 @@ static struct rga_reg * rga_reg_init_2(rga_session *session, struct rga_req *req break; } - reg0->session = session; + reg0->session = session; INIT_LIST_HEAD(®0->session_link); INIT_LIST_HEAD(®0->status_link); @@ -473,37 +529,34 @@ static struct rga_reg * rga_reg_init_2(rga_session *session, struct rga_req *req INIT_LIST_HEAD(®1->session_link); INIT_LIST_HEAD(®1->status_link); - //memcpy(®0->req, req0, sizeof(struct rga_req)); - //memcpy(®1->req, req1, sizeof(struct rga_req)); - if(req0->mmu_info.mmu_en) { ret = rga_set_mmu_info(reg0, req0); if(ret < 0) { printk("%s, [%d] set mmu info error \n", __FUNCTION__, __LINE__); - break; + break; } } - + RGA_gen_reg_info(req0, (uint8_t *)reg0->cmd_reg); - + if(req1->mmu_info.mmu_en) { ret = rga_set_mmu_info(reg1, req1); if(ret < 0) { printk("%s, [%d] set mmu info error \n", __FUNCTION__, __LINE__); - break; + break; } } - + RGA_gen_reg_info(req1, (uint8_t *)reg1->cmd_reg); - - spin_lock_irqsave(&rga_service.lock, flag); + + mutex_lock(&rga_service.lock); list_add_tail(®0->status_link, &rga_service.waiting); list_add_tail(®0->session_link, &session->waiting); - list_add_tail(®1->status_link, &rga_service.waiting); + list_add_tail(®1->status_link, &rga_service.waiting); list_add_tail(®1->session_link, &session->waiting); - spin_unlock_irqrestore(&rga_service.lock, flag); + mutex_unlock(&rga_service.lock); return reg1; } @@ -520,14 +573,15 @@ static struct rga_reg * rga_reg_init_2(rga_session *session, struct rga_req *req return NULL; } - +/* Caller must hold rga_service.lock */ static void rga_reg_deinit(struct rga_reg *reg) { list_del_init(®->session_link); list_del_init(®->status_link); - kfree(reg); + kfree(reg); } +/* Caller must hold rga_service.lock */ static void rga_reg_from_wait_to_run(struct rga_reg *reg) { list_del_init(®->status_link); @@ -537,127 +591,100 @@ static void rga_reg_from_wait_to_run(struct rga_reg *reg) list_add_tail(®->session_link, ®->session->running); } +/* Caller must hold rga_service.lock */ static void rga_service_session_clear(rga_session *session) { struct rga_reg *reg, *n; - list_for_each_entry_safe(reg, n, &session->waiting, session_link) + list_for_each_entry_safe(reg, n, &session->waiting, session_link) { rga_reg_deinit(reg); } - list_for_each_entry_safe(reg, n, &session->running, session_link) + list_for_each_entry_safe(reg, n, &session->running, session_link) { rga_reg_deinit(reg); } } -static void rga_try_set_reg(uint32_t num) +/* Caller must hold rga_service.lock */ +static void rga_try_set_reg(void) { - unsigned long flag; struct rga_reg *reg ; - - if (!num) - { - #if RGA_TEST - printk("rga try set reg cmd num is 0\n"); - #endif - - return; - } - udelay(3); - - spin_lock_irqsave(&rga_service.lock, flag); - if (!list_empty(&rga_service.waiting)) + if (list_empty(&rga_service.running)) { - do - { - if(!list_empty(&rga_service.running)) - { - break; + if (!list_empty(&rga_service.waiting)) + { + /* RGA is idle */ + reg = list_entry(rga_service.waiting.next, struct rga_reg, status_link); + + rga_power_on(); + udelay(1); + + rga_copy_reg(reg, 0); + rga_reg_from_wait_to_run(reg); + + dmac_flush_range(&rga_service.cmd_buff[0], &rga_service.cmd_buff[28]); + outer_flush_range(virt_to_phys(&rga_service.cmd_buff[0]),virt_to_phys(&rga_service.cmd_buff[28])); + + #if defined(CONFIG_ARCH_RK30) + rga_soft_reset(); + #endif + + rga_write(0x0, RGA_SYS_CTRL); + rga_write(0, RGA_MMU_CTRL); + + /* CMD buff */ + rga_write(virt_to_phys(rga_service.cmd_buff), RGA_CMD_ADDR); + +#if RGA_TEST + { + //printk(KERN_DEBUG "cmd_addr = %.8x\n", rga_read(RGA_CMD_ADDR)); + uint32_t i; + uint32_t *p; + p = rga_service.cmd_buff; + printk("CMD_REG\n"); + for (i=0; i<7; i++) + printk("%.8x %.8x %.8x %.8x\n", p[0 + i*4], p[1+i*4], p[2 + i*4], p[3 + i*4]); } - else - { - /* RGA is idle */ - reg = list_entry(rga_service.waiting.next, struct rga_reg, status_link); - rga_copy_reg(reg, 0); - rga_reg_from_wait_to_run(reg); - - dmac_flush_range(&rga_service.cmd_buff[0], &rga_service.cmd_buff[28]); - outer_flush_range(virt_to_phys(&rga_service.cmd_buff[0]),virt_to_phys(&rga_service.cmd_buff[28])); - - rga_soft_reset(); - rga_write(0, RGA_MMU_CTRL); - - /* CMD buff */ - rga_write(virt_to_phys(rga_service.cmd_buff), RGA_CMD_ADDR); - - #if RGA_TEST - { - //printk(KERN_DEBUG "cmd_addr = %.8x\n", rga_read(RGA_CMD_ADDR)); - uint32_t i; - uint32_t *p; - p = rga_service.cmd_buff; - printk(KERN_DEBUG "CMD_REG\n"); - for (i=0; i<7; i++) - printk("%.8x %.8x %.8x %.8x\n", p[0 + i*4], p[1+i*4], p[2 + i*4], p[3 + i*4]); - } - #endif - - /* master mode */ - rga_write((0x1<<2)|(0x1<<3), RGA_SYS_CTRL); - - /* All CMD finish int */ - rga_write(rga_read(RGA_INT)|(0x1<<10)|(0x1<<8), RGA_INT); - - /* Start proc */ - atomic_set(®->session->done, 0); - rga_write(0x1, RGA_CMD_CTRL); - - #if RGA_TEST - { - uint32_t i; - printk(KERN_DEBUG "CMD_READ_BACK_REG\n"); - for (i=0; i<7; i++) - printk(KERN_DEBUG "%.8x %.8x %.8x %.8x\n", rga_read(0x100 + i*16 + 0), - rga_read(0x100 + i*16 + 4), rga_read(0x100 + i*16 + 8), rga_read(0x100 + i*16 + 12)); - } - #endif +#endif + + /* master mode */ + rga_write((0x1<<2)|(0x1<<3), RGA_SYS_CTRL); + + /* All CMD finish int */ + rga_write(rga_read(RGA_INT)|(0x1<<10)|(0x1<<8), RGA_INT); + + #if RGA_TEST_TIME + rga_start = ktime_get(); + #endif + + /* Start proc */ + atomic_set(®->session->done, 0); + rga_write(0x1, RGA_CMD_CTRL); + +#if RGA_TEST + { + uint32_t i; + printk("CMD_READ_BACK_REG\n"); + for (i=0; i<7; i++) + printk("%.8x %.8x %.8x %.8x\n", rga_read(0x100 + i*16 + 0), + rga_read(0x100 + i*16 + 4), rga_read(0x100 + i*16 + 8), rga_read(0x100 + i*16 + 12)); } - num--; +#endif } - while(0); - } - spin_unlock_irqrestore(&rga_service.lock, flag); + } } -#if RGA_TEST -static void print_info(struct rga_req *req) -{ - printk("src.yrgb_addr = %.8x, src.uv_addr = %.8x, src.v_addr = %.8x\n", - req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr); - printk("src : act_w = %d, act_h = %d, vir_w = %d, vir_h = %d\n", - req->src.act_w, req->src.act_h, req->src.vir_w, req->src.vir_h); - printk("src : x_offset = %.8x y_offset = %.8x\n", req->src.x_offset, req->src.y_offset); - - printk("dst.yrgb_addr = %.8x, dst.uv_addr = %.8x, dst.v_addr = %.8x\n", - req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr); - printk("dst : x_offset = %.8x y_offset = %.8x\n", req->dst.x_offset, req->dst.y_offset); - printk("dst : act_w = %d, act_h = %d, vir_w = %d, vir_h = %d\n", - req->dst.act_w, req->dst.act_h, req->dst.vir_w, req->dst.vir_h); - - printk("clip.xmin = %d, clip.xmax = %d. clip.ymin = %d, clip.ymax = %d\n", - req->clip.xmin, req->clip.xmax, req->clip.ymin, req->clip.ymax); -} -#endif +/* Caller must hold rga_service.lock */ static void rga_del_running_list(void) { struct rga_reg *reg; - + while(!list_empty(&rga_service.running)) { reg = list_entry(rga_service.running.next, struct rga_reg, status_link); @@ -668,22 +695,23 @@ static void rga_del_running_list(void) reg->MMU_base = NULL; } atomic_sub(1, ®->session->task_running); - atomic_sub(1, &rga_service.total_running); - + atomic_sub(1, &rga_service.total_running); + if(list_empty(®->session->waiting)) { - atomic_set(®->session->done, 1); - wake_up_interruptible_sync(®->session->wait); + atomic_set(®->session->done, 1); + wake_up(®->session->wait); } - - rga_reg_deinit(reg); - } + + rga_reg_deinit(reg); + } } +/* Caller must hold rga_service.lock */ static void rga_del_running_list_timeout(void) { struct rga_reg *reg; - + while(!list_empty(&rga_service.running)) { reg = list_entry(rga_service.running.next, struct rga_reg, status_link); @@ -692,11 +720,14 @@ static void rga_del_running_list_timeout(void) { kfree(reg->MMU_base); } - + atomic_sub(1, ®->session->task_running); - atomic_sub(1, &rga_service.total_running); + atomic_sub(1, &rga_service.total_running); + + //printk("RGA soft reset for timeout process\n"); + rga_soft_reset(); + - #if 0 printk("RGA_INT is %.8x\n", rga_read(RGA_INT)); printk("reg->session->task_running = %d\n", atomic_read(®->session->task_running)); @@ -706,21 +737,21 @@ static void rga_del_running_list_timeout(void) { uint32_t *p, i; - p = reg->cmd_reg; - for (i=0; i<7; i++) + p = reg->cmd_reg; + for (i=0; i<7; i++) printk("%.8x %.8x %.8x %.8x\n", p[0 + i*4], p[1+i*4], p[2 + i*4], p[3 + i*4]); - + } #endif - + if(list_empty(®->session->waiting)) { atomic_set(®->session->done, 1); - wake_up_interruptible_sync(®->session->wait); + wake_up(®->session->wait); } - - rga_reg_deinit(reg); - } + + rga_reg_deinit(reg); + } } @@ -751,49 +782,80 @@ static void rga_mem_addr_sel(struct rga_req *req) break; case RK_FORMAT_YCrCb_420_SP : break; - case RK_FORMAT_YCrCb_420_P : + case RK_FORMAT_YCrCb_420_P : break; default : break; } - + } +static int rga_convert_dma_buf(struct rga_req *req) +{ + struct ion_handle *hdl; + ion_phys_addr_t phy_addr; + size_t len; + + if(req->src.yrgb_addr) { + hdl = ion_import_dma_buf(drvdata->ion_client, req->src.yrgb_addr); + ion_phys(drvdata->ion_client, hdl, &phy_addr, &len); + req->src.yrgb_addr = phy_addr; + req->src.uv_addr = req->src.yrgb_addr + (req->src.vir_w * req->src.vir_h); + } + else { + req->src.yrgb_addr = req->src.uv_addr; + req->src.uv_addr = req->src.yrgb_addr + (req->src.vir_w * req->src.vir_h); + } + + if(req->dst.yrgb_addr) { + hdl = ion_import_dma_buf(drvdata->ion_client, req->dst.yrgb_addr); + ion_phys(drvdata->ion_client, hdl, &phy_addr, &len); + req->dst.yrgb_addr = phy_addr; + req->dst.uv_addr = req->dst.yrgb_addr + (req->dst.vir_w * req->dst.vir_h); + } + else { + req->dst.yrgb_addr = req->dst.uv_addr; + req->dst.uv_addr = req->dst.yrgb_addr + (req->src.vir_w * req->src.vir_h); + } + + return 0; +} + static int rga_blit(rga_session *session, struct rga_req *req) { int ret = -1; - int num = 0; + int num = 0; struct rga_reg *reg; - struct rga_req *req2; - unsigned long flag; + struct rga_req req2; uint32_t saw, sah, daw, dah; - req2 = NULL; - saw = req->src.act_w; sah = req->src.act_h; daw = req->dst.act_w; dah = req->dst.act_h; - do - { - if((req->render_mode == bitblt_mode) && (((saw>>1) >= daw) || ((sah>>1) >= dah))) - { - /* generate 2 cmd for pre scale */ - req2 = kzalloc(sizeof(struct rga_req), GFP_KERNEL); - if(NULL == req2) { - return -EFAULT; - } + if(rga_convert_dma_buf(req)) { + printk("RGA : DMA buf copy error\n"); + return -EFAULT; + } + + #if RGA_TEST + print_info(req); + #endif + + do { + if((req->render_mode == bitblt_mode) && (((saw>>1) >= daw) || ((sah>>1) >= dah))) { + /* generate 2 cmd for pre scale */ ret = rga_check_param(req); if(ret == -EINVAL) { printk("req 0 argument is inval\n"); break; } - - ret = RGA_gen_two_pro(req, req2); + + ret = RGA_gen_two_pro(req, &req2); if(ret == -EINVAL) { break; } @@ -803,21 +865,21 @@ static int rga_blit(rga_session *session, struct rga_req *req) printk("req 1 argument is inval\n"); break; } - - ret = rga_check_param(req2); + + ret = rga_check_param(&req2); if(ret == -EINVAL) { printk("req 2 argument is inval\n"); break; } - reg = rga_reg_init_2(session, req, req2); + reg = rga_reg_init_2(session, req, &req2); if(reg == NULL) { break; - } + } num = 2; + } - else - { + else { /* check value if legal */ ret = rga_check_param(req); if(ret == -EINVAL) { @@ -826,33 +888,23 @@ static int rga_blit(rga_session *session, struct rga_req *req) } if(req->render_mode == bitblt_mode) - { - rga_mem_addr_sel(req); - } - + rga_mem_addr_sel(req); + reg = rga_reg_init(session, req); if(reg == NULL) { break; - } - num = 1; - } + } + num = 1; + } - //atomic_set(®->int_enable, 1); - - spin_lock_irqsave(&rga_service.lock, flag); + mutex_lock(&rga_service.lock); atomic_add(num, &rga_service.total_running); - spin_unlock_irqrestore(&rga_service.lock, flag); - - rga_try_set_reg(1); - - return 0; + rga_try_set_reg(); + mutex_unlock(&rga_service.lock); + + return 0; } while(0); - - if(NULL != req2) - { - kfree(req2); - } return -EFAULT; } @@ -860,14 +912,13 @@ static int rga_blit(rga_session *session, struct rga_req *req) static int rga_blit_async(rga_session *session, struct rga_req *req) { int ret = -1; - + #if RGA_TEST printk("*** rga_blit_async proc ***\n"); - print_info(req); #endif - + + atomic_set(&session->done, 0); ret = rga_blit(session, req); - return ret; } @@ -875,36 +926,29 @@ static int rga_blit_sync(rga_session *session, struct rga_req *req) { int ret = -1; int ret_timeout = 0; - unsigned long flag; - + #if RGA_TEST printk("*** rga_blit_sync proc ***\n"); - print_info(req); #endif - #if RGA_TEST_TIME - rga_start = ktime_get(); - #endif - + atomic_set(&session->done, 0); ret = rga_blit(session, req); - - ret_timeout = wait_event_interruptible_timeout(session->wait, atomic_read(&session->done), RGA_TIMEOUT_DELAY); - - if (unlikely(ret_timeout< 0)) - { - pr_err("sync pid %d wait task ret %d\n", session->pid, ret_timeout); - spin_lock_irqsave(&rga_service.lock, flag); + if(ret < 0) + return ret; + + ret_timeout = wait_event_timeout(session->wait, atomic_read(&session->done), RGA_TIMEOUT_DELAY); + + if (unlikely(ret_timeout< 0)) { + mutex_lock(&rga_service.lock); rga_del_running_list(); - spin_unlock_irqrestore(&rga_service.lock, flag); - ret = -ETIMEDOUT; - } - else if (0 == ret_timeout) - { - pr_err("sync pid %d wait %d task done timeout\n", session->pid, atomic_read(&session->task_running)); - spin_lock_irqsave(&rga_service.lock, flag); + mutex_unlock(&rga_service.lock); + ret = ret_timeout; + } + else if (0 == ret_timeout) { + mutex_lock(&rga_service.lock); rga_del_running_list_timeout(); - spin_unlock_irqrestore(&rga_service.lock, flag); - rga_try_set_reg(1); + rga_try_set_reg(); + mutex_unlock(&rga_service.lock); ret = -ETIMEDOUT; } @@ -913,61 +957,54 @@ static int rga_blit_sync(rga_session *session, struct rga_req *req) rga_end = ktime_sub(rga_end, rga_start); printk("sync one cmd end time %d\n", (int)ktime_to_us(rga_end)); #endif - - return ret; + + return ret; } static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg) { - struct rga_req *req; + struct rga_req req; int ret = 0; - rga_session *session = (rga_session *)file->private_data; - - if (NULL == session) - { + rga_session *session; + + mutex_lock(&rga_service.mutex); + + session = (rga_session *)file->private_data; + + if (NULL == session) { printk("%s [%d] rga thread session is null\n",__FUNCTION__,__LINE__); + mutex_unlock(&rga_service.mutex); return -EINVAL; } - mutex_lock(&rga_service.mutex); - - req = kzalloc(sizeof(struct rga_req), GFP_KERNEL); - if(req == NULL) - { - printk("%s [%d] get rga_req mem failed\n",__FUNCTION__,__LINE__); - mutex_unlock(&rga_service.mutex); - return -EINVAL; - } - - switch (cmd) - { + memset(&req, 0x0, sizeof(req)); + + switch (cmd) { case RGA_BLIT_SYNC: - if (unlikely(copy_from_user(req, (struct rga_req*)arg, sizeof(struct rga_req)))) + if (unlikely(copy_from_user(&req, (struct rga_req*)arg, sizeof(struct rga_req)))) { ERR("copy_from_user failed\n"); ret = -EFAULT; break; } - rga_power_on(); - ret = rga_blit_sync(session, req); + ret = rga_blit_sync(session, &req); break; case RGA_BLIT_ASYNC: - if (unlikely(copy_from_user(req, (struct rga_req*)arg, sizeof(struct rga_req)))) + if (unlikely(copy_from_user(&req, (struct rga_req*)arg, sizeof(struct rga_req)))) { ERR("copy_from_user failed\n"); ret = -EFAULT; break; } - rga_power_on(); if((atomic_read(&rga_service.total_running) > 16)) { - ret = rga_blit_sync(session, req); + ret = rga_blit_sync(session, &req); } else { - ret = rga_blit_async(session, req); + ret = rga_blit_async(session, &req); } break; case RGA_FLUSH: @@ -975,24 +1012,65 @@ static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg) break; case RGA_GET_RESULT: ret = rga_get_result(session, arg); + break; + case RGA_GET_VERSION: + ret = copy_to_user((void *)arg, RGA_VERSION, sizeof(RGA_VERSION)); + //ret = 0; + break; default: ERR("unknown ioctl cmd!\n"); ret = -EINVAL; break; } - if(req != NULL) { - kfree(req); - } - - mutex_unlock(&rga_service.mutex); - + mutex_unlock(&rga_service.mutex); + return ret; } + +long rga_ioctl_kernel(struct rga_req *req) +{ + int ret = 0; + rga_session *session; + + mutex_lock(&rga_service.mutex); + + session = &rga_session_global; + + if (NULL == session) { + printk("%s [%d] rga thread session is null\n",__FUNCTION__,__LINE__); + mutex_unlock(&rga_service.mutex); + return -EINVAL; + } + + switch (RGA_BLIT_SYNC) { + case RGA_BLIT_SYNC: + ret = rga_blit_sync(session, req); + break; + case RGA_BLIT_ASYNC: + break; + case RGA_FLUSH: + break; + case RGA_GET_RESULT: + break; + case RGA_GET_VERSION: + //ret = 0; + break; + default: + ERR("unknown ioctl cmd!\n"); + ret = -EINVAL; + break; + } + + mutex_unlock(&rga_service.mutex); + + return ret; +} + + static int rga_open(struct inode *inode, struct file *file) { - unsigned long flag; rga_session *session = kzalloc(sizeof(rga_session), GFP_KERNEL); if (NULL == session) { pr_err("unable to allocate memory for rga_session."); @@ -1001,103 +1079,69 @@ static int rga_open(struct inode *inode, struct file *file) session->pid = current->pid; //printk(KERN_DEBUG "+"); - + INIT_LIST_HEAD(&session->waiting); INIT_LIST_HEAD(&session->running); INIT_LIST_HEAD(&session->list_session); init_waitqueue_head(&session->wait); - spin_lock_irqsave(&rga_service.lock, flag); - list_add_tail(&session->list_session, &rga_service.session); - spin_unlock_irqrestore(&rga_service.lock, flag); + mutex_lock(&rga_service.lock); + list_add_tail(&session->list_session, &rga_service.session); + mutex_unlock(&rga_service.lock); atomic_set(&session->task_running, 0); atomic_set(&session->num_done, 0); - + file->private_data = (void *)session; - //DBG("*** rga dev opened by pid %d *** \n", session->pid); + //DBG("*** rga dev opened by pid %d *** \n", session->pid); return nonseekable_open(inode, file); - + } static int rga_release(struct inode *inode, struct file *file) { int task_running; - unsigned long flag; rga_session *session = (rga_session *)file->private_data; if (NULL == session) return -EINVAL; //printk(KERN_DEBUG "-"); task_running = atomic_read(&session->task_running); - if (task_running) + if (task_running) { - pr_err("rga_service session %d still has %d task running when closing\n", session->pid, task_running); + pr_err("rga_service session %d still has %d task running when closing\n", session->pid, task_running); msleep(100); - /*ͬ²½*/ + /*ͬ²½*/ } - - wake_up_interruptible_sync(&session->wait); - spin_lock_irqsave(&rga_service.lock, flag); + + wake_up(&session->wait); + mutex_lock(&rga_service.lock); list_del(&session->list_session); rga_service_session_clear(session); kfree(session); - spin_unlock_irqrestore(&rga_service.lock, flag); + mutex_unlock(&rga_service.lock); //DBG("*** rga dev close ***\n"); return 0; } -static irqreturn_t rga_irq(int irq, void *dev_id) +static irqreturn_t rga_irq_thread(int irq, void *dev_id) { - unsigned long flag; - - /*clear INT */ - rga_write(rga_read(RGA_INT) | (0x1<<6) | (0x1<<7) | (0x1<<4), RGA_INT); + mutex_lock(&rga_service.lock); + if (rga_service.enable) { + rga_del_running_list(); + rga_try_set_reg(); + } + mutex_unlock(&rga_service.lock); - spin_lock_irqsave(&rga_service.lock, flag); - rga_del_running_list(); - - if(!list_empty(&rga_service.waiting)) - { - spin_unlock_irqrestore(&rga_service.lock, flag); - rga_try_set_reg(1); - } - else - { - spin_unlock_irqrestore(&rga_service.lock, flag); - } - return IRQ_HANDLED; } -static int rga_suspend(struct platform_device *pdev, pm_message_t state) +static irqreturn_t rga_irq(int irq, void *dev_id) { - uint32_t enable; - - enable = rga_service.enable; - rga_power_off(NULL); - rga_service.enable = enable; - - return 0; -} - -static int rga_resume(struct platform_device *pdev) -{ - if(rga_service.enable) - { - rga_service.enable = false; - rga_power_on(); - rga_try_set_reg(1); - } - - return 0; -} + /*clear INT */ + rga_write(rga_read(RGA_INT) | (0x1<<6) | (0x1<<7) | (0x1<<4), RGA_INT); -static void rga_shutdown(struct platform_device *pdev) -{ - pr_cont("shutdown..."); - rga_power_off(NULL); - pr_cont("done\n"); + return IRQ_WAKE_THREAD; } struct file_operations rga_fops = { @@ -1113,88 +1157,80 @@ static struct miscdevice rga_dev ={ .fops = &rga_fops, }; -static int __devinit rga_drv_probe(struct platform_device *pdev) + +#if defined(CONFIG_OF) +static const struct of_device_id rockchip_rga_dt_ids[] = { + { .compatible = "rockchip,rga", }, + {}, +}; +#endif + +static int rga_drv_probe(struct platform_device *pdev) { struct rga_drvdata *data; + struct resource *res; + //struct device_node *np = pdev->dev.of_node; int ret = 0; - data = kzalloc(sizeof(struct rga_drvdata), GFP_KERNEL); - - INIT_LIST_HEAD(&rga_service.waiting); - INIT_LIST_HEAD(&rga_service.running); - INIT_LIST_HEAD(&rga_service.done); - INIT_LIST_HEAD(&rga_service.session); - spin_lock_init(&rga_service.lock); - spin_lock_init(&rga_service.lock_power); - atomic_set(&rga_service.total_running, 0); - atomic_set(&rga_service.src_format_swt, 0); - rga_service.last_prc_src_format = 1; /* default is yuv first*/ - rga_service.enable = false; - - if(NULL == data) - { + mutex_init(&rga_service.lock); + mutex_init(&rga_service.mutex); + atomic_set(&rga_service.total_running, 0); + atomic_set(&rga_service.src_format_swt, 0); + rga_service.last_prc_src_format = 1; /* default is yuv first*/ + rga_service.enable = false; + + data = devm_kzalloc(&pdev->dev, sizeof(struct rga_drvdata), GFP_KERNEL); + if(! data) { ERR("failed to allocate driver data.\n"); - return -ENOMEM; - } - - pd_rga = clk_get(NULL, "pd_rga"); - aclk_rga = clk_get(NULL, "aclk_rga"); - if (IS_ERR(aclk_rga)) - { - ERR("failed to find rga axi clock source.\n"); - ret = -ENOENT; - goto err_clock; + return -ENOMEM; } - hclk_rga = clk_get(NULL, "hclk_rga"); - if (IS_ERR(hclk_rga)) - { - ERR("failed to find rga ahb clock source.\n"); - ret = -ENOENT; - goto err_clock; - } + INIT_DELAYED_WORK(&data->power_off_work, rga_power_off_work); + wake_lock_init(&data->wake_lock, WAKE_LOCK_SUSPEND, "rga"); - rga_power_on(); - - /* map the memory */ - if (!request_mem_region(RK30_RGA_PHYS, RK30_RGA_SIZE, "rga_io")) - { - pr_info("failed to reserve rga HW regs\n"); - return -EBUSY; - } - data->rga_base = (void*)ioremap_nocache(RK30_RGA_PHYS, RK30_RGA_SIZE); - if (data->rga_base == NULL) - { + //data->pd_rga = devm_clk_get(&pdev->dev, "pd_rga"); + data->aclk_rga = devm_clk_get(&pdev->dev, "aclk_rga"); + data->hclk_rga = devm_clk_get(&pdev->dev, "hclk_rga"); + + /* map the registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->rga_base = devm_ioremap_resource(&pdev->dev, res); + if (!data->rga_base) { ERR("rga ioremap failed\n"); ret = -ENOENT; goto err_ioremap; } /* get the IRQ */ - data->irq0 = pdev->resource[1].start; - printk("rga irq %d\n", data->irq0); - if (data->irq0 <= 0) - { - ERR("failed to get rga irq resource (%d).\n", data->irq0); - ret = data->irq0; + data->irq = ret = platform_get_irq(pdev, 0); + if (ret <= 0) { + ERR("failed to get rga irq resource (%d).\n", data->irq); + ret = data->irq; goto err_irq; } /* request the IRQ */ - ret = request_irq(data->irq0, rga_irq, 0/*IRQF_DISABLED*/, "rga", pdev); + //ret = request_threaded_irq(data->irq, rga_irq, rga_irq_thread, 0, "rga", pdev); + ret = devm_request_threaded_irq(&pdev->dev, data->irq, rga_irq, rga_irq_thread, 0, "rga", data); if (ret) { ERR("rga request_irq failed (%d).\n", ret); goto err_irq; } - mutex_init(&rga_service.mutex); - INIT_DELAYED_WORK(&data->power_off_work, rga_power_off); - data->rga_irq_callback = NULL; - platform_set_drvdata(pdev, data); drvdata = data; - + + #if defined(CONFIG_ION_ROCKCHIP) + data->ion_client = rockchip_ion_client_create("rga"); + if (IS_ERR(data->ion_client)) { + dev_err(&pdev->dev, "failed to create ion client for rga"); + return PTR_ERR(data->ion_client); + } else { + dev_info(&pdev->dev, "rga ion client create success!\n"); + } + #endif + ret = misc_register(&rga_dev); if(ret) { @@ -1202,19 +1238,17 @@ static int __devinit rga_drv_probe(struct platform_device *pdev) goto err_misc_register; } - rga_power_off(NULL); - - DBG("RGA Driver loaded succesfully\n"); + pr_info("Driver loaded succesfully\n"); - return 0; + return 0; err_misc_register: - free_irq(data->irq0, pdev); + free_irq(data->irq, pdev); err_irq: iounmap(data->rga_base); err_ioremap: -err_clock: - kfree(data); + wake_lock_destroy(&data->wake_lock); + //kfree(data); return ret; } @@ -1222,33 +1256,28 @@ err_clock: static int rga_drv_remove(struct platform_device *pdev) { struct rga_drvdata *data = platform_get_drvdata(pdev); - DBG("%s [%d]\n",__FUNCTION__,__LINE__); + DBG("%s [%d]\n",__FUNCTION__,__LINE__); - misc_deregister(&(data->miscdev)); - free_irq(data->irq0, &data->miscdev); - iounmap((void __iomem *)(data->rga_base)); + wake_lock_destroy(&data->wake_lock); + misc_deregister(&(data->miscdev)); + free_irq(data->irq, &data->miscdev); + iounmap((void __iomem *)(data->rga_base)); - if(aclk_rga) { - clk_put(aclk_rga); - } - - if(hclk_rga) { - clk_put(hclk_rga); - } + //clk_put(data->pd_rga); + devm_clk_put(&pdev->dev, data->aclk_rga); + devm_clk_put(&pdev->dev, data->hclk_rga); - kfree(data); - return 0; + //kfree(data); + return 0; } static struct platform_driver rga_driver = { .probe = rga_drv_probe, - .remove = __devexit_p(rga_drv_remove), - .suspend = rga_suspend, - .resume = rga_resume, - .shutdown = rga_shutdown, + .remove = rga_drv_remove, .driver = { .owner = THIS_MODULE, .name = "rga", + .of_match_table = of_match_ptr(rockchip_rga_dt_ids), }, }; @@ -1266,7 +1295,7 @@ static int __init rga_init(void) /* malloc pre scale mid buf mmu table */ mmu_buf = kzalloc(1024*8, GFP_KERNEL); - if(mmu_buf == NULL) + if(mmu_buf == NULL) { printk(KERN_ERR "RGA get Pre Scale buff failed. \n"); return -1; @@ -1274,18 +1303,18 @@ static int __init rga_init(void) /* malloc 8 M buf */ for(i=0; i<2048; i++) - { + { buf_p = (uint32_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO); if(buf_p == NULL) { printk(KERN_ERR "RGA init pre scale buf falied\n"); return -ENOMEM; } - - mmu_buf[i] = virt_to_phys((void *)((uint32_t)buf_p)); + + mmu_buf[i] = virt_to_phys((void *)((uint32_t)buf_p)); } - - rga_service.pre_scale_buf = (uint32_t *)mmu_buf; + + rga_service.pre_scale_buf = (uint32_t *)mmu_buf; if ((ret = platform_driver_register(&rga_driver)) != 0) { @@ -1293,10 +1322,33 @@ static int __init rga_init(void) return ret; } - //rga_test_0(); - - INFO("Module initialized.\n"); - + { + rga_session_global.pid = 0x0000ffff; + INIT_LIST_HEAD(&rga_session_global.waiting); + INIT_LIST_HEAD(&rga_session_global.running); + INIT_LIST_HEAD(&rga_session_global.list_session); + + INIT_LIST_HEAD(&rga_service.waiting); + INIT_LIST_HEAD(&rga_service.running); + INIT_LIST_HEAD(&rga_service.done); + INIT_LIST_HEAD(&rga_service.session); + + init_waitqueue_head(&rga_session_global.wait); + //mutex_lock(&rga_service.lock); + list_add_tail(&rga_session_global.list_session, &rga_service.session); + //mutex_unlock(&rga_service.lock); + atomic_set(&rga_session_global.task_running, 0); + atomic_set(&rga_session_global.num_done, 0); + } + + + + #if RGA_TEST_CASE + rga_test_0(); + #endif + + INFO("Module initialized.\n"); + return 0; } @@ -1304,31 +1356,24 @@ static void __exit rga_exit(void) { uint32_t i; - rga_power_off(NULL); + rga_power_off(); for(i=0; i<2048; i++) { if((uint32_t *)rga_service.pre_scale_buf[i] != NULL) { __free_page((void *)rga_service.pre_scale_buf[i]); - } + } } - + if(rga_service.pre_scale_buf != NULL) { kfree((uint8_t *)rga_service.pre_scale_buf); } - platform_driver_unregister(&rga_driver); + platform_driver_unregister(&rga_driver); } -#if 0 - -#include "320x240_swap0_Y4200.h" -#include "320x240_swap0_U4200.h" -#include "320x240_swap0_V4200.h" -#include "320x240_swap0_UV4200.h" -#include "320x240_swap0_ABGR8888.h" - +#if RGA_TEST_CASE extern struct fb_info * rk_get_fb(int fb_id); EXPORT_SYMBOL(rk_get_fb); @@ -1338,12 +1383,17 @@ EXPORT_SYMBOL(rk_direct_fb_show); unsigned int src_buf[1920*1080]; unsigned int dst_buf[1920*1080]; +//unsigned int tmp_buf[1920*1080 * 2]; void rga_test_0(void) { struct rga_req req; rga_session session; unsigned int *src, *dst; + uint32_t i, j; + uint8_t *p; + uint8_t t; + uint32_t *dst0, *dst1, *dst2; struct fb_info *fb; @@ -1361,40 +1411,54 @@ void rga_test_0(void) fb = rk_get_fb(0); memset(&req, 0, sizeof(struct rga_req)); - src = Y4200_320_240_swap0; + src = src_buf; dst = dst_buf; - //memset(src_buf, 0x80, 1920*1080*4); + memset(src_buf, 0x80, 1024*600*4); + + dmac_flush_range(&src_buf[0], &src_buf[1024*600]); + outer_flush_range(virt_to_phys(&src_buf[0]),virt_to_phys(&src_buf[1024*600])); + - //dmac_flush_range(&src_buf[0], &src_buf[1920*1080]); - //outer_flush_range(virt_to_phys(&src_buf[0]),virt_to_phys(&src_buf[1024*1024])); - #if 0 memset(src_buf, 0x80, 800*480*4); memset(dst_buf, 0xcc, 800*480*4); - + dmac_flush_range(&dst_buf[0], &dst_buf[800*480]); outer_flush_range(virt_to_phys(&dst_buf[0]),virt_to_phys(&dst_buf[800*480])); #endif - - req.src.act_w = 320; - req.src.act_h = 240; - req.src.vir_w = 320; - req.src.vir_h = 240; - req.src.yrgb_addr = (uint32_t)src; - req.src.uv_addr = (uint32_t)UV4200_320_240_swap0; - req.src.v_addr = (uint32_t)V4200_320_240_swap0; - req.src.format = RK_FORMAT_YCbCr_420_SP; + dst0 = &dst_buf[0]; + //dst1 = &dst_buf[1280*800*4]; + //dst2 = &dst_buf[1280*800*4*2]; + + i = j = 0; + + printk("\n********************************\n"); + printk("************ RGA_TEST ************\n"); + printk("********************************\n\n"); + + req.src.act_w = 1024; + req.src.act_h = 600; - req.dst.act_w = 1280; - req.dst.act_h = 800; + req.src.vir_w = 1024; + req.src.vir_h = 600; + req.src.yrgb_addr = (uint32_t)virt_to_phys(src); + req.src.uv_addr = (uint32_t)(req.src.yrgb_addr + 1080*1920); + req.src.v_addr = (uint32_t)virt_to_phys(src); + req.src.format = RK_FORMAT_RGBA_8888; + + req.dst.act_w = 600; + req.dst.act_h = 352; req.dst.vir_w = 1280; req.dst.vir_h = 800; - req.dst.x_offset = 0; + req.dst.x_offset = 600; req.dst.y_offset = 0; - req.dst.yrgb_addr = (uint32_t)dst; + + dst = dst0; + + req.dst.yrgb_addr = ((uint32_t)virt_to_phys(dst)); //req.dst.format = RK_FORMAT_RGB_565; @@ -1405,39 +1469,46 @@ void rga_test_0(void) //req.render_mode = color_fill_mode; //req.fg_color = 0x80ffffff; - + req.rotate_mode = 1; - req.scale_mode = 2; + //req.scale_mode = 2; //req.alpha_rop_flag = 0; - //req.alpha_rop_mode = 0x1; + //req.alpha_rop_mode = 0x19; + //req.PD_mode = 3; - req.sina = 0; - req.cosa = 65536; + req.sina = 65536; + req.cosa = 0; + + //req.mmu_info.mmu_flag = 0x21; + //req.mmu_info.mmu_en = 1; + + //printk("src = %.8x\n", req.src.yrgb_addr); + //printk("src = %.8x\n", req.src.uv_addr); + //printk("dst = %.8x\n", req.dst.yrgb_addr); - req.mmu_info.mmu_flag = 0x21; - req.mmu_info.mmu_en = 1; rga_blit_sync(&session, &req); + #if 1 fb->var.bits_per_pixel = 32; fb->var.xres = 1280; fb->var.yres = 800; - + fb->var.red.length = 8; fb->var.red.offset = 0; fb->var.red.msb_right = 0; - + fb->var.green.length = 8; fb->var.green.offset = 8; fb->var.green.msb_right = 0; - + fb->var.blue.length = 8; - + fb->var.blue.offset = 16; fb->var.blue.msb_right = 0; - + fb->var.transp.length = 8; fb->var.transp.offset = 24; fb->var.transp.msb_right = 0; @@ -1447,8 +1518,9 @@ void rga_test_0(void) fb->fix.smem_start = virt_to_phys(dst); - rk_direct_fb_show(fb); - + rk_direct_fb_show(fb); + #endif + } #endif