Loading drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c +34 −4 Original line number Diff line number Diff line Loading @@ -903,9 +903,11 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, goto done; if (cpas_core->streamon_clients == 0) { atomic_set(&cpas_core->irq_count, 1); rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info, applied_level); if (rc) { atomic_set(&cpas_core->irq_count, 0); CAM_ERR(CAM_CPAS, "enable_resorce failed, rc=%d", rc); goto done; } Loading @@ -913,14 +915,17 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, if (cpas_core->internal_ops.power_on) { rc = cpas_core->internal_ops.power_on(cpas_hw); if (rc) { atomic_set(&cpas_core->irq_count, 0); cam_cpas_soc_disable_resources( &cpas_hw->soc_info); &cpas_hw->soc_info, true, true); CAM_ERR(CAM_CPAS, "failed in power_on settings rc=%d", rc); goto done; } } CAM_DBG(CAM_CPAS, "irq_count=%d\n", atomic_read(&cpas_core->irq_count)); cpas_hw->hw_state = CAM_HW_STATE_POWER_UP; } Loading @@ -935,6 +940,10 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, return rc; } static int _check_irq_count(struct cam_cpas *cpas_core) { return (atomic_read(&cpas_core->irq_count) > 0) ? 0 : 1; } static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, uint32_t arg_size) Loading @@ -947,6 +956,7 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, struct cam_ahb_vote ahb_vote; struct cam_axi_vote axi_vote; int rc = 0; long result; if (!hw_priv || !stop_args) { CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK", Loading Loading @@ -995,11 +1005,29 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, } } rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info); rc = cam_cpas_soc_disable_irq(&cpas_hw->soc_info); if (rc) { CAM_ERR(CAM_CPAS, "disable_irq failed, rc=%d", rc); goto done; } /* Wait for any IRQs still being handled */ atomic_dec(&cpas_core->irq_count); result = wait_event_timeout(cpas_core->irq_count_wq, _check_irq_count(cpas_core), HZ); if (result == 0) { CAM_ERR(CAM_CPAS, "Wait failed: irq_count=%d", atomic_read(&cpas_core->irq_count)); } rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, false); if (rc) { CAM_ERR(CAM_CPAS, "disable_resorce failed, rc=%d", rc); goto done; } CAM_DBG(CAM_CPAS, "Disabled all the resources: irq_count=%d\n", atomic_read(&cpas_core->irq_count)); cpas_hw->hw_state = CAM_HW_STATE_POWER_DOWN; } Loading Loading @@ -1450,6 +1478,8 @@ int cam_cpas_hw_probe(struct platform_device *pdev, soc_private = (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; cpas_core->num_clients = soc_private->num_clients; atomic_set(&cpas_core->irq_count, 0); init_waitqueue_head(&cpas_core->irq_count_wq); if (internal_ops->setup_regbase) { rc = internal_ops->setup_regbase(&cpas_hw->soc_info, Loading Loading @@ -1505,7 +1535,7 @@ int cam_cpas_hw_probe(struct platform_device *pdev, if (rc) goto disable_soc_res; rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info); rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true); if (rc) { CAM_ERR(CAM_CPAS, "failed in soc_disable_resources, rc=%d", rc); goto remove_default_vote; Loading @@ -1523,7 +1553,7 @@ int cam_cpas_hw_probe(struct platform_device *pdev, return 0; disable_soc_res: cam_cpas_soc_disable_resources(&cpas_hw->soc_info); cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true); remove_default_vote: cam_cpas_util_vote_default_ahb_axi(cpas_hw, false); axi_cleanup: Loading drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 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 Loading @@ -187,6 +187,8 @@ struct cam_cpas { struct list_head axi_ports_list_head; struct cam_cpas_internal_ops internal_ops; struct workqueue_struct *work_queue; atomic_t irq_count; wait_queue_head_t irq_count_wq; }; int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); Loading drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c +16 −3 Original line number Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 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 Loading @@ -209,13 +209,26 @@ int cam_cpas_soc_enable_resources(struct cam_hw_soc_info *soc_info, return rc; } int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info) int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info, bool disable_clocks, bool disble_irq) { int rc = 0; rc = cam_soc_util_disable_platform_resource(soc_info, true, true); rc = cam_soc_util_disable_platform_resource(soc_info, disable_clocks, disble_irq); if (rc) CAM_ERR(CAM_CPAS, "disable platform failed, rc=%d", rc); return rc; } int cam_cpas_soc_disable_irq(struct cam_hw_soc_info *soc_info) { int rc = 0; rc = cam_soc_util_irq_disable(soc_info); if (rc) CAM_ERR(CAM_CPAS, "disable irq failed, rc=%d", rc); return rc; } drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h +4 −2 Original line number Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 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 Loading @@ -61,5 +61,7 @@ int cam_cpas_soc_init_resources(struct cam_hw_soc_info *soc_info, int cam_cpas_soc_deinit_resources(struct cam_hw_soc_info *soc_info); int cam_cpas_soc_enable_resources(struct cam_hw_soc_info *soc_info, enum cam_vote_level default_level); int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info); int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info, bool disable_clocks, bool disble_irq); int cam_cpas_soc_disable_irq(struct cam_hw_soc_info *soc_info); #endif /* _CAM_CPAS_SOC_H_ */ drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c +18 −2 Original line number Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 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 Loading @@ -354,6 +354,11 @@ static void cam_cpastop_work(struct work_struct *work) cpas_core = (struct cam_cpas *) cpas_hw->core_info; soc_info = &cpas_hw->soc_info; if (!atomic_inc_not_zero(&cpas_core->irq_count)) { CAM_ERR(CAM_CPAS, "CPAS off"); return; } for (i = 0; i < camnoc_info->irq_err_size; i++) { if ((payload->irq_status & camnoc_info->irq_err[i].sbm_port) && (camnoc_info->irq_err[i].enable)) { Loading Loading @@ -398,6 +403,9 @@ static void cam_cpastop_work(struct work_struct *work) ~camnoc_info->irq_err[i].sbm_port; } } atomic_dec(&cpas_core->irq_count); wake_up(&cpas_core->irq_count_wq); CAM_DBG(CAM_CPAS, "irq_count=%d\n", atomic_read(&cpas_core->irq_count)); if (payload->irq_status) CAM_ERR(CAM_CPAS, "IRQ not handled irq_status=0x%x", Loading @@ -414,9 +422,14 @@ static irqreturn_t cam_cpastop_handle_irq(int irq_num, void *data) int camnoc_index = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC]; struct cam_cpas_work_payload *payload; if (!atomic_inc_not_zero(&cpas_core->irq_count)) { CAM_ERR(CAM_CPAS, "CPAS off"); return IRQ_HANDLED; } payload = kzalloc(sizeof(struct cam_cpas_work_payload), GFP_ATOMIC); if (!payload) return IRQ_HANDLED; goto done; payload->irq_status = cam_io_r_mb( soc_info->reg_map[camnoc_index].mem_base + Loading @@ -433,6 +446,9 @@ static irqreturn_t cam_cpastop_handle_irq(int irq_num, void *data) cam_cpastop_reset_irq(cpas_hw); queue_work(cpas_core->work_queue, &payload->work); done: atomic_dec(&cpas_core->irq_count); wake_up(&cpas_core->irq_count_wq); return IRQ_HANDLED; } Loading Loading
drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c +34 −4 Original line number Diff line number Diff line Loading @@ -903,9 +903,11 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, goto done; if (cpas_core->streamon_clients == 0) { atomic_set(&cpas_core->irq_count, 1); rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info, applied_level); if (rc) { atomic_set(&cpas_core->irq_count, 0); CAM_ERR(CAM_CPAS, "enable_resorce failed, rc=%d", rc); goto done; } Loading @@ -913,14 +915,17 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, if (cpas_core->internal_ops.power_on) { rc = cpas_core->internal_ops.power_on(cpas_hw); if (rc) { atomic_set(&cpas_core->irq_count, 0); cam_cpas_soc_disable_resources( &cpas_hw->soc_info); &cpas_hw->soc_info, true, true); CAM_ERR(CAM_CPAS, "failed in power_on settings rc=%d", rc); goto done; } } CAM_DBG(CAM_CPAS, "irq_count=%d\n", atomic_read(&cpas_core->irq_count)); cpas_hw->hw_state = CAM_HW_STATE_POWER_UP; } Loading @@ -935,6 +940,10 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, return rc; } static int _check_irq_count(struct cam_cpas *cpas_core) { return (atomic_read(&cpas_core->irq_count) > 0) ? 0 : 1; } static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, uint32_t arg_size) Loading @@ -947,6 +956,7 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, struct cam_ahb_vote ahb_vote; struct cam_axi_vote axi_vote; int rc = 0; long result; if (!hw_priv || !stop_args) { CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK", Loading Loading @@ -995,11 +1005,29 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, } } rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info); rc = cam_cpas_soc_disable_irq(&cpas_hw->soc_info); if (rc) { CAM_ERR(CAM_CPAS, "disable_irq failed, rc=%d", rc); goto done; } /* Wait for any IRQs still being handled */ atomic_dec(&cpas_core->irq_count); result = wait_event_timeout(cpas_core->irq_count_wq, _check_irq_count(cpas_core), HZ); if (result == 0) { CAM_ERR(CAM_CPAS, "Wait failed: irq_count=%d", atomic_read(&cpas_core->irq_count)); } rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, false); if (rc) { CAM_ERR(CAM_CPAS, "disable_resorce failed, rc=%d", rc); goto done; } CAM_DBG(CAM_CPAS, "Disabled all the resources: irq_count=%d\n", atomic_read(&cpas_core->irq_count)); cpas_hw->hw_state = CAM_HW_STATE_POWER_DOWN; } Loading Loading @@ -1450,6 +1478,8 @@ int cam_cpas_hw_probe(struct platform_device *pdev, soc_private = (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; cpas_core->num_clients = soc_private->num_clients; atomic_set(&cpas_core->irq_count, 0); init_waitqueue_head(&cpas_core->irq_count_wq); if (internal_ops->setup_regbase) { rc = internal_ops->setup_regbase(&cpas_hw->soc_info, Loading Loading @@ -1505,7 +1535,7 @@ int cam_cpas_hw_probe(struct platform_device *pdev, if (rc) goto disable_soc_res; rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info); rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true); if (rc) { CAM_ERR(CAM_CPAS, "failed in soc_disable_resources, rc=%d", rc); goto remove_default_vote; Loading @@ -1523,7 +1553,7 @@ int cam_cpas_hw_probe(struct platform_device *pdev, return 0; disable_soc_res: cam_cpas_soc_disable_resources(&cpas_hw->soc_info); cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true); remove_default_vote: cam_cpas_util_vote_default_ahb_axi(cpas_hw, false); axi_cleanup: Loading
drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 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 Loading @@ -187,6 +187,8 @@ struct cam_cpas { struct list_head axi_ports_list_head; struct cam_cpas_internal_ops internal_ops; struct workqueue_struct *work_queue; atomic_t irq_count; wait_queue_head_t irq_count_wq; }; int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); Loading
drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c +16 −3 Original line number Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 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 Loading @@ -209,13 +209,26 @@ int cam_cpas_soc_enable_resources(struct cam_hw_soc_info *soc_info, return rc; } int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info) int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info, bool disable_clocks, bool disble_irq) { int rc = 0; rc = cam_soc_util_disable_platform_resource(soc_info, true, true); rc = cam_soc_util_disable_platform_resource(soc_info, disable_clocks, disble_irq); if (rc) CAM_ERR(CAM_CPAS, "disable platform failed, rc=%d", rc); return rc; } int cam_cpas_soc_disable_irq(struct cam_hw_soc_info *soc_info) { int rc = 0; rc = cam_soc_util_irq_disable(soc_info); if (rc) CAM_ERR(CAM_CPAS, "disable irq failed, rc=%d", rc); return rc; }
drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h +4 −2 Original line number Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 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 Loading @@ -61,5 +61,7 @@ int cam_cpas_soc_init_resources(struct cam_hw_soc_info *soc_info, int cam_cpas_soc_deinit_resources(struct cam_hw_soc_info *soc_info); int cam_cpas_soc_enable_resources(struct cam_hw_soc_info *soc_info, enum cam_vote_level default_level); int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info); int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info, bool disable_clocks, bool disble_irq); int cam_cpas_soc_disable_irq(struct cam_hw_soc_info *soc_info); #endif /* _CAM_CPAS_SOC_H_ */
drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c +18 −2 Original line number Diff line number Diff line /* Copyright (c) 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2018, 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 Loading @@ -354,6 +354,11 @@ static void cam_cpastop_work(struct work_struct *work) cpas_core = (struct cam_cpas *) cpas_hw->core_info; soc_info = &cpas_hw->soc_info; if (!atomic_inc_not_zero(&cpas_core->irq_count)) { CAM_ERR(CAM_CPAS, "CPAS off"); return; } for (i = 0; i < camnoc_info->irq_err_size; i++) { if ((payload->irq_status & camnoc_info->irq_err[i].sbm_port) && (camnoc_info->irq_err[i].enable)) { Loading Loading @@ -398,6 +403,9 @@ static void cam_cpastop_work(struct work_struct *work) ~camnoc_info->irq_err[i].sbm_port; } } atomic_dec(&cpas_core->irq_count); wake_up(&cpas_core->irq_count_wq); CAM_DBG(CAM_CPAS, "irq_count=%d\n", atomic_read(&cpas_core->irq_count)); if (payload->irq_status) CAM_ERR(CAM_CPAS, "IRQ not handled irq_status=0x%x", Loading @@ -414,9 +422,14 @@ static irqreturn_t cam_cpastop_handle_irq(int irq_num, void *data) int camnoc_index = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC]; struct cam_cpas_work_payload *payload; if (!atomic_inc_not_zero(&cpas_core->irq_count)) { CAM_ERR(CAM_CPAS, "CPAS off"); return IRQ_HANDLED; } payload = kzalloc(sizeof(struct cam_cpas_work_payload), GFP_ATOMIC); if (!payload) return IRQ_HANDLED; goto done; payload->irq_status = cam_io_r_mb( soc_info->reg_map[camnoc_index].mem_base + Loading @@ -433,6 +446,9 @@ static irqreturn_t cam_cpastop_handle_irq(int irq_num, void *data) cam_cpastop_reset_irq(cpas_hw); queue_work(cpas_core->work_queue, &payload->work); done: atomic_dec(&cpas_core->irq_count); wake_up(&cpas_core->irq_count_wq); return IRQ_HANDLED; } Loading