diff --git a/drivers/cam_cdm/cam_cdm.h b/drivers/cam_cdm/cam_cdm.h index 8d8c443af2..7d83cd8296 100644 --- a/drivers/cam_cdm/cam_cdm.h +++ b/drivers/cam_cdm/cam_cdm.h @@ -581,6 +581,7 @@ struct cam_cdm_intf_mgr { uint32_t dt_supported_hw_cdm; int32_t refcount; struct cam_cdm_intf_devices nodes[CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM]; + struct dentry *dentry; }; int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw, diff --git a/drivers/cam_cdm/cam_cdm_core_common.c b/drivers/cam_cdm/cam_cdm_core_common.c index 8d3e2d4f83..e998e03a96 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.c +++ b/drivers/cam_cdm/cam_cdm_core_common.c @@ -18,6 +18,38 @@ #include "cam_cdm_soc.h" #include "cam_cdm_core_common.h" +int cam_cdm_util_cpas_start(struct cam_hw_info *cdm_hw) +{ + struct cam_cdm *core = NULL; + struct cam_ahb_vote ahb_vote; + struct cam_axi_vote axi_vote = {0}; + int rc = 0; + + if (!cdm_hw) { + CAM_ERR(CAM_CDM, "Invalid cdm hw"); + return -EINVAL; + } + + core = (struct cam_cdm *)cdm_hw->core_info; + + ahb_vote.type = CAM_VOTE_ABSOLUTE; + ahb_vote.vote.level = CAM_LOWSVS_VOTE; + axi_vote.num_paths = 1; + axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; + axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; + axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; + axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; + + rc = cam_cpas_start(core->cpas_handle, &ahb_vote, &axi_vote); + if (rc) { + CAM_ERR(CAM_CDM, "CDM[%d] CPAS start failed rc=%d", core->index, rc); + return rc; + } + + return rc; +} + static void cam_cdm_get_client_refcount(struct cam_cdm_client *client) { mutex_lock(&client->lock); @@ -341,25 +373,7 @@ int cam_cdm_stream_ops_internal(void *hw_priv, if (operation == true) { if (!cdm_hw->open_count) { - struct cam_ahb_vote ahb_vote; - struct cam_axi_vote axi_vote = {0}; - - ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_LOWSVS_VOTE; - axi_vote.num_paths = 1; - axi_vote.axi_path[0].path_data_type = - CAM_AXI_PATH_DATA_ALL; - axi_vote.axi_path[0].transac_type = - CAM_AXI_TRANSACTION_READ; - axi_vote.axi_path[0].camnoc_bw = - CAM_CPAS_DEFAULT_AXI_BW; - axi_vote.axi_path[0].mnoc_ab_bw = - CAM_CPAS_DEFAULT_AXI_BW; - axi_vote.axi_path[0].mnoc_ib_bw = - CAM_CPAS_DEFAULT_AXI_BW; - - rc = cam_cpas_start(core->cpas_handle, - &ahb_vote, &axi_vote); + rc = cam_cdm_util_cpas_start(cdm_hw); if (rc != 0) { CAM_ERR(CAM_CDM, "CPAS start failed"); goto end; diff --git a/drivers/cam_cdm/cam_cdm_core_common.h b/drivers/cam_cdm/cam_cdm_core_common.h index d4875e2717..c863e2d8a1 100644 --- a/drivers/cam_cdm/cam_cdm_core_common.h +++ b/drivers/cam_cdm/cam_cdm_core_common.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CDM_CORE_COMMON_H_ @@ -58,5 +58,6 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, enum cam_cdm_cb_status status, void *data); void cam_hw_cdm_dump_core_debug_registers( struct cam_hw_info *cdm_hw, bool pause_core); +int cam_cdm_util_cpas_start(struct cam_hw_info *cdm_hw); #endif /* _CAM_CDM_CORE_COMMON_H_ */ diff --git a/drivers/cam_cdm/cam_cdm_hw_core.c b/drivers/cam_cdm/cam_cdm_hw_core.c index b369653480..e7a517d92b 100644 --- a/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/drivers/cam_cdm/cam_cdm_hw_core.c @@ -2135,6 +2135,65 @@ int cam_hw_cdm_deinit(void *hw_priv, return rc; } +#if (defined(CONFIG_CAM_TEST_IRQ_LINE) && defined(CONFIG_CAM_TEST_IRQ_LINE_AT_PROBE)) +static int cam_cdm_test_irq_line(void *hw_priv) +{ + struct cam_hw_info *cdm_hw = hw_priv; + struct cam_cdm *core = NULL; + int rc = 0; + + if (!cdm_hw) { + CAM_ERR(CAM_CDM, "Invalid cdm hw"); + return -EINVAL; + } + + core = (struct cam_cdm *)cdm_hw->core_info; + + rc = cam_cdm_util_cpas_start(cdm_hw); + if (rc) { + CAM_ERR(CAM_CDM, "CDM[%d] Failed in cpas start rc", core->index, rc); + goto done; + } + + rc = cam_hw_cdm_init(cdm_hw, NULL, 0); + if (rc) { + CAM_ERR(CAM_CDM, "CDM[%d] Failed in cdm init rc", core->index, rc); + goto cpas_stop; + } + + rc = cam_hw_cdm_deinit(cdm_hw, NULL, 0); + if (rc) { + CAM_ERR(CAM_CDM, "CDM[%d] Failed in cdm deinit rc", core->index, rc); + goto cpas_stop; + } + +cpas_stop: + rc = cam_cpas_stop(core->cpas_handle); + if (rc) + CAM_ERR(CAM_CDM, "CDM[%d] Failed in cpas stop rc", core->index, rc); +done: + return rc; +} +#else +static int cam_cdm_test_irq_line(void *hw_priv) +{ + return -EPERM; +} +#endif + + +#if (defined(CONFIG_CAM_TEST_IRQ_LINE) && defined(CONFIG_CAM_TEST_IRQ_LINE_AT_PROBE)) +static int cam_cdm_test_irq_line_at_probe(struct cam_hw_info *cdm_hw) +{ + return cam_cdm_test_irq_line(cdm_hw); +} +#else +static int cam_cdm_test_irq_line_at_probe(struct cam_hw_info *cdm_hw) +{ + return -EPERM; +} +#endif + static int cam_hw_cdm_component_bind(struct device *dev, struct device *master_dev, void *data) { @@ -2144,8 +2203,6 @@ static int cam_hw_cdm_component_bind(struct device *dev, struct cam_cdm *cdm_core = NULL; struct cam_cdm_private_dt_data *soc_private = NULL; struct cam_cpas_register_params cpas_parms; - struct cam_ahb_vote ahb_vote; - struct cam_axi_vote axi_vote = {0}; char cdm_name[128], work_q_name[128]; struct platform_device *pdev = to_platform_device(dev); @@ -2213,6 +2270,7 @@ static int cam_hw_cdm_component_bind(struct device *dev, cdm_hw_intf->hw_ops.read = NULL; cdm_hw_intf->hw_ops.write = NULL; cdm_hw_intf->hw_ops.process_cmd = cam_cdm_process_cmd; + cdm_hw_intf->hw_ops.test_irq_line = cam_cdm_test_irq_line; mutex_lock(&cdm_hw->hw_mutex); CAM_DBG(CAM_CDM, "type %d index %d", cdm_hw_intf->hw_type, @@ -2285,16 +2343,7 @@ static int cam_hw_cdm_component_bind(struct device *dev, cpas_parms.client_handle); cdm_core->cpas_handle = cpas_parms.client_handle; - ahb_vote.type = CAM_VOTE_ABSOLUTE; - ahb_vote.vote.level = CAM_LOWSVS_VOTE; - axi_vote.num_paths = 1; - axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL; - axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ; - axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW; - axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW; - axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW; - - rc = cam_cpas_start(cdm_core->cpas_handle, &ahb_vote, &axi_vote); + rc = cam_cdm_util_cpas_start(cdm_hw); if (rc) { CAM_ERR(CAM_CDM, "CPAS start failed"); goto cpas_unregister; @@ -2357,6 +2406,8 @@ static int cam_hw_cdm_component_bind(struct device *dev, CAM_ERR(CAM_CDM, "HW CDM Interface registration failed"); goto cpas_unregister; } + + cam_cdm_test_irq_line_at_probe(cdm_hw); mutex_unlock(&cdm_hw->hw_mutex); CAM_DBG(CAM_CDM, "%s component bound successfully", cdm_core->name); diff --git a/drivers/cam_cdm/cam_cdm_intf.c b/drivers/cam_cdm/cam_cdm_intf.c index e057595522..23404fc74c 100644 --- a/drivers/cam_cdm/cam_cdm_intf.c +++ b/drivers/cam_cdm/cam_cdm_intf.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -617,6 +617,80 @@ int cam_cdm_intf_deregister_hw_cdm(struct cam_hw_intf *hw, return rc; } +static int cam_cdm_set_irq_line_test(void *data, u64 val) +{ + int i, rc = 0; + struct cam_hw_intf *hw_intf; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + return rc; + } + mutex_lock(&cam_cdm_mgr_lock); + + for (i = 0 ; i < cdm_mgr.cdm_count; i++) { + if (!cdm_mgr.nodes[i].device || !cdm_mgr.nodes[i].data) { + CAM_ERR(CAM_CDM, "invalid node present in index=%d", i); + continue; + } + + hw_intf = cdm_mgr.nodes[i].device; + + if (hw_intf->hw_ops.test_irq_line) { + CAM_DBG(CAM_CDM, "Testing irq line for CDM at index %d", i); + + rc = hw_intf->hw_ops.test_irq_line(hw_intf->hw_priv); + if (rc) + CAM_ERR(CAM_CDM, + "[%d] : CDM%d type %d - irq line test failed rc %d", + i, hw_intf->hw_idx, hw_intf->hw_type, rc); + else + CAM_INFO(CAM_CDM, + "[%d] : CDM%d type %d - irq line test passed", + i, hw_intf->hw_idx, hw_intf->hw_type); + } else { + CAM_WARN(CAM_CDM, "test irq line interface not present for cdm at index %d", + i); + } + } + + mutex_unlock(&cam_cdm_mgr_lock); + put_cdm_mgr_refcount(); + + return rc; +} + +static int cam_cdm_get_irq_line_test(void *data, u64 *val) +{ + return 0; +} + + +DEFINE_DEBUGFS_ATTRIBUTE(cam_cdm_irq_line_test, cam_cdm_get_irq_line_test, + cam_cdm_set_irq_line_test, "%16llu"); + +int cam_cdm_debugfs_init(struct cam_cdm_intf_mgr *mgr) +{ + struct dentry *dbgfileptr = NULL; + int rc; + + if (!cam_debugfs_available()) + return 0; + + rc = cam_debugfs_create_subdir("cdm", &dbgfileptr); + if (rc) { + CAM_ERR(CAM_CDM, "DebugFS could not create directory!"); + return rc; + } + + mgr->dentry = dbgfileptr; + + debugfs_create_file("test_irq_line", 0644, + mgr->dentry, NULL, &cam_cdm_irq_line_test); + + return 0; +} + static int cam_cdm_intf_component_bind(struct device *dev, struct device *master_dev, void *data) { @@ -655,6 +729,8 @@ static int cam_cdm_intf_component_bind(struct device *dev, mutex_unlock(&cam_cdm_mgr_lock); } + cam_cdm_debugfs_init(&cdm_mgr); + CAM_DBG(CAM_CDM, "CDM Intf component bound successfully"); return rc; @@ -695,6 +771,7 @@ static void cam_cdm_intf_component_unbind(struct device *dev, cdm_mgr.nodes[i].data = NULL; cdm_mgr.nodes[i].refcount = 0; } + cdm_mgr.probe_done = false; end: