mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 12:57:06 +09:00
fix tower defence rga softreset bug
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user