Loading drivers/media/platform/msm/camera_v2/fd/Makefile +2 −0 Original line number Diff line number Diff line GCC_VERSION := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc) ccflags-y += -Idrivers/media/video/msm ccflags-y += -Idrivers/media/platform/msm/camera_v2/common ccflags-y += -Idrivers/media/platform/msm/camera_v2 ccflags-y += -Idrivers/media/platform/msm/camera_v2/pproc/cpp obj-$(CONFIG_MSM_FD) += msm_fd_dev.o msm_fd_hw.o drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c +80 −0 Original line number Diff line number Diff line Loading @@ -264,8 +264,10 @@ static void msm_fd_stop_streaming(struct vb2_queue *q) { struct fd_ctx *ctx = vb2_get_drv_priv(q); mutex_lock(&ctx->fd_device->recovery_lock); msm_fd_hw_remove_buffers_from_queue(ctx->fd_device, q); msm_fd_hw_put(ctx->fd_device); mutex_unlock(&ctx->fd_device->recovery_lock); } /* Videobuf2 queue callbacks. */ Loading Loading @@ -325,6 +327,69 @@ static struct vb2_mem_ops msm_fd_vb2_mem_ops = { .put_userptr = msm_fd_put_userptr, }; /* * msm_fd_vbif_error_handler - FD VBIF Error handler * @handle: FD Device handle * @error: CPP-VBIF Error code */ static int msm_fd_vbif_error_handler(void *handle, uint32_t error) { struct fd_ctx *ctx; struct msm_fd_device *fd; struct msm_fd_buffer *active_buf; int ret; if (NULL == handle) { dev_err(fd->dev, "FD Ctx is null, Cannot recover\n"); return 0; } ctx = (struct fd_ctx *)handle; fd = (struct msm_fd_device *)ctx->fd_device; if (error == CPP_VBIF_ERROR_HANG) { mutex_lock(&fd->recovery_lock); dev_err(fd->dev, "Handling FD VBIF Hang\n"); if (fd->state != MSM_FD_DEVICE_RUNNING) { dev_err(fd->dev, "FD is not FD_DEVICE_RUNNING, %d\n", fd->state); mutex_unlock(&fd->recovery_lock); return 0; } fd->recovery_mode = 1; /* Halt and reset */ msm_fd_hw_put(fd); msm_fd_hw_get(fd, ctx->settings.speed); /* Get active buffer */ active_buf = msm_fd_hw_get_active_buffer(fd); if (active_buf == NULL) { dev_dbg(fd->dev, "no active buffer, return\n"); fd->recovery_mode = 0; mutex_unlock(&fd->recovery_lock); return 0; } dev_dbg(fd->dev, "Active Buffer present.. Start re-schedule\n"); /* Queue the buffer again */ msm_fd_hw_add_buffer(fd, active_buf); /* Schedule and restart */ ret = msm_fd_hw_schedule_next_buffer(fd); if (ret) { dev_err(fd->dev, "Cannot reschedule buffer, recovery failed\n"); fd->recovery_mode = 0; mutex_unlock(&fd->recovery_lock); return ret; } dev_dbg(fd->dev, "Restarted FD after VBIF HAng\n"); mutex_unlock(&fd->recovery_lock); } return 0; } /* * msm_fd_open - Fd device open method. * @file: Pointer to file struct. Loading Loading @@ -388,6 +453,10 @@ static int msm_fd_open(struct file *file) goto error_ahb_config; } /* Register with CPP VBIF error handler */ msm_cpp_vbif_register_error_handler((void *)ctx, VBIF_CLIENT_FD, msm_fd_vbif_error_handler); return 0; error_ahb_config: Loading @@ -409,6 +478,10 @@ static int msm_fd_release(struct file *file) { struct fd_ctx *ctx = msm_fd_ctx_from_fh(file->private_data); /* Un-register with CPP VBIF error handler */ msm_cpp_vbif_register_error_handler((void *)ctx, VBIF_CLIENT_FD, NULL); vb2_queue_release(&ctx->vb2_q); vfree(ctx->stats); Loading Loading @@ -1173,6 +1246,12 @@ static void msm_fd_wq_handler(struct work_struct *work) /* Stats are ready, set correct frame id */ atomic_set(&stats->frame_id, ctx->sequence); /* If Recovery mode is on, we got IRQ after recovery, reset it */ if (fd->recovery_mode) { fd->recovery_mode = 0; dev_dbg(fd->dev, "Got IRQ after Recovery\n"); } /* We have the data from fd hw, we can start next processing */ msm_fd_hw_schedule_next_buffer(fd); Loading Loading @@ -1209,6 +1288,7 @@ static int fd_probe(struct platform_device *pdev) mutex_init(&fd->lock); spin_lock_init(&fd->slock); mutex_init(&fd->recovery_lock); init_completion(&fd->hw_halt_completion); INIT_LIST_HEAD(&fd->buf_queue); fd->pdev = pdev; Loading drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h +5 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ #include <linux/msm_ion.h> #include "cam_soc_api.h" #include "cam_hw_ops.h" #include "msm_cpp.h" /* Maximum number of result buffers */ #define MSM_FD_MAX_RESULT_BUFS 5 /* Max number of clocks defined in device tree */ Loading Loading @@ -213,12 +215,14 @@ enum msm_fd_mem_resources { * @work_queue: Pointer to FD device IRQ bottom half workqueue. * @work: IRQ bottom half work struct. * @hw_halt_completion: Completes when face detection hw halt completes. * @recovery_mode: Indicates if FD is in recovery mode */ struct msm_fd_device { u32 hw_revision; struct mutex lock; spinlock_t slock; struct mutex recovery_lock; int ref_count; int irq_num; Loading Loading @@ -247,6 +251,7 @@ struct msm_fd_device { struct workqueue_struct *work_queue; struct work_struct work; struct completion hw_halt_completion; int recovery_mode; }; #endif /* __MSM_FD_DEV_H__ */ drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c +4 −0 Original line number Diff line number Diff line Loading @@ -1058,6 +1058,8 @@ static int msm_fd_hw_enable(struct msm_fd_device *fd, msm_fd_hw_set_direction_angle(fd, buffer->settings.direction_index, buffer->settings.angle_index); msm_fd_hw_run(fd); if (fd->recovery_mode) dev_err(fd->dev, "Scheduled buffer in recovery mode\n"); return 1; } Loading Loading @@ -1259,6 +1261,8 @@ int msm_fd_hw_schedule_next_buffer(struct msm_fd_device *fd) } } else { fd->state = MSM_FD_DEVICE_IDLE; if (fd->recovery_mode) dev_err(fd->dev, "No Buffer in recovery mode.Device Idle\n"); } spin_unlock(&fd->slock); Loading Loading
drivers/media/platform/msm/camera_v2/fd/Makefile +2 −0 Original line number Diff line number Diff line GCC_VERSION := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc) ccflags-y += -Idrivers/media/video/msm ccflags-y += -Idrivers/media/platform/msm/camera_v2/common ccflags-y += -Idrivers/media/platform/msm/camera_v2 ccflags-y += -Idrivers/media/platform/msm/camera_v2/pproc/cpp obj-$(CONFIG_MSM_FD) += msm_fd_dev.o msm_fd_hw.o
drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c +80 −0 Original line number Diff line number Diff line Loading @@ -264,8 +264,10 @@ static void msm_fd_stop_streaming(struct vb2_queue *q) { struct fd_ctx *ctx = vb2_get_drv_priv(q); mutex_lock(&ctx->fd_device->recovery_lock); msm_fd_hw_remove_buffers_from_queue(ctx->fd_device, q); msm_fd_hw_put(ctx->fd_device); mutex_unlock(&ctx->fd_device->recovery_lock); } /* Videobuf2 queue callbacks. */ Loading Loading @@ -325,6 +327,69 @@ static struct vb2_mem_ops msm_fd_vb2_mem_ops = { .put_userptr = msm_fd_put_userptr, }; /* * msm_fd_vbif_error_handler - FD VBIF Error handler * @handle: FD Device handle * @error: CPP-VBIF Error code */ static int msm_fd_vbif_error_handler(void *handle, uint32_t error) { struct fd_ctx *ctx; struct msm_fd_device *fd; struct msm_fd_buffer *active_buf; int ret; if (NULL == handle) { dev_err(fd->dev, "FD Ctx is null, Cannot recover\n"); return 0; } ctx = (struct fd_ctx *)handle; fd = (struct msm_fd_device *)ctx->fd_device; if (error == CPP_VBIF_ERROR_HANG) { mutex_lock(&fd->recovery_lock); dev_err(fd->dev, "Handling FD VBIF Hang\n"); if (fd->state != MSM_FD_DEVICE_RUNNING) { dev_err(fd->dev, "FD is not FD_DEVICE_RUNNING, %d\n", fd->state); mutex_unlock(&fd->recovery_lock); return 0; } fd->recovery_mode = 1; /* Halt and reset */ msm_fd_hw_put(fd); msm_fd_hw_get(fd, ctx->settings.speed); /* Get active buffer */ active_buf = msm_fd_hw_get_active_buffer(fd); if (active_buf == NULL) { dev_dbg(fd->dev, "no active buffer, return\n"); fd->recovery_mode = 0; mutex_unlock(&fd->recovery_lock); return 0; } dev_dbg(fd->dev, "Active Buffer present.. Start re-schedule\n"); /* Queue the buffer again */ msm_fd_hw_add_buffer(fd, active_buf); /* Schedule and restart */ ret = msm_fd_hw_schedule_next_buffer(fd); if (ret) { dev_err(fd->dev, "Cannot reschedule buffer, recovery failed\n"); fd->recovery_mode = 0; mutex_unlock(&fd->recovery_lock); return ret; } dev_dbg(fd->dev, "Restarted FD after VBIF HAng\n"); mutex_unlock(&fd->recovery_lock); } return 0; } /* * msm_fd_open - Fd device open method. * @file: Pointer to file struct. Loading Loading @@ -388,6 +453,10 @@ static int msm_fd_open(struct file *file) goto error_ahb_config; } /* Register with CPP VBIF error handler */ msm_cpp_vbif_register_error_handler((void *)ctx, VBIF_CLIENT_FD, msm_fd_vbif_error_handler); return 0; error_ahb_config: Loading @@ -409,6 +478,10 @@ static int msm_fd_release(struct file *file) { struct fd_ctx *ctx = msm_fd_ctx_from_fh(file->private_data); /* Un-register with CPP VBIF error handler */ msm_cpp_vbif_register_error_handler((void *)ctx, VBIF_CLIENT_FD, NULL); vb2_queue_release(&ctx->vb2_q); vfree(ctx->stats); Loading Loading @@ -1173,6 +1246,12 @@ static void msm_fd_wq_handler(struct work_struct *work) /* Stats are ready, set correct frame id */ atomic_set(&stats->frame_id, ctx->sequence); /* If Recovery mode is on, we got IRQ after recovery, reset it */ if (fd->recovery_mode) { fd->recovery_mode = 0; dev_dbg(fd->dev, "Got IRQ after Recovery\n"); } /* We have the data from fd hw, we can start next processing */ msm_fd_hw_schedule_next_buffer(fd); Loading Loading @@ -1209,6 +1288,7 @@ static int fd_probe(struct platform_device *pdev) mutex_init(&fd->lock); spin_lock_init(&fd->slock); mutex_init(&fd->recovery_lock); init_completion(&fd->hw_halt_completion); INIT_LIST_HEAD(&fd->buf_queue); fd->pdev = pdev; Loading
drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h +5 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ #include <linux/msm_ion.h> #include "cam_soc_api.h" #include "cam_hw_ops.h" #include "msm_cpp.h" /* Maximum number of result buffers */ #define MSM_FD_MAX_RESULT_BUFS 5 /* Max number of clocks defined in device tree */ Loading Loading @@ -213,12 +215,14 @@ enum msm_fd_mem_resources { * @work_queue: Pointer to FD device IRQ bottom half workqueue. * @work: IRQ bottom half work struct. * @hw_halt_completion: Completes when face detection hw halt completes. * @recovery_mode: Indicates if FD is in recovery mode */ struct msm_fd_device { u32 hw_revision; struct mutex lock; spinlock_t slock; struct mutex recovery_lock; int ref_count; int irq_num; Loading Loading @@ -247,6 +251,7 @@ struct msm_fd_device { struct workqueue_struct *work_queue; struct work_struct work; struct completion hw_halt_completion; int recovery_mode; }; #endif /* __MSM_FD_DEV_H__ */
drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c +4 −0 Original line number Diff line number Diff line Loading @@ -1058,6 +1058,8 @@ static int msm_fd_hw_enable(struct msm_fd_device *fd, msm_fd_hw_set_direction_angle(fd, buffer->settings.direction_index, buffer->settings.angle_index); msm_fd_hw_run(fd); if (fd->recovery_mode) dev_err(fd->dev, "Scheduled buffer in recovery mode\n"); return 1; } Loading Loading @@ -1259,6 +1261,8 @@ int msm_fd_hw_schedule_next_buffer(struct msm_fd_device *fd) } } else { fd->state = MSM_FD_DEVICE_IDLE; if (fd->recovery_mode) dev_err(fd->dev, "No Buffer in recovery mode.Device Idle\n"); } spin_unlock(&fd->slock); Loading