From 2c477301dfd7c708f5e180e3485d901a3ba8b55a Mon Sep 17 00:00:00 2001 From: Shubhraprakash Das Date: Mon, 7 Mar 2016 12:36:57 -0800 Subject: [PATCH] msm: camera: isp: Implement new ioctl Implement a new ioctl that sets the ahb clock vote. This can be used from user space to make register programming quicker. CRs-Fixed: 1001335 Change-Id: I1bc0253ada50040d55b57f0ed07ba66b5535106a Signed-off-by: Shubhraprakash Das --- .../msm/camera_v2/common/cam_hw_ops.h | 2 +- .../platform/msm/camera_v2/isp/msm_isp.h | 4 ++ .../platform/msm/camera_v2/isp/msm_isp32.c | 1 + .../platform/msm/camera_v2/isp/msm_isp40.c | 1 + .../platform/msm/camera_v2/isp/msm_isp44.c | 1 + .../platform/msm/camera_v2/isp/msm_isp46.c | 1 + .../platform/msm/camera_v2/isp/msm_isp47.c | 41 +++++++++++++++++++ .../platform/msm/camera_v2/isp/msm_isp_util.c | 10 ++++- include/uapi/media/msmb_isp.h | 15 +++++++ 9 files changed, 74 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.h b/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.h index 97aadc8446c7..42a99c411d1b 100644 --- a/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.h +++ b/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.h @@ -39,4 +39,4 @@ enum cam_ahb_clk_client { int cam_config_ahb_clk(struct device *dev, unsigned long freq, enum cam_ahb_clk_client id, enum cam_ahb_clk_vote vote); int cam_ahb_clk_init(struct platform_device *pdev); -#endif /* _CAM_HW_OPS_H_ */ +#endif 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 e0e768d39612..95465fb24feb 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -28,6 +28,7 @@ #include #include "msm_buf_mgr.h" +#include "cam_hw_ops.h" #define VFE40_8974V1_VERSION 0x10000018 #define VFE40_8974V2_VERSION 0x1001001A @@ -239,6 +240,8 @@ struct msm_vfe_core_ops { void (*get_rdi_wm_mask)(struct vfe_device *vfe_dev, uint32_t *rdi_wm_mask); bool (*is_module_cfg_lock_needed)(uint32_t reg_offset); + int (*ahb_clk_cfg)(struct vfe_device *vfe_dev, + struct msm_isp_ahb_clk_cfg *ahb_cfg); }; struct msm_vfe_stats_ops { int (*get_stats_idx)(enum msm_isp_stats_type stats_type); @@ -703,6 +706,7 @@ struct vfe_device { uint32_t **vfe_clk_rates; size_t num_clk; size_t num_rates; + enum cam_ahb_clk_vote ahb_vote; /* Sync variables*/ struct completion reset_complete; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c index b336bdf9b7d8..9481bede6417 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c @@ -1514,6 +1514,7 @@ struct msm_vfe_hardware_info vfe32_hw_info = { .get_overflow_mask = msm_vfe32_get_overflow_mask, .is_module_cfg_lock_needed = msm_vfe32_is_module_cfg_lock_needed, + .ahb_clk_cfg = NULL, }, .stats_ops = { .get_stats_idx = msm_vfe32_get_stats_idx, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index fdd08da436d4..d4f0453d72ff 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -2256,6 +2256,7 @@ struct msm_vfe_hardware_info vfe40_hw_info = { .process_error_status = msm_vfe40_process_error_status, .is_module_cfg_lock_needed = msm_vfe40_is_module_cfg_lock_needed, + .ahb_clk_cfg = NULL, }, .stats_ops = { .get_stats_idx = msm_vfe40_get_stats_idx, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c index c927dcaee449..08b20395813c 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c @@ -1906,6 +1906,7 @@ struct msm_vfe_hardware_info vfe44_hw_info = { .process_error_status = msm_vfe44_process_error_status, .is_module_cfg_lock_needed = msm_vfe44_is_module_cfg_lock_needed, + .ahb_clk_cfg = NULL, }, .stats_ops = { .get_stats_idx = msm_vfe44_get_stats_idx, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c index b8e1838d0a7e..9f815e65edc8 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c @@ -2001,6 +2001,7 @@ struct msm_vfe_hardware_info vfe46_hw_info = { .process_error_status = msm_vfe46_process_error_status, .is_module_cfg_lock_needed = msm_vfe46_is_module_cfg_lock_needed, + .ahb_clk_cfg = NULL, }, .stats_ops = { .get_stats_idx = msm_vfe46_get_stats_idx, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index 3a1adbadbb80..20aa69f322db 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -238,6 +238,43 @@ static int32_t msm_vfe47_init_dt_parms(struct vfe_device *vfe_dev, return 0; } +static enum cam_ahb_clk_vote msm_isp47_get_cam_clk_vote( + enum msm_vfe_ahb_clk_vote vote) +{ + switch (vote) { + case MSM_ISP_CAMERA_AHB_SVS_VOTE: + return CAM_AHB_SVS_VOTE; + case MSM_ISP_CAMERA_AHB_TURBO_VOTE: + return CAM_AHB_TURBO_VOTE; + case MSM_ISP_CAMERA_AHB_NOMINAL_VOTE: + return CAM_AHB_NOMINAL_VOTE; + case MSM_ISP_CAMERA_AHB_SUSPEND_VOTE: + return CAM_AHB_SUSPEND_VOTE; + } + return 0; +} + +static int msm_isp47_ahb_clk_cfg(struct vfe_device *vfe_dev, + struct msm_isp_ahb_clk_cfg *ahb_cfg) +{ + int rc = 0; + enum cam_ahb_clk_vote vote; + + vote = msm_isp47_get_cam_clk_vote(ahb_cfg->vote); + + if (vote && vfe_dev->ahb_vote != vote) { + rc = cam_config_ahb_clk(NULL, 0, + (vfe_dev->pdev->id == ISP_VFE0 ? + CAM_AHB_CLIENT_VFE0 : CAM_AHB_CLIENT_VFE1), vote); + if (rc) + pr_err("%s: failed to set ahb vote to %x\n", + __func__, vote); + else + vfe_dev->ahb_vote = vote; + } + return rc; +} + int msm_vfe47_init_hardware(struct vfe_device *vfe_dev) { int rc = -1; @@ -253,6 +290,7 @@ int msm_vfe47_init_hardware(struct vfe_device *vfe_dev) pr_err("%s: failed to vote for AHB\n", __func__); goto ahb_vote_fail; } + vfe_dev->ahb_vote = CAM_AHB_SVS_VOTE; rc = vfe_dev->hw_info->vfe_ops.platform_ops.enable_regulators( vfe_dev, 1); @@ -280,6 +318,7 @@ clk_enable_failed: enable_regulators_failed: if (cam_config_ahb_clk(NULL, 0, id, CAM_AHB_SUSPEND_VOTE) < 0) pr_err("%s: failed to remove vote for AHB\n", __func__); + vfe_dev->ahb_vote = CAM_AHB_SUSPEND_VOTE; ahb_vote_fail: return rc; } @@ -312,6 +351,7 @@ void msm_vfe47_release_hardware(struct vfe_device *vfe_dev) if (cam_config_ahb_clk(NULL, 0, id, CAM_AHB_SUSPEND_VOTE) < 0) pr_err("%s: failed to vote for AHB\n", __func__); + vfe_dev->ahb_vote = CAM_AHB_SUSPEND_VOTE; } void msm_vfe47_init_hardware_reg(struct vfe_device *vfe_dev) @@ -2637,6 +2677,7 @@ struct msm_vfe_hardware_info vfe47_hw_info = { .process_error_status = msm_vfe47_process_error_status, .is_module_cfg_lock_needed = msm_vfe47_is_module_cfg_lock_needed, + .ahb_clk_cfg = msm_isp47_ahb_clk_cfg, }, .stats_ops = { .get_stats_idx = msm_vfe47_get_stats_idx, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 286ecaca129c..83c5a7d43cac 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -701,7 +701,6 @@ static int msm_isp_proc_cmd_list(struct vfe_device *vfe_dev, void *arg) } #endif /* CONFIG_COMPAT */ - static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -814,6 +813,15 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, rc = msm_isp_cfg_input(vfe_dev, arg); mutex_unlock(&vfe_dev->core_mutex); break; + case VIDIOC_MSM_ISP_AHB_CLK_CFG: + mutex_lock(&vfe_dev->core_mutex); + if (vfe_dev->hw_info->vfe_ops.core_ops.ahb_clk_cfg) + rc = vfe_dev->hw_info->vfe_ops.core_ops. + ahb_clk_cfg(vfe_dev, arg); + else + rc = -EOPNOTSUPP; + mutex_unlock(&vfe_dev->core_mutex); + break; case VIDIOC_MSM_ISP_SET_DUAL_HW_MASTER_SLAVE: mutex_lock(&vfe_dev->core_mutex); rc = msm_isp_set_dual_HW_master_slave_mode(vfe_dev, arg); diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h index 96d43b6ce342..7f7ebd3ba21f 100644 --- a/include/uapi/media/msmb_isp.h +++ b/include/uapi/media/msmb_isp.h @@ -756,6 +756,18 @@ struct msm_isp_event_data { } u; /* union can have max 52 bytes */ }; +enum msm_vfe_ahb_clk_vote { + MSM_ISP_CAMERA_AHB_SVS_VOTE = 1, + MSM_ISP_CAMERA_AHB_TURBO_VOTE = 2, + MSM_ISP_CAMERA_AHB_NOMINAL_VOTE = 3, + MSM_ISP_CAMERA_AHB_SUSPEND_VOTE = 4, +}; + +struct msm_isp_ahb_clk_cfg { + uint32_t vote; + uint32_t reserved[2]; +}; + #define V4L2_PIX_FMT_QBGGR8 v4l2_fourcc('Q', 'B', 'G', '8') #define V4L2_PIX_FMT_QGBRG8 v4l2_fourcc('Q', 'G', 'B', '8') #define V4L2_PIX_FMT_QGRBG8 v4l2_fourcc('Q', 'G', 'R', '8') @@ -861,4 +873,7 @@ struct msm_isp_event_data { #define VIDIOC_MSM_ISP_UNMAP_BUF \ _IOWR('V', BASE_VIDIOC_PRIVATE+24, struct msm_isp_unmap_buf_req) +#define VIDIOC_MSM_ISP_AHB_CLK_CFG \ + _IOWR('V', BASE_VIDIOC_PRIVATE+25, struct msm_isp_ahb_clk_cfg) + #endif /* __MSMB_ISP__ */