diff options
Diffstat (limited to 'drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c')
| -rw-r--r-- | drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c | 46 |
1 files changed, 31 insertions, 15 deletions
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c index 2fe3c9228ac5..4948d734eb02 100644 --- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c @@ -143,7 +143,7 @@ void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq) static void s5p_mfc_watchdog(struct timer_list *t) { - struct s5p_mfc_dev *dev = from_timer(dev, t, watchdog_timer); + struct s5p_mfc_dev *dev = timer_container_of(dev, t, watchdog_timer); if (test_bit(0, &dev->hw_lock)) atomic_inc(&dev->watchdog_cnt); @@ -739,6 +739,20 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) ctx->state = MFCINST_RUNNING; goto irq_cleanup_hw; + case S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET: + ctx->state = MFCINST_NAL_ABORT; + s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); + set_work_bit(ctx); + WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0); + s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); + break; + + case S5P_MFC_R2H_CMD_NAL_ABORT_RET: + ctx->state = MFCINST_ERROR; + s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); + s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); + goto irq_cleanup_hw; + default: mfc_debug(2, "Unknown int reason\n"); s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); @@ -774,8 +788,10 @@ static int s5p_mfc_open(struct file *file) int ret = 0; mfc_debug_enter(); - if (mutex_lock_interruptible(&dev->mfc_mutex)) - return -ERESTARTSYS; + if (mutex_lock_interruptible(&dev->mfc_mutex)) { + ret = -ERESTARTSYS; + goto err_enter; + } dev->num_inst++; /* It is guarded by mfc_mutex in vfd */ /* Allocate memory for context */ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); @@ -785,8 +801,7 @@ static int s5p_mfc_open(struct file *file) } init_waitqueue_head(&ctx->queue); v4l2_fh_init(&ctx->fh, vdev); - file->private_data = &ctx->fh; - v4l2_fh_add(&ctx->fh); + v4l2_fh_add(&ctx->fh, file); ctx->dev = dev; INIT_LIST_HEAD(&ctx->src_queue); INIT_LIST_HEAD(&ctx->dst_queue); @@ -861,7 +876,7 @@ static int s5p_mfc_open(struct file *file) /* Init videobuf2 queue for CAPTURE */ q = &ctx->vq_dst; q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - q->drv_priv = &ctx->fh; + q->drv_priv = ctx; q->lock = &dev->mfc_mutex; if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; @@ -888,7 +903,7 @@ static int s5p_mfc_open(struct file *file) /* Init videobuf2 queue for OUTPUT */ q = &ctx->vq_src; q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - q->drv_priv = &ctx->fh; + q->drv_priv = ctx; q->lock = &dev->mfc_mutex; if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; @@ -933,19 +948,20 @@ err_pwr_enable: if (dev->num_inst == 1) { if (s5p_mfc_power_off(dev) < 0) mfc_err("power off failed\n"); - del_timer_sync(&dev->watchdog_timer); + timer_delete_sync(&dev->watchdog_timer); } err_ctrls_setup: s5p_mfc_dec_ctrls_delete(ctx); err_bad_node: dev->ctx[ctx->num] = NULL; err_no_ctx: - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); v4l2_fh_exit(&ctx->fh); kfree(ctx); err_alloc: dev->num_inst--; mutex_unlock(&dev->mfc_mutex); +err_enter: mfc_debug_leave(); return ret; } @@ -953,7 +969,7 @@ err_alloc: /* Release MFC context */ static int s5p_mfc_release(struct file *file) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; /* if dev is null, do cleanup that doesn't need dev */ @@ -982,7 +998,7 @@ static int s5p_mfc_release(struct file *file) if (dev->num_inst == 0) { mfc_debug(2, "Last instance\n"); s5p_mfc_deinit_hw(dev); - del_timer_sync(&dev->watchdog_timer); + timer_delete_sync(&dev->watchdog_timer); s5p_mfc_clock_off(dev); if (s5p_mfc_power_off(dev) < 0) mfc_err("Power off failed\n"); @@ -994,7 +1010,7 @@ static int s5p_mfc_release(struct file *file) if (dev) dev->ctx[ctx->num] = NULL; s5p_mfc_dec_ctrls_delete(ctx); - v4l2_fh_del(&ctx->fh); + v4l2_fh_del(&ctx->fh, file); /* vdev is gone if dev is null */ if (dev) v4l2_fh_exit(&ctx->fh); @@ -1010,7 +1026,7 @@ static int s5p_mfc_release(struct file *file) static __poll_t s5p_mfc_poll(struct file *file, struct poll_table_struct *wait) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); struct s5p_mfc_dev *dev = ctx->dev; struct vb2_queue *src_q, *dst_q; struct vb2_buffer *src_vb = NULL, *dst_vb = NULL; @@ -1061,7 +1077,7 @@ end: /* Mmap */ static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma) { - struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data); + struct s5p_mfc_ctx *ctx = file_to_ctx(file); unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; int ret; @@ -1458,7 +1474,7 @@ static void s5p_mfc_remove(struct platform_device *pdev) } mutex_unlock(&dev->mfc_mutex); - del_timer_sync(&dev->watchdog_timer); + timer_delete_sync(&dev->watchdog_timer); flush_work(&dev->watchdog_work); video_unregister_device(dev->vfd_enc); |
