diff options
author | Sammy He <r62914@freescale.com> | 2011-10-26 20:46:39 +0800 |
---|---|---|
committer | Jason Liu <r64343@freescale.com> | 2012-01-09 21:02:57 +0800 |
commit | 6a881ff9d783e68bd2233d35cdfa8ba8d99002a9 (patch) | |
tree | c2a70a0023f7ea82bbf66db2458d42bd137f1a58 /drivers/mxc/vpu | |
parent | 2a3e5d31f38ff61c8efda6814d18447ea8b31d3a (diff) |
ENGR00160802-2 vpu: Check interrupt reason before disable clock
There may be more interrupt than PIC_DONE reported, we cannot disable
clock if picture isn't done since vpu is still in busy in the status.
This patch will check interrupt reason before clock is disabled.
Signed-off-by: Sammy He <r62914@freescale.com>
Diffstat (limited to 'drivers/mxc/vpu')
-rw-r--r-- | drivers/mxc/vpu/mxc_vpu.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c index b622f91b68be..8a11487fc0e6 100644 --- a/drivers/mxc/vpu/mxc_vpu.c +++ b/drivers/mxc/vpu/mxc_vpu.c @@ -86,6 +86,7 @@ static struct mxc_vpu_platform_data *vpu_plat; static struct iram_setting iram; /* implement the blocking ioctl */ +static int irq_status; static int codec_done; static wait_queue_head_t vpu_queue; @@ -211,14 +212,17 @@ static inline void vpu_worker_callback(struct work_struct *w) if (dev->async_queue) kill_fasync(&dev->async_queue, SIGIO, POLL_IN); - codec_done = 1; - wake_up_interruptible(&vpu_queue); - + irq_status = 1; /* * Clock is gated on when dec/enc started, gate it off when - * interrupt is received. + * codec is done. */ - clk_disable(vpu_clk); + if (codec_done) { + clk_disable(vpu_clk); + codec_done = 0; + } + + wake_up_interruptible(&vpu_queue); } /*! @@ -227,8 +231,11 @@ static inline void vpu_worker_callback(struct work_struct *w) static irqreturn_t vpu_ipi_irq_handler(int irq, void *dev_id) { struct vpu_priv *dev = dev_id; + unsigned long reg; - READ_REG(BIT_INT_STATUS); + reg = READ_REG(BIT_INT_REASON); + if (reg & 0x8) + codec_done = 1; WRITE_REG(0x1, BIT_INT_CLEAR); queue_work(dev->workqueue, &dev->work); @@ -243,8 +250,11 @@ static irqreturn_t vpu_ipi_irq_handler(int irq, void *dev_id) static irqreturn_t vpu_jpu_irq_handler(int irq, void *dev_id) { struct vpu_priv *dev = dev_id; + unsigned long reg; - WRITE_REG(0, MJPEG_PIC_STATUS_REG); + reg = READ_REG(MJPEG_PIC_STATUS_REG); + if (reg & 0x3) + codec_done = 1; queue_work(dev->workqueue, &dev->work); @@ -351,7 +361,7 @@ static long vpu_ioctl(struct file *filp, u_int cmd, { u_long timeout = (u_long) arg; if (!wait_event_interruptible_timeout - (vpu_queue, codec_done != 0, + (vpu_queue, irq_status != 0, msecs_to_jiffies(timeout))) { printk(KERN_WARNING "VPU blocking: timeout.\n"); ret = -ETIME; @@ -360,7 +370,7 @@ static long vpu_ioctl(struct file *filp, u_int cmd, "VPU interrupt received.\n"); ret = -ERESTARTSYS; } else - codec_done = 0; + irq_status = 0; break; } case VPU_IOC_IRAM_SETTING: @@ -677,8 +687,8 @@ static int vpu_dev_probe(struct platform_device *pdev) free_irq(vpu_ipi_irq, &vpu_data); goto err_out_class; } - err = request_irq(vpu_jpu_irq, vpu_jpu_irq_handler, 0, "VPU_JPG_IRQ", - (void *)(&vpu_data)); + err = request_irq(vpu_jpu_irq, vpu_jpu_irq_handler, IRQF_TRIGGER_RISING, + "VPU_JPG_IRQ", (void *)(&vpu_data)); if (err) { free_irq(vpu_ipi_irq, &vpu_data); goto err_out_class; |