aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSammy He <r62914@freescale.com>2011-10-26 20:46:39 +0800
committerEric Miao <eric.miao@canonical.com>2011-11-10 07:38:53 +0800
commitf455018396dad3d61b6e6d535cba29aeec8dcbf3 (patch)
treed3a6770abb48e22b21831d065234f4f992a0d893 /drivers
parentb71e825e2a56a344440dff851637d519170e05d2 (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')
-rw-r--r--drivers/mxc/vpu/mxc_vpu.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c
index b622f91b68b..8a11487fc0e 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;