summaryrefslogtreecommitdiff
path: root/drivers/media/platform/msm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/msm')
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c74
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h1
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;