Loading Documentation/devicetree/bindings/media/video/msm-cpp.txt +8 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,13 @@ Optional properties: The first entry is register offset and second entry is register value. - qcom,micro-reset: Boolean flag indicating if micro reset need to be enabled. This needs to present on platforms that support this feature. - qcom,cpp-cx-ipeak: To handle Cx peak current limit. <phandle bit> phandle - phandle of cx ipeak device node bit - bit number of client in relevant register This is used to access Cx ipeak HW module to limit the current drawn by various subsystem blocks on Cx power rail. CPP set their bit in tcsr register if it is going to cross its own threshold. Example: Loading Loading @@ -105,6 +112,7 @@ Example: "micro_iface_clk", "camss_ahb_clk"; "smmu_cpp_axi_clk", "cpp_vbif_ahb_clk"; qcom,clock-rates = <0 0 0 0 465000000 0 0 465000000 0 0 0 0>; qcom,cpp-cx-ipeak = <&cx_ipeak_lm 2>; qcom,min-clock-rate = <320000000>; qcom,bus-master = <1>; qcom,vbif-qos-setting = <0x20 0x10000000>, Loading drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +59 −3 Original line number Diff line number Diff line Loading @@ -980,6 +980,7 @@ static int cpp_init_hardware(struct cpp_device *cpp_dev) { int rc = 0; uint32_t vbif_version; cpp_dev->turbo_vote = 0; rc = msm_camera_regulator_enable(cpp_dev->cpp_vdd, cpp_dev->num_reg, true); Loading Loading @@ -1432,6 +1433,14 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return -ENODEV; } if (cpp_dev->turbo_vote == 1) { rc = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, false); if (rc) pr_err("cx_ipeak_update failed"); else cpp_dev->turbo_vote = 0; } cpp_dev->cpp_open_cnt--; if (cpp_dev->cpp_open_cnt == 0) { pr_debug("irq_status: 0x%x\n", Loading Loading @@ -2955,6 +2964,38 @@ static int msm_cpp_validate_input(unsigned int cmd, void *arg, return 0; } unsigned long cpp_cx_ipeak_update(struct cpp_device *cpp_dev, unsigned long clock, int idx) { unsigned long clock_rate = 0; int ret = 0; if ((clock >= cpp_dev->hw_info.freq_tbl [(cpp_dev->hw_info.freq_tbl_count) - 1]) && (cpp_dev->turbo_vote == 0)) { ret = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, true); if (ret) { pr_err("cx_ipeak voting failed setting clock below turbo"); clock = cpp_dev->hw_info.freq_tbl [(cpp_dev->hw_info.freq_tbl_count) - 2]; } else { cpp_dev->turbo_vote = 1; } clock_rate = msm_cpp_set_core_clk(cpp_dev, clock, idx); } else if (clock < cpp_dev->hw_info.freq_tbl [(cpp_dev->hw_info.freq_tbl_count) - 1]) { clock_rate = msm_cpp_set_core_clk(cpp_dev, clock, idx); if (cpp_dev->turbo_vote == 1) { ret = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, false); if (ret) pr_err("cx_ipeak unvoting failed"); else cpp_dev->turbo_vote = 0; } } return clock_rate; } long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { Loading Loading @@ -3337,9 +3378,15 @@ STREAM_BUFF_END: mutex_unlock(&cpp_dev->mutex); return -EINVAL; } if (cpp_dev->cpp_cx_ipeak) { clock_rate = cpp_cx_ipeak_update(cpp_dev, clock_settings.clock_rate, msm_cpp_core_clk_idx); } else { clock_rate = msm_cpp_set_core_clk(cpp_dev, clock_settings.clock_rate, msm_cpp_core_clk_idx); } if (rc < 0) { pr_err("Fail to set core clk\n"); mutex_unlock(&cpp_dev->mutex); Loading Loading @@ -4391,6 +4438,15 @@ static int cpp_probe(struct platform_device *pdev) } } if (of_find_property(pdev->dev.of_node, "qcom,cpp-cx-ipeak", NULL)) { cpp_dev->cpp_cx_ipeak = cx_ipeak_register( pdev->dev.of_node, "qcom,cpp-cx-ipeak"); if (cpp_dev->cpp_cx_ipeak) CPP_DBG("Cx ipeak Registration Successful "); else pr_err("Cx ipeak Registration Unsuccessful"); } rc = msm_camera_get_reset_info(pdev, &cpp_dev->micro_iface_reset); if (rc < 0) { Loading drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h +4 −1 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -24,6 +24,7 @@ #include "cam_soc_api.h" #include "cam_hw_ops.h" #include <media/msmb_pproc.h> #include <soc/qcom/cx_ipeak.h> /* hw version info: 31:28 Major version Loading Loading @@ -284,6 +285,8 @@ struct cpp_device { uint32_t micro_reset; struct msm_cpp_payload_params payload_params; struct msm_cpp_vbif_data *vbif_data; bool turbo_vote; struct cx_ipeak_client *cpp_cx_ipeak; }; int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev); Loading Loading
Documentation/devicetree/bindings/media/video/msm-cpp.txt +8 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,13 @@ Optional properties: The first entry is register offset and second entry is register value. - qcom,micro-reset: Boolean flag indicating if micro reset need to be enabled. This needs to present on platforms that support this feature. - qcom,cpp-cx-ipeak: To handle Cx peak current limit. <phandle bit> phandle - phandle of cx ipeak device node bit - bit number of client in relevant register This is used to access Cx ipeak HW module to limit the current drawn by various subsystem blocks on Cx power rail. CPP set their bit in tcsr register if it is going to cross its own threshold. Example: Loading Loading @@ -105,6 +112,7 @@ Example: "micro_iface_clk", "camss_ahb_clk"; "smmu_cpp_axi_clk", "cpp_vbif_ahb_clk"; qcom,clock-rates = <0 0 0 0 465000000 0 0 465000000 0 0 0 0>; qcom,cpp-cx-ipeak = <&cx_ipeak_lm 2>; qcom,min-clock-rate = <320000000>; qcom,bus-master = <1>; qcom,vbif-qos-setting = <0x20 0x10000000>, Loading
drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +59 −3 Original line number Diff line number Diff line Loading @@ -980,6 +980,7 @@ static int cpp_init_hardware(struct cpp_device *cpp_dev) { int rc = 0; uint32_t vbif_version; cpp_dev->turbo_vote = 0; rc = msm_camera_regulator_enable(cpp_dev->cpp_vdd, cpp_dev->num_reg, true); Loading Loading @@ -1432,6 +1433,14 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return -ENODEV; } if (cpp_dev->turbo_vote == 1) { rc = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, false); if (rc) pr_err("cx_ipeak_update failed"); else cpp_dev->turbo_vote = 0; } cpp_dev->cpp_open_cnt--; if (cpp_dev->cpp_open_cnt == 0) { pr_debug("irq_status: 0x%x\n", Loading Loading @@ -2955,6 +2964,38 @@ static int msm_cpp_validate_input(unsigned int cmd, void *arg, return 0; } unsigned long cpp_cx_ipeak_update(struct cpp_device *cpp_dev, unsigned long clock, int idx) { unsigned long clock_rate = 0; int ret = 0; if ((clock >= cpp_dev->hw_info.freq_tbl [(cpp_dev->hw_info.freq_tbl_count) - 1]) && (cpp_dev->turbo_vote == 0)) { ret = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, true); if (ret) { pr_err("cx_ipeak voting failed setting clock below turbo"); clock = cpp_dev->hw_info.freq_tbl [(cpp_dev->hw_info.freq_tbl_count) - 2]; } else { cpp_dev->turbo_vote = 1; } clock_rate = msm_cpp_set_core_clk(cpp_dev, clock, idx); } else if (clock < cpp_dev->hw_info.freq_tbl [(cpp_dev->hw_info.freq_tbl_count) - 1]) { clock_rate = msm_cpp_set_core_clk(cpp_dev, clock, idx); if (cpp_dev->turbo_vote == 1) { ret = cx_ipeak_update(cpp_dev->cpp_cx_ipeak, false); if (ret) pr_err("cx_ipeak unvoting failed"); else cpp_dev->turbo_vote = 0; } } return clock_rate; } long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { Loading Loading @@ -3337,9 +3378,15 @@ STREAM_BUFF_END: mutex_unlock(&cpp_dev->mutex); return -EINVAL; } if (cpp_dev->cpp_cx_ipeak) { clock_rate = cpp_cx_ipeak_update(cpp_dev, clock_settings.clock_rate, msm_cpp_core_clk_idx); } else { clock_rate = msm_cpp_set_core_clk(cpp_dev, clock_settings.clock_rate, msm_cpp_core_clk_idx); } if (rc < 0) { pr_err("Fail to set core clk\n"); mutex_unlock(&cpp_dev->mutex); Loading Loading @@ -4391,6 +4438,15 @@ static int cpp_probe(struct platform_device *pdev) } } if (of_find_property(pdev->dev.of_node, "qcom,cpp-cx-ipeak", NULL)) { cpp_dev->cpp_cx_ipeak = cx_ipeak_register( pdev->dev.of_node, "qcom,cpp-cx-ipeak"); if (cpp_dev->cpp_cx_ipeak) CPP_DBG("Cx ipeak Registration Successful "); else pr_err("Cx ipeak Registration Unsuccessful"); } rc = msm_camera_get_reset_info(pdev, &cpp_dev->micro_iface_reset); if (rc < 0) { Loading
drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h +4 −1 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -24,6 +24,7 @@ #include "cam_soc_api.h" #include "cam_hw_ops.h" #include <media/msmb_pproc.h> #include <soc/qcom/cx_ipeak.h> /* hw version info: 31:28 Major version Loading Loading @@ -284,6 +285,8 @@ struct cpp_device { uint32_t micro_reset; struct msm_cpp_payload_params payload_params; struct msm_cpp_vbif_data *vbif_data; bool turbo_vote; struct cx_ipeak_client *cpp_cx_ipeak; }; int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev); Loading