From cb1de10385fa81c3a94b8123d1c0ed45af77454e Mon Sep 17 00:00:00 2001 From: zsq Date: Mon, 23 Apr 2012 12:13:12 +0000 Subject: [PATCH] fix tower defence rga softreset bug --- drivers/video/rockchip/rga/rga.h | 2 + drivers/video/rockchip/rga/rga_drv.c | 99 +++++++++++++++++------ drivers/video/rockchip/rga/rga_mmu_info.c | 13 ++- 3 files changed, 86 insertions(+), 28 deletions(-) diff --git a/drivers/video/rockchip/rga/rga.h b/drivers/video/rockchip/rga/rga.h index d9d05f8d3b6a..0a8e1d0abe6c 100755 --- a/drivers/video/rockchip/rga/rga.h +++ b/drivers/video/rockchip/rga/rga.h @@ -355,6 +355,8 @@ struct rga_reg { uint32_t cmd_reg[RGA_REG_CMD_LEN]; uint32_t *MMU_base; atomic_t int_enable; + + struct rga_req req; }; diff --git a/drivers/video/rockchip/rga/rga_drv.c b/drivers/video/rockchip/rga/rga_drv.c index 725ed796ae9f..3e98eb752577 100755 --- a/drivers/video/rockchip/rga/rga_drv.c +++ b/drivers/video/rockchip/rga/rga_drv.c @@ -52,12 +52,12 @@ #define RGA_TEST 0 #define RGA_TEST_TIME 0 #define RGA_TEST_FLUSH_TIME 0 -#define RGA_INFO_BUS_ERROR 0 +#define RGA_INFO_BUS_ERROR 1 #define PRE_SCALE_BUF_SIZE 2048*1024*4 #define RGA_POWER_OFF_DELAY 4*HZ /* 4s */ -#define RGA_TIMEOUT_DELAY 1*HZ /* 1s */ +#define RGA_TIMEOUT_DELAY 2*HZ /* 2s */ #define RGA_MAJOR 255 @@ -94,10 +94,10 @@ static struct clk *hclk_rga; 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); - /* Logging */ #define RGA_DEBUG 1 #if RGA_DEBUG @@ -267,14 +267,12 @@ static int rga_flush(rga_session *session, unsigned long arg) if (unlikely(ret_timeout < 0)) { pr_err("flush pid %d wait task ret %d\n", session->pid, ret); - rga_soft_reset(); rga_del_running_list(); ret = -ETIMEDOUT; } 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)); - rga_soft_reset(); - rga_del_running_list(); + rga_del_running_list_timeout(); rga_try_set_reg(1); ret = -ETIMEDOUT; } @@ -395,6 +393,8 @@ static struct rga_reg * rga_reg_init(rga_session *session, struct rga_req *req) reg->session = session; INIT_LIST_HEAD(®->session_link); INIT_LIST_HEAD(®->status_link); + + memcpy(®->req, req, sizeof(struct rga_req)); if (req->mmu_info.mmu_en) { @@ -460,6 +460,9 @@ 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); @@ -563,14 +566,14 @@ static void rga_try_set_reg(uint32_t num) else { /* RGA is idle */ - reg = list_entry(rga_service.waiting.next, struct rga_reg, status_link); - rga_soft_reset(); + 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 */ @@ -589,10 +592,10 @@ static void rga_try_set_reg(uint32_t num) #endif /* master mode */ - rga_write(0x1<<2, RGA_SYS_CTRL); + rga_write((0x1<<2)|(0x1<<3), RGA_SYS_CTRL); /* All CMD finish int */ - rga_write((0x1<<10)|(0x1<<8), RGA_INT); + rga_write(rga_read(RGA_INT)|(0x1<<10)|(0x1<<8), RGA_INT); /* Start proc */ atomic_set(®->session->done, 0); @@ -616,7 +619,7 @@ static void rga_try_set_reg(uint32_t num) } -#if RGA_TEST +#if 1//RGA_TEST static void print_info(struct rga_req *req) { printk("src.yrgb_addr = %.8x, src.uv_addr = %.8x, src.v_addr = %.8x\n", @@ -663,6 +666,50 @@ static void rga_del_running_list(void) } } +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); + + if(reg->MMU_base != NULL) + { + kfree(reg->MMU_base); + } + + atomic_sub(1, ®->session->task_running); + atomic_sub(1, &rga_service.total_running); + + + #if 0 + printk("RGA_INT is %.8x\n", rga_read(RGA_INT)); + printk("reg->session->task_running = %d\n", atomic_read(®->session->task_running)); + printk("rga_service.total_running = %d\n", atomic_read(&rga_service.total_running)); + + print_info(®->req); + + { + uint32_t *p, 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); + } + + rga_reg_deinit(reg); + } +} + + static int rga_blit(rga_session *session, struct rga_req *req) { @@ -785,15 +832,13 @@ static int rga_blit_sync(rga_session *session, struct rga_req *req) if (unlikely(ret_timeout< 0)) { pr_err("sync pid %d wait task ret %d\n", session->pid, ret_timeout); - rga_soft_reset(); rga_del_running_list(); 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)); - rga_soft_reset(); - rga_del_running_list(); + rga_del_running_list_timeout(); rga_try_set_reg(1); ret = -ETIMEDOUT; } @@ -850,7 +895,15 @@ static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg) break; } rga_power_on(); - ret = rga_blit_async(session, req); + + if((atomic_read(&rga_service.total_running) > 16)) + { + ret = rga_blit_sync(session, req); + } + else + { + ret = rga_blit_async(session, req); + } break; case RGA_FLUSH: ret = rga_flush(session, arg); @@ -933,24 +986,20 @@ static irqreturn_t rga_irq(int irq, void *dev_id) #if RGA_TEST printk("rga_irq is valid\n"); - #endif - - while(((rga_read(RGA_STATUS) & 0x1) != 0) && (i<10))// idle - { - mdelay(1); - i++; - } + #endif - #if RGA_INFO_BUS_ERROR + #if 0//RGA_INFO_BUS_ERROR if(rga_read(RGA_INT) & 0x1) { printk("bus Error interrupt is occur\n"); + rga_soft_reset(); } #endif - /*clear INT */ + /*clear INT */ rga_write(rga_read(RGA_INT) | (0x1<<6) | (0x1<<7) | (0x1<<4), RGA_INT); - spin_lock_irqsave(&rga_service.lock, flag); + + spin_lock_irqsave(&rga_service.lock, flag); rga_del_running_list(); spin_unlock_irqrestore(&rga_service.lock, flag); diff --git a/drivers/video/rockchip/rga/rga_mmu_info.c b/drivers/video/rockchip/rga/rga_mmu_info.c index e41c3dc41dde..181c266f7573 100755 --- a/drivers/video/rockchip/rga/rga_mmu_info.c +++ b/drivers/video/rockchip/rga/rga_mmu_info.c @@ -373,7 +373,7 @@ static int rga_mmu_info_BitBlt_mode(struct rga_reg *reg, struct rga_req *req) { /* cal src buf mmu info */ SrcMemSize = rga_buf_size_cal(req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr, - req->src.format, req->src.vir_w, req->src.vir_h, + req->src.format, req->src.vir_w, req->src.act_h + req->src.y_offset, &SrcStart); if(SrcMemSize == 0) { return -EINVAL; @@ -381,7 +381,7 @@ static int rga_mmu_info_BitBlt_mode(struct rga_reg *reg, struct rga_req *req) /* cal dst buf mmu info */ DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr, - req->dst.format, req->dst.vir_w, req->dst.vir_h, + req->dst.format, req->dst.vir_w, req->dst.act_h + req->dst.y_offset, &DstStart); if(DstMemSize == 0) { return -EINVAL; @@ -465,6 +465,8 @@ static int rga_mmu_info_BitBlt_mode(struct rga_reg *reg, struct rga_req *req) } } + MMU_Base[AllSize] = MMU_Base[AllSize - 1]; + /* zsq * change the buf address in req struct */ @@ -710,7 +712,8 @@ static int rga_mmu_info_color_fill_mode(struct rga_reg *reg, struct rga_req *req MMU_p[i] = (uint32_t)virt_to_phys((uint32_t *)((DstStart + i) << PAGE_SHIFT)); } } - + + MMU_Base[AllSize] = MMU_Base[AllSize - 1]; /* zsq * change the buf address in req struct @@ -923,6 +926,8 @@ static int rga_mmu_info_blur_sharp_filter_mode(struct rga_reg *reg, struct rga_r } } + MMU_Base[AllSize] = MMU_Base[AllSize - 1]; + /* zsq * change the buf address in req struct * for the reason of lie to MMU @@ -1077,6 +1082,8 @@ static int rga_mmu_info_pre_scale_mode(struct rga_reg *reg, struct rga_req *req) } } + MMU_Base[AllSize] = MMU_Base[AllSize - 1]; + /* zsq * change the buf address in req struct * for the reason of lie to MMU -- 2.34.1