diff options
Diffstat (limited to 'drivers/media/platform/msm/camera_v2')
-rw-r--r-- | drivers/media/platform/msm/camera_v2/isp/msm_isp.h | 2 | ||||
-rw-r--r-- | drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 74 | ||||
-rw-r--r-- | drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h | 1 |
3 files changed, 63 insertions, 14 deletions
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index d6d49d8c148b..50688b61c3d5 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -19,7 +19,7 @@ #include <linux/io.h> #include <linux/list.h> #include <linux/delay.h> -#include <linux/avtimer.h> +#include <linux/avtimer_kernel.h> #include <media/v4l2-subdev.h> #include <media/msmb_isp.h> #include <linux/msm-bus.h> diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index 841160ef8e63..a9aa9a7f3692 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -107,6 +107,8 @@ static int msm_cpp_buffer_ops(struct cpp_device *cpp_dev, qcmd; \ }) +#define MSM_CPP_MAX_TIMEOUT_TRIAL 3 + struct msm_cpp_timer_data_t { struct cpp_device *cpp_dev; struct msm_cpp_frame_info_t *processed_frame; @@ -177,6 +179,14 @@ static void msm_cpp_write(u32 data, void __iomem *cpp_base) writel_relaxed((data), cpp_base + MSM_CPP_MICRO_FIFO_RX_DATA); } +static void msm_cpp_clear_timer(struct cpp_device *cpp_dev) +{ + atomic_set(&cpp_timer.used, 0); + del_timer(&cpp_timer.cpp_timer); + cpp_timer.data.processed_frame = NULL; + cpp_dev->timeout_trial_cnt = 0; +} + static uint32_t msm_cpp_read(void __iomem *cpp_base) { uint32_t tmp, retry = 0; @@ -620,7 +630,6 @@ void msm_cpp_do_tasklet(unsigned long data) uint32_t tx_fifo[MSM_CPP_TX_FIFO_LEVEL]; struct cpp_device *cpp_dev = (struct cpp_device *) data; struct msm_cpp_tasklet_queue_cmd *queue_cmd; - struct msm_cpp_timer_t *timer = NULL; while (atomic_read(&cpp_dev->irq_cnt)) { spin_lock_irqsave(&cpp_dev->tasklet_lock, flags); @@ -649,19 +658,13 @@ void msm_cpp_do_tasklet(unsigned long data) CPP_DBG("Frame done!!\n"); /* delete CPP timer */ CPP_DBG("delete timer.\n"); - timer = &cpp_timer; - atomic_set(&timer->used, 0); - del_timer(&timer->cpp_timer); - timer->data.processed_frame = NULL; + msm_cpp_clear_timer(cpp_dev); msm_cpp_notify_frame_done(cpp_dev); } else if (msg_id == MSM_CPP_MSG_ID_FRAME_NACK) { pr_err("NACK error from hw!!\n"); CPP_DBG("delete timer.\n"); - timer = &cpp_timer; - atomic_set(&timer->used, 0); - del_timer(&timer->cpp_timer); - timer->data.processed_frame = NULL; + msm_cpp_clear_timer(cpp_dev); msm_cpp_notify_frame_done(cpp_dev); } i += cmd_len + 2; @@ -1090,6 +1093,7 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) pr_debug("DEBUG_R1: 0x%x\n", msm_camera_io_r(cpp_dev->cpp_hw_base + 0x8C)); msm_camera_io_w(0x0, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL); + msm_cpp_clear_timer(cpp_dev); cpp_deinit_mem(cpp_dev); if (cpp_dev->iommu_state == CPP_IOMMU_STATE_ATTACHED) { iommu_detach_device(cpp_dev->domain, @@ -1227,8 +1231,9 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) pr_err("cpp_timer_callback called. (jiffies=%lu)\n", jiffies); - if (!work) { - pr_err("Invalid work:%p\n", work); + if (!work || cpp_timer.data.cpp_dev->state != CPP_STATE_ACTIVE) { + pr_err("Invalid work:%p or state:%d\n", work, + cpp_timer.data.cpp_dev->state); return; } if (!atomic_read(&cpp_timer.used)) { @@ -1252,6 +1257,14 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) return; } + if (cpp_timer.data.cpp_dev->timeout_trial_cnt >= + MSM_CPP_MAX_TIMEOUT_TRIAL) { + pr_info("Max trial reached\n"); + msm_cpp_notify_frame_done(cpp_timer.data.cpp_dev); + cpp_timer.data.cpp_dev->timeout_trial_cnt = 0; + return; + } + this_frame = cpp_timer.data.processed_frame; pr_err("Starting timer to fire in %d ms. (jiffies=%lu)\n", CPP_CMD_TIMEOUT_MS, jiffies); @@ -1267,6 +1280,7 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) for (i = 0; i < this_frame->msg_len; i++) msm_cpp_write(this_frame->cpp_cmd_msg[i], cpp_timer.data.cpp_dev->base); + cpp_timer.data.cpp_dev->timeout_trial_cnt++; return; } @@ -1535,6 +1549,26 @@ ERROR1: return rc; } +void msm_cpp_clean_queue(struct cpp_device *cpp_dev) +{ + struct msm_queue_cmd *frame_qcmd = NULL; + struct msm_cpp_frame_info_t *processed_frame = NULL; + struct msm_device_queue *queue = NULL; + + while (cpp_dev->processing_q.len) { + pr_info("queue len:%d\n", cpp_dev->processing_q.len); + queue = &cpp_dev->processing_q; + frame_qcmd = msm_dequeue(queue, list_frame); + if (frame_qcmd) { + processed_frame = frame_qcmd->command; + kfree(frame_qcmd); + if (processed_frame) + kfree(processed_frame->cpp_cmd_msg); + kfree(processed_frame); + } + } +} + long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -1695,6 +1729,11 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, kfree(k_stream_buff_info.buffer_info); kfree(u_stream_buff_info); + if (cpp_dev->stream_cnt == 0) { + cpp_dev->state = CPP_STATE_ACTIVE; + msm_cpp_clear_timer(cpp_dev); + msm_cpp_clean_queue(cpp_dev); + } if (cmd != VIDIOC_MSM_CPP_APPEND_STREAM_BUFF_INFO) { cpp_dev->stream_cnt++; @@ -1708,7 +1747,7 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, CPP_DBG("VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO\n"); if ((ioctl_ptr->len == 0) || - (ioctl_ptr->len > sizeof(uint32_t))) + (ioctl_ptr->len > sizeof(uint32_t))) return -EINVAL; rc = (copy_from_user(&identity, @@ -1735,11 +1774,14 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, buff_queue_info->stream_id); if (cpp_dev->stream_cnt > 0) { cpp_dev->stream_cnt--; - pr_err("stream_cnt:%d\n", cpp_dev->stream_cnt); + pr_info("stream_cnt:%d\n", cpp_dev->stream_cnt); if (cpp_dev->stream_cnt == 0) { rc = msm_isp_update_bandwidth(ISP_CPP, 0, 0); if (rc < 0) pr_err("Bandwidth Reset Failed!\n"); + cpp_dev->state = CPP_STATE_IDLE; + msm_cpp_clear_timer(cpp_dev); + msm_cpp_clean_queue(cpp_dev); } } else { pr_err("error: stream count underflow %d\n", @@ -1827,6 +1869,12 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, case MSM_SD_SHUTDOWN: CPP_DBG("MSM_SD_SHUTDOWN\n"); mutex_unlock(&cpp_dev->mutex); + pr_info("shutdown cpp node. open cnt:%d\n", + cpp_dev->cpp_open_cnt); + + if (atomic_read(&cpp_timer.used)) + pr_info("Timer state not cleared\n"); + while (cpp_dev->cpp_open_cnt != 0) cpp_close_node(sd, NULL); mutex_lock(&cpp_dev->mutex); diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h index e306335a826d..308552840060 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h @@ -198,6 +198,7 @@ struct cpp_device { struct msm_cpp_work_t *work; uint32_t fw_version; uint8_t stream_cnt; + uint8_t timeout_trial_cnt; int domain_num; struct iommu_domain *domain; |