summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c58
1 files changed, 54 insertions, 4 deletions
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 6339555bdf76..83abaea1fa44 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
@@ -1461,8 +1461,9 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
VBIF_CLIENT_CPP, cpp_vbif_error_handler);
if (cpp_dev->cpp_open_cnt == 1) {
- rc = cpp_init_hardware(cpp_dev);
+ rc = cpp_init_mem(cpp_dev);
if (rc < 0) {
+ pr_err("Error: init memory fail\n");
cpp_dev->cpp_open_cnt--;
cpp_dev->cpp_subscribe_list[i].active = 0;
cpp_dev->cpp_subscribe_list[i].vfh = NULL;
@@ -1470,16 +1471,14 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
return rc;
}
- rc = cpp_init_mem(cpp_dev);
+ rc = cpp_init_hardware(cpp_dev);
if (rc < 0) {
- pr_err("Error: init memory fail\n");
cpp_dev->cpp_open_cnt--;
cpp_dev->cpp_subscribe_list[i].active = 0;
cpp_dev->cpp_subscribe_list[i].vfh = NULL;
mutex_unlock(&cpp_dev->mutex);
return rc;
}
-
cpp_dev->state = CPP_STATE_IDLE;
CPP_DBG("Invoking msm_ion_client_create()\n");
@@ -1499,6 +1498,8 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
uint32_t i;
int rc = -1;
+ int counter = 0;
+ u32 result = 0;
struct cpp_device *cpp_dev = NULL;
struct msm_device_queue *processing_q = NULL;
struct msm_device_queue *eventData_q = NULL;
@@ -1579,6 +1580,55 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
msm_camera_io_r(cpp_dev->cpp_hw_base + 0x88));
pr_debug("DEBUG_R1: 0x%x\n",
msm_camera_io_r(cpp_dev->cpp_hw_base + 0x8C));
+
+ /* mask IRQ status */
+ msm_camera_io_w(0xB, cpp_dev->cpp_hw_base + 0xC);
+
+ /* clear IRQ status */
+ msm_camera_io_w(0xFFFFF, cpp_dev->cpp_hw_base + 0x14);
+
+ /* MMSS_A_CPP_AXI_CMD = 0x16C, reset 0x1*/
+ msm_camera_io_w(0x1, cpp_dev->cpp_hw_base + 0x16C);
+
+ while (counter < MSM_CPP_POLL_RETRIES) {
+ result = msm_camera_io_r(cpp_dev->cpp_hw_base + 0x10);
+ if (result & 0x2)
+ break;
+ /*
+ * Below usleep values are chosen based on experiments
+ * and this was the smallest number which works. This
+ * sleep is needed to leave enough time for hardware
+ * to update status register.
+ */
+ usleep_range(200, 250);
+ counter++;
+ }
+
+ pr_debug("CPP AXI done counter %d result 0x%x\n",
+ counter, result);
+
+ /* clear IRQ status */
+ msm_camera_io_w(0xFFFFF, cpp_dev->cpp_hw_base + 0x14);
+ counter = 0;
+ /* MMSS_A_CPP_RST_CMD_0 = 0x8, firmware reset = 0x3DF77 */
+ msm_camera_io_w(0x3DF77, cpp_dev->cpp_hw_base + 0x8);
+
+ while (counter < MSM_CPP_POLL_RETRIES) {
+ result = msm_camera_io_r(cpp_dev->cpp_hw_base + 0x10);
+ if (result & 0x1)
+ break;
+ /*
+ * Below usleep values are chosen based on experiments
+ * and this was the smallest number which works. This
+ * sleep is needed to leave enough time for hardware
+ * to update status register.
+ */
+ usleep_range(200, 250);
+ counter++;
+ }
+ pr_debug("CPP reset done counter %d result 0x%x\n",
+ counter, result);
+
msm_camera_io_w(0x0, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL);
msm_cpp_clear_timer(cpp_dev);
cpp_release_hardware(cpp_dev);