Loading drivers/Makefile +5 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,11 @@ camera-$(CONFIG_SPECTRA_ISP) += \ cam_isp/cam_isp_dev.o \ cam_isp/cam_isp_context.o camera-$(CONFIG_SPECTRA_SFE) += \ cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.o \ cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.o \ cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.o camera-$(CONFIG_SPECTRA_ICP) += \ cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.o \ cam_icp/icp_hw/ipe_hw/ipe_dev.o \ Loading drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ enum cam_isp_hw_type { CAM_ISP_HW_TYPE_TFE, CAM_ISP_HW_TYPE_TFE_CSID, CAM_ISP_HW_TYPE_TPG, CAM_ISP_HW_TYPE_SFE, CAM_ISP_HW_TYPE_MAX, }; Loading drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h 0 → 100644 +157 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SFE_HW_INTF_H_ #define _CAM_SFE_HW_INTF_H_ #include "cam_isp_hw.h" #define CAM_SFE_HW_NUM_MAX 2 #define SFE_CORE_BASE_IDX 0 enum cam_isp_hw_sfe_in { CAM_ISP_HW_SFE_IN_PIX, CAM_ISP_HW_SFE_IN_RD0, CAM_ISP_HW_SFE_IN_RD1, CAM_ISP_HW_SFE_IN_RD2, CAM_ISP_HW_SFE_IN_RDI0, CAM_ISP_HW_SFE_IN_RDI1, CAM_ISP_HW_SFE_IN_RDI2, CAM_ISP_HW_SFE_IN_RDI3, CAM_ISP_HW_SFE_IN_RDI4, CAM_ISP_HW_SFE_IN_MAX, }; enum cam_sfe_hw_irq_status { CAM_SFE_IRQ_STATUS_SUCCESS, CAM_SFE_IRQ_STATUS_ERR, CAM_SFE_IRQ_STATUS_OVERFLOW, CAM_SFE_IRQ_STATUS_VIOLATION, CAM_SFE_IRQ_STATUS_MAX, }; /* * struct cam_sfe_hw_get_hw_cap: * * @reserved_1: reserved * @reserved_2: reserved * @reserved_3: reserved * @reserved_4: reserved */ struct cam_sfe_hw_get_hw_cap { uint32_t reserved_1; uint32_t reserved_2; uint32_t reserved_3; uint32_t reserved_4; }; /* * struct cam_sfe_hw_vfe_bus_rd_acquire_args: * * @rsrc_node: Pointer to Resource Node object, filled if acquire * is successful * @res_id: Unique Identity of port to associate with this * resource. * @is_dual: Flag to indicate dual SFE usecase * @cdm_ops: CDM operations * @unpacket_fmt: Unpacker format for read engine * @is_offline: Flag to indicate offline usecase */ struct cam_sfe_hw_sfe_bus_rd_acquire_args { struct cam_isp_resource_node *rsrc_node; uint32_t res_id; uint32_t is_dual; struct cam_cdm_utils_ops *cdm_ops; uint32_t unpacker_fmt; bool is_offline; }; /* * struct cam_sfe_hw_sfe_bus_in_acquire_args: * * @rsrc_node: Pointer to Resource Node object, filled if acquire * is successful * @res_id: Unique Identity of port to associate with this * resource. * @cdm_ops: CDM operations * @is_dual: Dual mode usecase * @sync_mode: If in dual mode, indicates master/slave * @in_port: in port info * @is_fe_enabled: Flag to indicate if FE is enabled * @is_offline: Flag to indicate Offline IFE */ struct cam_sfe_hw_sfe_in_acquire_args { struct cam_isp_resource_node *rsrc_node; uint32_t res_id; struct cam_cdm_utils_ops *cdm_ops; uint32_t is_dual; enum cam_isp_hw_sync_mode sync_mode; struct cam_isp_in_port_generic_info *in_port; bool is_fe_enabled; bool is_offline; }; /* * struct cam_sfe_hw_sfe_out_acquire_args: * * @rsrc_node: Pointer to Resource Node object, filled if acquire * is successful * @out_port_info: Output Port details to acquire * @unique_id: Unique Identity of Context to associate with this * resource. Used for composite grouping of multiple * resources in the same context * @is_dual: Dual SFE or not * @split_id: In case of Dual SFE, this is Left or Right. * @is_master: In case of Dual SFE, this is Master or Slave. * @cdm_ops: CDM operations */ struct cam_sfe_hw_sfe_out_acquire_args { struct cam_isp_resource_node *rsrc_node; struct cam_isp_out_port_generic_info *out_port_info; uint32_t unique_id; uint32_t is_dual; enum cam_isp_hw_split_id split_id; uint32_t is_master; struct cam_cdm_utils_ops *cdm_ops; }; /* * struct cam_sfe_acquire_args: * * @rsrc_type: Type of Resource (OUT/IN) to acquire * @tasklet: Tasklet to associate with this resource. This is * used to schedule bottom of IRQ events associated * with this resource. * @priv: Context data * @event_cb: Callback function to hw mgr in case of hw events * @sfe_out: Acquire args for SFE_OUT * @sfe_bus_rd Acquire args for SFE_BUS_READ * @sfe_in: Acquire args for SFE_IN */ struct cam_sfe_acquire_args { enum cam_isp_resource_type rsrc_type; void *tasklet; void *priv; cam_hw_mgr_event_cb_func event_cb; union { struct cam_sfe_hw_sfe_out_acquire_args sfe_out; struct cam_sfe_hw_sfe_in_acquire_args sfe_in; struct cam_sfe_hw_sfe_bus_rd_acquire_args sfe_rd; }; }; /* * cam_sfe_hw_init() * * @Brief: Initialize SFE HW device * * @sfe_hw: sfe_hw interface to fill in and return on * successful initialization * @hw_idx: Index of SFE HW */ int cam_sfe_hw_init(struct cam_hw_intf **sfe_hw, uint32_t hw_idx); #endif /* _CAM_SFE_HW_INTF_H_ */ drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c 0 → 100644 +263 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #include <linux/slab.h> #include <linux/list.h> #include "cam_tasklet_util.h" #include "cam_sfe_hw_intf.h" #include "cam_sfe_soc.h" #include "cam_sfe_core.h" #include "cam_debug_util.h" static const char drv_name[] = "sfe"; #define SFE_CORE_BASE_IDX 0 int cam_sfe_get_hw_caps(void *hw_priv, void *get_hw_cap_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) { struct cam_hw_info *sfe_hw = hw_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_sfe_hw_core_info *core_info = NULL; struct cam_isp_resource_node *isp_res = NULL; int rc = 0; CAM_DBG(CAM_SFE, "Enter"); if (!hw_priv) { CAM_ERR(CAM_SFE, "Invalid arguments"); return -EINVAL; } mutex_lock(&sfe_hw->hw_mutex); sfe_hw->open_count++; if (sfe_hw->open_count > 1) { mutex_unlock(&sfe_hw->hw_mutex); CAM_DBG(CAM_SFE, "SFE has already been initialized cnt %d", sfe_hw->open_count); return 0; } mutex_unlock(&sfe_hw->hw_mutex); soc_info = &sfe_hw->soc_info; core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; /* Turn ON Regulators, Clocks and other SOC resources */ rc = cam_sfe_enable_soc_resources(soc_info); if (rc) { CAM_ERR(CAM_SFE, "Enable SOC failed"); rc = -EFAULT; goto decrement_open_cnt; } isp_res = (struct cam_isp_resource_node *)init_hw_args; if (isp_res && isp_res->init) { rc = isp_res->init(isp_res, NULL, 0); if (rc) { CAM_ERR(CAM_SFE, "init Failed rc=%d", rc); goto disable_soc; } } CAM_DBG(CAM_SFE, "Enable soc done"); /* Do HW Reset */ rc = cam_sfe_reset(hw_priv, NULL, 0); if (rc) { CAM_ERR(CAM_SFE, "Reset Failed rc=%d", rc); goto deinit_sfe_res; } sfe_hw->hw_state = CAM_HW_STATE_POWER_UP; return rc; deinit_sfe_res: if (isp_res && isp_res->deinit) isp_res->deinit(isp_res, NULL, 0); disable_soc: cam_sfe_disable_soc_resources(soc_info); decrement_open_cnt: mutex_lock(&sfe_hw->hw_mutex); sfe_hw->open_count--; mutex_unlock(&sfe_hw->hw_mutex); return rc; } int cam_sfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) { struct cam_hw_info *sfe_hw = hw_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_sfe_hw_core_info *core_info = NULL; struct cam_isp_resource_node *isp_res = NULL; int rc = 0; CAM_DBG(CAM_SFE, "Enter"); if (!hw_priv) { CAM_ERR(CAM_SFE, "Invalid arguments"); return -EINVAL; } mutex_lock(&sfe_hw->hw_mutex); if (!sfe_hw->open_count) { mutex_unlock(&sfe_hw->hw_mutex); CAM_ERR(CAM_SFE, "Error! Unbalanced deinit"); return -EFAULT; } sfe_hw->open_count--; if (sfe_hw->open_count) { mutex_unlock(&sfe_hw->hw_mutex); CAM_DBG(CAM_SFE, "open_cnt non-zero =%d", sfe_hw->open_count); return 0; } mutex_unlock(&sfe_hw->hw_mutex); soc_info = &sfe_hw->soc_info; core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; isp_res = (struct cam_isp_resource_node *)deinit_hw_args; if (isp_res && isp_res->deinit) { rc = isp_res->deinit(isp_res, NULL, 0); if (rc) CAM_ERR(CAM_SFE, "deinit failed"); } /* Turn OFF Regulators, Clocks and other SOC resources */ CAM_DBG(CAM_SFE, "Disable SOC resource"); rc = cam_sfe_disable_soc_resources(soc_info); if (rc) CAM_ERR(CAM_SFE, "Disable SOC failed"); sfe_hw->hw_state = CAM_HW_STATE_POWER_DOWN; CAM_DBG(CAM_SFE, "Exit"); return rc; } int cam_sfe_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_release(void *hw_priv, void *release_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_start(void *hw_priv, void *start_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_stop(void *hw_priv, void *stop_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_read(void *hw_priv, void *read_args, uint32_t arg_size) { return -EPERM; } int cam_sfe_write(void *hw_priv, void *write_args, uint32_t arg_size) { return -EPERM; } int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { struct cam_hw_info *sfe_hw = hw_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_sfe_hw_core_info *core_info = NULL; struct cam_sfe_hw_info *hw_info = NULL; int rc; if (!hw_priv) { CAM_ERR(CAM_SFE, "Invalid arguments"); return -EINVAL; } soc_info = &sfe_hw->soc_info; core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; hw_info = core_info->sfe_hw_info; switch (cmd_type) { case CAM_ISP_HW_CMD_GET_CHANGE_BASE: case CAM_ISP_HW_CMD_GET_REG_UPDATE: rc = 0; break; default: CAM_ERR(CAM_SFE, "Invalid cmd type:%d", cmd_type); rc = -EINVAL; break; } return rc; } irqreturn_t cam_sfe_irq(int irq_num, void *data) { struct cam_hw_info *sfe_hw; struct cam_sfe_hw_core_info *core_info; if (!data) return IRQ_NONE; sfe_hw = (struct cam_hw_info *)data; core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; return cam_irq_controller_handle_irq(irq_num, core_info->sfe_irq_controller); } int cam_sfe_core_init( struct cam_sfe_hw_core_info *core_info, struct cam_hw_soc_info *soc_info, struct cam_hw_intf *hw_intf, struct cam_sfe_hw_info *sfe_hw_info) { CAM_DBG(CAM_SFE, "Enter"); INIT_LIST_HEAD(&core_info->free_payload_list); spin_lock_init(&core_info->spin_lock); return 0; } int cam_sfe_core_deinit( struct cam_sfe_hw_core_info *core_info, struct cam_sfe_hw_info *sfe_hw_info) { int rc = -EINVAL; unsigned long flags; spin_lock_irqsave(&core_info->spin_lock, flags); INIT_LIST_HEAD(&core_info->free_payload_list); rc = cam_irq_controller_deinit(&core_info->sfe_irq_controller); if (rc) CAM_ERR(CAM_SFE, "Error cam_irq_controller_deinit failed rc=%d", rc); spin_unlock_irqrestore(&core_info->spin_lock, flags); return rc; } drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h 0 → 100644 +61 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SFE_CORE_H_ #define _CAM_SFE_CORE_H_ #include <linux/spinlock.h> #include "cam_hw_intf.h" #include "cam_sfe_hw_intf.h" struct cam_sfe_hw_info { struct cam_irq_controller_reg_info *irq_reg_info; }; #define CAM_SFE_EVT_MAX 256 struct cam_sfe_hw_core_info { struct cam_sfe_hw_info *sfe_hw_info; void *sfe_irq_controller; void *tasklet_info; struct list_head free_payload_list; spinlock_t spin_lock; int irq_handle; }; int cam_sfe_get_hw_caps(void *device_priv, void *get_hw_cap_args, uint32_t arg_size); int cam_sfe_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); int cam_sfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size); int cam_sfe_reset(void *device_priv, void *reset_core_args, uint32_t arg_size); int cam_sfe_reserve(void *device_priv, void *reserve_args, uint32_t arg_size); int cam_sfe_release(void *device_priv, void *reserve_args, uint32_t arg_size); int cam_sfe_start(void *device_priv, void *start_args, uint32_t arg_size); int cam_sfe_stop(void *device_priv, void *stop_args, uint32_t arg_size); int cam_sfe_read(void *device_priv, void *read_args, uint32_t arg_size); int cam_sfe_write(void *device_priv, void *write_args, uint32_t arg_size); int cam_sfe_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); irqreturn_t cam_sfe_irq(int irq_num, void *data); int cam_sfe_core_init(struct cam_sfe_hw_core_info *core_info, struct cam_hw_soc_info *soc_info, struct cam_hw_intf *hw_intf, struct cam_sfe_hw_info *sfe_hw_info); int cam_sfe_core_deinit(struct cam_sfe_hw_core_info *core_info, struct cam_sfe_hw_info *sfe_hw_info); #endif /* _CAM_SFE_CORE_H_ */ Loading
drivers/Makefile +5 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,11 @@ camera-$(CONFIG_SPECTRA_ISP) += \ cam_isp/cam_isp_dev.o \ cam_isp/cam_isp_context.o camera-$(CONFIG_SPECTRA_SFE) += \ cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_soc.o \ cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.o \ cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.o camera-$(CONFIG_SPECTRA_ICP) += \ cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.o \ cam_icp/icp_hw/ipe_hw/ipe_dev.o \ Loading
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ enum cam_isp_hw_type { CAM_ISP_HW_TYPE_TFE, CAM_ISP_HW_TYPE_TFE_CSID, CAM_ISP_HW_TYPE_TPG, CAM_ISP_HW_TYPE_SFE, CAM_ISP_HW_TYPE_MAX, }; Loading
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h 0 → 100644 +157 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SFE_HW_INTF_H_ #define _CAM_SFE_HW_INTF_H_ #include "cam_isp_hw.h" #define CAM_SFE_HW_NUM_MAX 2 #define SFE_CORE_BASE_IDX 0 enum cam_isp_hw_sfe_in { CAM_ISP_HW_SFE_IN_PIX, CAM_ISP_HW_SFE_IN_RD0, CAM_ISP_HW_SFE_IN_RD1, CAM_ISP_HW_SFE_IN_RD2, CAM_ISP_HW_SFE_IN_RDI0, CAM_ISP_HW_SFE_IN_RDI1, CAM_ISP_HW_SFE_IN_RDI2, CAM_ISP_HW_SFE_IN_RDI3, CAM_ISP_HW_SFE_IN_RDI4, CAM_ISP_HW_SFE_IN_MAX, }; enum cam_sfe_hw_irq_status { CAM_SFE_IRQ_STATUS_SUCCESS, CAM_SFE_IRQ_STATUS_ERR, CAM_SFE_IRQ_STATUS_OVERFLOW, CAM_SFE_IRQ_STATUS_VIOLATION, CAM_SFE_IRQ_STATUS_MAX, }; /* * struct cam_sfe_hw_get_hw_cap: * * @reserved_1: reserved * @reserved_2: reserved * @reserved_3: reserved * @reserved_4: reserved */ struct cam_sfe_hw_get_hw_cap { uint32_t reserved_1; uint32_t reserved_2; uint32_t reserved_3; uint32_t reserved_4; }; /* * struct cam_sfe_hw_vfe_bus_rd_acquire_args: * * @rsrc_node: Pointer to Resource Node object, filled if acquire * is successful * @res_id: Unique Identity of port to associate with this * resource. * @is_dual: Flag to indicate dual SFE usecase * @cdm_ops: CDM operations * @unpacket_fmt: Unpacker format for read engine * @is_offline: Flag to indicate offline usecase */ struct cam_sfe_hw_sfe_bus_rd_acquire_args { struct cam_isp_resource_node *rsrc_node; uint32_t res_id; uint32_t is_dual; struct cam_cdm_utils_ops *cdm_ops; uint32_t unpacker_fmt; bool is_offline; }; /* * struct cam_sfe_hw_sfe_bus_in_acquire_args: * * @rsrc_node: Pointer to Resource Node object, filled if acquire * is successful * @res_id: Unique Identity of port to associate with this * resource. * @cdm_ops: CDM operations * @is_dual: Dual mode usecase * @sync_mode: If in dual mode, indicates master/slave * @in_port: in port info * @is_fe_enabled: Flag to indicate if FE is enabled * @is_offline: Flag to indicate Offline IFE */ struct cam_sfe_hw_sfe_in_acquire_args { struct cam_isp_resource_node *rsrc_node; uint32_t res_id; struct cam_cdm_utils_ops *cdm_ops; uint32_t is_dual; enum cam_isp_hw_sync_mode sync_mode; struct cam_isp_in_port_generic_info *in_port; bool is_fe_enabled; bool is_offline; }; /* * struct cam_sfe_hw_sfe_out_acquire_args: * * @rsrc_node: Pointer to Resource Node object, filled if acquire * is successful * @out_port_info: Output Port details to acquire * @unique_id: Unique Identity of Context to associate with this * resource. Used for composite grouping of multiple * resources in the same context * @is_dual: Dual SFE or not * @split_id: In case of Dual SFE, this is Left or Right. * @is_master: In case of Dual SFE, this is Master or Slave. * @cdm_ops: CDM operations */ struct cam_sfe_hw_sfe_out_acquire_args { struct cam_isp_resource_node *rsrc_node; struct cam_isp_out_port_generic_info *out_port_info; uint32_t unique_id; uint32_t is_dual; enum cam_isp_hw_split_id split_id; uint32_t is_master; struct cam_cdm_utils_ops *cdm_ops; }; /* * struct cam_sfe_acquire_args: * * @rsrc_type: Type of Resource (OUT/IN) to acquire * @tasklet: Tasklet to associate with this resource. This is * used to schedule bottom of IRQ events associated * with this resource. * @priv: Context data * @event_cb: Callback function to hw mgr in case of hw events * @sfe_out: Acquire args for SFE_OUT * @sfe_bus_rd Acquire args for SFE_BUS_READ * @sfe_in: Acquire args for SFE_IN */ struct cam_sfe_acquire_args { enum cam_isp_resource_type rsrc_type; void *tasklet; void *priv; cam_hw_mgr_event_cb_func event_cb; union { struct cam_sfe_hw_sfe_out_acquire_args sfe_out; struct cam_sfe_hw_sfe_in_acquire_args sfe_in; struct cam_sfe_hw_sfe_bus_rd_acquire_args sfe_rd; }; }; /* * cam_sfe_hw_init() * * @Brief: Initialize SFE HW device * * @sfe_hw: sfe_hw interface to fill in and return on * successful initialization * @hw_idx: Index of SFE HW */ int cam_sfe_hw_init(struct cam_hw_intf **sfe_hw, uint32_t hw_idx); #endif /* _CAM_SFE_HW_INTF_H_ */
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c 0 → 100644 +263 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #include <linux/slab.h> #include <linux/list.h> #include "cam_tasklet_util.h" #include "cam_sfe_hw_intf.h" #include "cam_sfe_soc.h" #include "cam_sfe_core.h" #include "cam_debug_util.h" static const char drv_name[] = "sfe"; #define SFE_CORE_BASE_IDX 0 int cam_sfe_get_hw_caps(void *hw_priv, void *get_hw_cap_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size) { struct cam_hw_info *sfe_hw = hw_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_sfe_hw_core_info *core_info = NULL; struct cam_isp_resource_node *isp_res = NULL; int rc = 0; CAM_DBG(CAM_SFE, "Enter"); if (!hw_priv) { CAM_ERR(CAM_SFE, "Invalid arguments"); return -EINVAL; } mutex_lock(&sfe_hw->hw_mutex); sfe_hw->open_count++; if (sfe_hw->open_count > 1) { mutex_unlock(&sfe_hw->hw_mutex); CAM_DBG(CAM_SFE, "SFE has already been initialized cnt %d", sfe_hw->open_count); return 0; } mutex_unlock(&sfe_hw->hw_mutex); soc_info = &sfe_hw->soc_info; core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; /* Turn ON Regulators, Clocks and other SOC resources */ rc = cam_sfe_enable_soc_resources(soc_info); if (rc) { CAM_ERR(CAM_SFE, "Enable SOC failed"); rc = -EFAULT; goto decrement_open_cnt; } isp_res = (struct cam_isp_resource_node *)init_hw_args; if (isp_res && isp_res->init) { rc = isp_res->init(isp_res, NULL, 0); if (rc) { CAM_ERR(CAM_SFE, "init Failed rc=%d", rc); goto disable_soc; } } CAM_DBG(CAM_SFE, "Enable soc done"); /* Do HW Reset */ rc = cam_sfe_reset(hw_priv, NULL, 0); if (rc) { CAM_ERR(CAM_SFE, "Reset Failed rc=%d", rc); goto deinit_sfe_res; } sfe_hw->hw_state = CAM_HW_STATE_POWER_UP; return rc; deinit_sfe_res: if (isp_res && isp_res->deinit) isp_res->deinit(isp_res, NULL, 0); disable_soc: cam_sfe_disable_soc_resources(soc_info); decrement_open_cnt: mutex_lock(&sfe_hw->hw_mutex); sfe_hw->open_count--; mutex_unlock(&sfe_hw->hw_mutex); return rc; } int cam_sfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size) { struct cam_hw_info *sfe_hw = hw_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_sfe_hw_core_info *core_info = NULL; struct cam_isp_resource_node *isp_res = NULL; int rc = 0; CAM_DBG(CAM_SFE, "Enter"); if (!hw_priv) { CAM_ERR(CAM_SFE, "Invalid arguments"); return -EINVAL; } mutex_lock(&sfe_hw->hw_mutex); if (!sfe_hw->open_count) { mutex_unlock(&sfe_hw->hw_mutex); CAM_ERR(CAM_SFE, "Error! Unbalanced deinit"); return -EFAULT; } sfe_hw->open_count--; if (sfe_hw->open_count) { mutex_unlock(&sfe_hw->hw_mutex); CAM_DBG(CAM_SFE, "open_cnt non-zero =%d", sfe_hw->open_count); return 0; } mutex_unlock(&sfe_hw->hw_mutex); soc_info = &sfe_hw->soc_info; core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; isp_res = (struct cam_isp_resource_node *)deinit_hw_args; if (isp_res && isp_res->deinit) { rc = isp_res->deinit(isp_res, NULL, 0); if (rc) CAM_ERR(CAM_SFE, "deinit failed"); } /* Turn OFF Regulators, Clocks and other SOC resources */ CAM_DBG(CAM_SFE, "Disable SOC resource"); rc = cam_sfe_disable_soc_resources(soc_info); if (rc) CAM_ERR(CAM_SFE, "Disable SOC failed"); sfe_hw->hw_state = CAM_HW_STATE_POWER_DOWN; CAM_DBG(CAM_SFE, "Exit"); return rc; } int cam_sfe_reset(void *hw_priv, void *reset_core_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_release(void *hw_priv, void *release_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_start(void *hw_priv, void *start_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_stop(void *hw_priv, void *stop_args, uint32_t arg_size) { CAM_DBG(CAM_SFE, "Enter"); return 0; } int cam_sfe_read(void *hw_priv, void *read_args, uint32_t arg_size) { return -EPERM; } int cam_sfe_write(void *hw_priv, void *write_args, uint32_t arg_size) { return -EPERM; } int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { struct cam_hw_info *sfe_hw = hw_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_sfe_hw_core_info *core_info = NULL; struct cam_sfe_hw_info *hw_info = NULL; int rc; if (!hw_priv) { CAM_ERR(CAM_SFE, "Invalid arguments"); return -EINVAL; } soc_info = &sfe_hw->soc_info; core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; hw_info = core_info->sfe_hw_info; switch (cmd_type) { case CAM_ISP_HW_CMD_GET_CHANGE_BASE: case CAM_ISP_HW_CMD_GET_REG_UPDATE: rc = 0; break; default: CAM_ERR(CAM_SFE, "Invalid cmd type:%d", cmd_type); rc = -EINVAL; break; } return rc; } irqreturn_t cam_sfe_irq(int irq_num, void *data) { struct cam_hw_info *sfe_hw; struct cam_sfe_hw_core_info *core_info; if (!data) return IRQ_NONE; sfe_hw = (struct cam_hw_info *)data; core_info = (struct cam_sfe_hw_core_info *)sfe_hw->core_info; return cam_irq_controller_handle_irq(irq_num, core_info->sfe_irq_controller); } int cam_sfe_core_init( struct cam_sfe_hw_core_info *core_info, struct cam_hw_soc_info *soc_info, struct cam_hw_intf *hw_intf, struct cam_sfe_hw_info *sfe_hw_info) { CAM_DBG(CAM_SFE, "Enter"); INIT_LIST_HEAD(&core_info->free_payload_list); spin_lock_init(&core_info->spin_lock); return 0; } int cam_sfe_core_deinit( struct cam_sfe_hw_core_info *core_info, struct cam_sfe_hw_info *sfe_hw_info) { int rc = -EINVAL; unsigned long flags; spin_lock_irqsave(&core_info->spin_lock, flags); INIT_LIST_HEAD(&core_info->free_payload_list); rc = cam_irq_controller_deinit(&core_info->sfe_irq_controller); if (rc) CAM_ERR(CAM_SFE, "Error cam_irq_controller_deinit failed rc=%d", rc); spin_unlock_irqrestore(&core_info->spin_lock, flags); return rc; }
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h 0 → 100644 +61 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SFE_CORE_H_ #define _CAM_SFE_CORE_H_ #include <linux/spinlock.h> #include "cam_hw_intf.h" #include "cam_sfe_hw_intf.h" struct cam_sfe_hw_info { struct cam_irq_controller_reg_info *irq_reg_info; }; #define CAM_SFE_EVT_MAX 256 struct cam_sfe_hw_core_info { struct cam_sfe_hw_info *sfe_hw_info; void *sfe_irq_controller; void *tasklet_info; struct list_head free_payload_list; spinlock_t spin_lock; int irq_handle; }; int cam_sfe_get_hw_caps(void *device_priv, void *get_hw_cap_args, uint32_t arg_size); int cam_sfe_init_hw(void *device_priv, void *init_hw_args, uint32_t arg_size); int cam_sfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size); int cam_sfe_reset(void *device_priv, void *reset_core_args, uint32_t arg_size); int cam_sfe_reserve(void *device_priv, void *reserve_args, uint32_t arg_size); int cam_sfe_release(void *device_priv, void *reserve_args, uint32_t arg_size); int cam_sfe_start(void *device_priv, void *start_args, uint32_t arg_size); int cam_sfe_stop(void *device_priv, void *stop_args, uint32_t arg_size); int cam_sfe_read(void *device_priv, void *read_args, uint32_t arg_size); int cam_sfe_write(void *device_priv, void *write_args, uint32_t arg_size); int cam_sfe_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); irqreturn_t cam_sfe_irq(int irq_num, void *data); int cam_sfe_core_init(struct cam_sfe_hw_core_info *core_info, struct cam_hw_soc_info *soc_info, struct cam_hw_intf *hw_intf, struct cam_sfe_hw_info *sfe_hw_info); int cam_sfe_core_deinit(struct cam_sfe_hw_core_info *core_info, struct cam_sfe_hw_info *sfe_hw_info); #endif /* _CAM_SFE_CORE_H_ */