msm: camera: isp: Support for SFE IRQ handling

Add irq controller support for the SFE core & bus interfaces.

CRs-Fixed: 2783797
Change-Id: I84c04a13fa26a9d040bab9e7ec7ba2d3061e1f76
Signed-off-by: Jigarkumar Zala <jzala@codeaurora.org>
Signed-off-by: Karthik Anantha Ram <kartanan@codeaurora.org>
This commit is contained in:
Jigarkumar Zala
2020-07-28 22:25:46 -07:00
committed by Gerrit - the friendly Code Review server
parent 1232bfaa25
commit e4b180abaf
12 changed files with 1201 additions and 71 deletions

View File

@@ -7,6 +7,7 @@
#define _CAM_SFE_HW_INTF_H_
#include "cam_isp_hw.h"
#include "cam_isp_hw_mgr_intf.h"
#define SFE_CORE_BASE_IDX 0
#define SFE_RT_CDM_BASE_IDX 1
@@ -48,6 +49,11 @@ enum cam_sfe_bus_irq_regs {
CAM_SFE_BUS_IRQ_REGISTERS_MAX,
};
enum cam_sfe_bus_rd_irq_regs {
CAM_SFE_IRQ_BUS_RD_REG_STATUS0,
CAM_SFE_BUS_RD_IRQ_REGISTERS_MAX,
};
/*
* struct cam_sfe_fe_update_args:
*
@@ -83,33 +89,78 @@ struct cam_sfe_core_config_args {
};
/*
* struct cam_sfe_irq_evt_payload:
* struct cam_sfe_top_irq_evt_payload:
*
* @Brief: This structure is used to save payload for IRQ
* related to SFE resources
* related to SFE top resource
*
* @list: list_head node for the payload
* @core_index: Index of SFE HW that generated this IRQ event
* @evt_id: IRQ event
* @irq_reg_val: IRQ and Error register values, read when IRQ was
* handled
* @bus_irq_val Bus irq register status
* @ccif_violation_status ccif violation status
* @overflow_status bus overflow status
* @image_size_vio_sts image size violations status
* @violation_status ccif violation status
* @error_type: Identify different errors
* @ts: Timestamp
*/
struct cam_sfe_irq_evt_payload {
struct cam_sfe_top_irq_evt_payload {
struct list_head list;
uint32_t core_index;
uint32_t evt_id;
uint32_t irq_reg_val[CAM_SFE_IRQ_REGISTERS_MAX];
uint32_t bus_irq_val[CAM_SFE_BUS_IRQ_REGISTERS_MAX];
uint32_t violation_status;
uint32_t error_type;
struct cam_isp_timestamp ts;
};
/*
* struct cam_sfe_bus_wr_irq_evt_payload:
*
* @Brief: This structure is used to save payload for IRQ
* BUS related to SFE resources
*
* @list: list_head node for the payload
* @core_index: Index of SFE HW that generated this IRQ event
* @irq_reg_val Bus irq register status
* @ccif_violation_status ccif violation status
* @overflow_status bus overflow status
* @image_size_vio_sts image size violations status
* @error_type: Identify different errors
* @evt_id: IRQ event
* @ts: Timestamp
*/
struct cam_sfe_bus_wr_irq_evt_payload {
struct list_head list;
uint32_t core_index;
uint32_t irq_reg_val[CAM_SFE_BUS_IRQ_REGISTERS_MAX];
uint32_t ccif_violation_status;
uint32_t overflow_status;
uint32_t image_size_vio_sts;
uint32_t image_size_violation_status;
uint32_t error_type;
uint32_t evt_id;
struct cam_isp_timestamp ts;
};
/*
* struct cam_sfe_bus_rd_irq_evt_payload:
*
* @Brief: This structure is used to save payload for IRQ
* BUS related to SFE resources
*
* @list: list_head node for the payload
* @irq_reg_val Bus irq register status
* @constraint_violation constraint violation
* @error_type: Identify different errors
* @evt_id: IRQ event
* @ts: Timestamp
*/
struct cam_sfe_bus_rd_irq_evt_payload {
struct list_head list;
uint32_t irq_reg_val[
CAM_SFE_BUS_RD_IRQ_REGISTERS_MAX];
uint32_t constraint_violation;
uint32_t error_type;
uint32_t evt_id;
struct cam_isp_timestamp ts;
};

View File

@@ -128,6 +128,14 @@ static struct cam_sfe_top_hw_info sfe680_top_hw_info = {
},
};
static struct cam_irq_register_set sfe680_bus_rd_irq_reg[1] = {
{
.mask_reg_offset = 0x00000404,
.clear_reg_offset = 0x00000408,
.status_reg_offset = 0x00000410,
},
};
static struct cam_sfe_bus_rd_hw_info sfe680_bus_rd_hw_info = {
.common_reg = {
.hw_version = 0x00000400,
@@ -136,6 +144,13 @@ static struct cam_sfe_bus_rd_hw_info sfe680_bus_rd_hw_info = {
.input_if_cmd = 0x00000414,
.test_bus_ctrl = 0x0000042C,
.security_cfg = 0x00000420,
.cons_violation_status = 0x00000434,
.irq_reg_info = {
.num_registers = 1,
.irq_reg_set = sfe680_bus_rd_irq_reg,
.global_clear_offset = 0x0000040C,
.global_clear_bitmask = 0x00000001,
},
},
.num_client = 3,
.bus_client_reg = {
@@ -191,6 +206,14 @@ static struct cam_sfe_bus_rd_hw_info sfe680_bus_rd_hw_info = {
.top_irq_shift = 0x1,
};
static struct cam_irq_register_set sfe680_bus_wr_irq_reg[1] = {
{
.mask_reg_offset = 0x00000818,
.clear_reg_offset = 0x00000820,
.status_reg_offset = 0x00000828,
},
};
static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = {
.common_reg = {
.hw_version = 0x00000800,
@@ -211,7 +234,13 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = {
.debug_status_top_cfg = 0x000008D4,
.debug_status_top = 0x000008D8,
.test_bus_ctrl = 0x000008DC,
.top_irq_mask_0 = 0x00000818,
.top_irq_mask_0 = 0x00000020,
.irq_reg_info = {
.num_registers = 1,
.irq_reg_set = sfe680_bus_wr_irq_reg,
.global_clear_offset = 0x00000830,
.global_clear_bitmask = 0x00000001,
},
},
.num_client = 13,
.bus_client_reg = {
@@ -679,8 +708,23 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = {
.top_irq_shift = 0x0,
};
static struct cam_irq_register_set sfe680_top_irq_reg_set[1] = {
{
.mask_reg_offset = 0x00000020,
.clear_reg_offset = 0x00000024,
.status_reg_offset = 0x00000028,
},
};
static struct cam_irq_controller_reg_info sfe680_top_irq_reg_info = {
.num_registers = 1,
.irq_reg_set = sfe680_top_irq_reg_set,
.global_clear_offset = 0x0000001C,
.global_clear_bitmask = 0x00000001,
};
struct cam_sfe_hw_info cam_sfe680_hw_info = {
.irq_reg_info = NULL,
.irq_reg_info = &sfe680_top_irq_reg_info,
.bus_wr_version = CAM_SFE_BUS_WR_VER_1_0,
.bus_wr_hw_info = &sfe680_bus_wr_hw_info,

View File

@@ -407,17 +407,28 @@ int cam_sfe_core_init(
struct cam_hw_intf *hw_intf,
struct cam_sfe_hw_info *sfe_hw_info)
{
int rc;
int rc = -EINVAL;
rc = cam_irq_controller_init(drv_name,
CAM_SOC_GET_REG_MAP_START(soc_info, SFE_CORE_BASE_IDX),
sfe_hw_info->irq_reg_info, &core_info->sfe_irq_controller,
true);
if (rc) {
CAM_ERR(CAM_SFE, "SFE irq controller init failed");
return rc;
}
rc = cam_sfe_top_init(sfe_hw_info->top_version, soc_info, hw_intf,
sfe_hw_info->top_hw_info, &core_info->sfe_top);
sfe_hw_info->top_hw_info, core_info->sfe_irq_controller,
&core_info->sfe_top);
if (rc) {
CAM_ERR(CAM_SFE, "SFE top init failed rc: %d", rc);
return rc;
goto deinit_controller;
}
rc = cam_sfe_bus_init(sfe_hw_info->bus_wr_version, BUS_TYPE_SFE_WR,
soc_info, hw_intf, sfe_hw_info->bus_wr_hw_info,
core_info->sfe_irq_controller,
&core_info->sfe_bus_wr);
if (rc) {
CAM_ERR(CAM_SFE, "SFE bus wr init failed rc: %d", rc);
@@ -426,13 +437,13 @@ int cam_sfe_core_init(
rc = cam_sfe_bus_init(sfe_hw_info->bus_rd_version, BUS_TYPE_SFE_RD,
soc_info, hw_intf, sfe_hw_info->bus_rd_hw_info,
core_info->sfe_irq_controller,
&core_info->sfe_bus_rd);
if (rc) {
CAM_ERR(CAM_SFE, "SFE bus rd init failed rc: %d", rc);
goto deinit_bus_wr;
}
INIT_LIST_HEAD(&core_info->free_payload_list);
spin_lock_init(&core_info->spin_lock);
CAM_DBG(CAM_SFE, "SFE device [%u] INIT success",
hw_intf->hw_idx);
@@ -445,6 +456,11 @@ deinit_bus_wr:
deinit_top:
cam_sfe_top_deinit(sfe_hw_info->top_version,
&core_info->sfe_top);
deinit_controller:
if (cam_irq_controller_deinit(&core_info->sfe_irq_controller))
CAM_ERR(CAM_SFE,
"Error cam_irq_controller_deinit failed rc=%d", rc);
return rc;
}
@@ -452,15 +468,11 @@ int cam_sfe_core_deinit(
struct cam_sfe_hw_core_info *core_info,
struct cam_sfe_hw_info *sfe_hw_info)
{
int rc = -EINVAL, i;
int rc = -EINVAL;
unsigned long flags;
spin_lock_irqsave(&core_info->spin_lock, flags);
INIT_LIST_HEAD(&core_info->free_payload_list);
for (i = 0; i < CAM_SFE_EVT_MAX; i++)
INIT_LIST_HEAD(&core_info->evt_payload[i].list);
rc = cam_sfe_bus_deinit(BUS_TYPE_SFE_RD,
sfe_hw_info->bus_rd_version,
&core_info->sfe_bus_rd);
@@ -481,6 +493,11 @@ int cam_sfe_core_deinit(
CAM_ERR(CAM_SFE,
"SFE top deinit failed rc: %d", rc);
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;
}

View File

@@ -34,8 +34,6 @@ struct cam_sfe_hw_core_info {
struct cam_sfe_bus *sfe_bus_rd;
void *sfe_irq_controller;
void *tasklet_info;
struct cam_sfe_irq_evt_payload evt_payload[CAM_SFE_EVT_MAX];
struct list_head free_payload_list;
spinlock_t spin_lock;
};

View File

@@ -14,6 +14,7 @@ int cam_sfe_bus_init(
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *bus_hw_info,
void *sfe_irq_controller,
struct cam_sfe_bus **sfe_bus)
{
int rc = -ENODEV;
@@ -23,7 +24,7 @@ int cam_sfe_bus_init(
switch (bus_version) {
case CAM_SFE_BUS_WR_VER_1_0:
rc = cam_sfe_bus_wr_init(soc_info, hw_intf,
bus_hw_info, sfe_bus);
bus_hw_info, sfe_irq_controller, sfe_bus);
break;
default:
CAM_ERR(CAM_SFE, "Unsupported Bus WR Version 0x%x",
@@ -35,7 +36,7 @@ int cam_sfe_bus_init(
switch (bus_version) {
case CAM_SFE_BUS_RD_VER_1_0:
rc = cam_sfe_bus_rd_init(soc_info, hw_intf,
bus_hw_info, sfe_bus);
bus_hw_info, sfe_irq_controller, sfe_bus);
break;
default:
CAM_ERR(CAM_SFE, "Unsupported Bus RD Version 0x%x",

View File

@@ -28,7 +28,12 @@ static const char drv_name[] = "sfe_bus_rd";
#define MAX_REG_VAL_PAIR_SIZE \
(MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
#define BUS_RD_DEFAULT_LATENCY_BUF_ALLOC 512
#define BUS_RD_DEFAULT_LATENCY_BUF_ALLOC 512
#define CAM_SFE_BUS_RD_PAYLOAD_MAX 16
static uint32_t bus_rd_error_irq_mask[1] = {
0x00000001,
};
enum cam_sfe_bus_rd_unpacker_format {
BUS_RD_UNPACKER_FMT_PLAIN_128 = 0x0,
@@ -60,7 +65,12 @@ struct cam_sfe_bus_rd_common_data {
struct cam_sfe_bus_rd_reg_offset_common *common_reg;
uint32_t io_buf_update[
MAX_REG_VAL_PAIR_SIZE];
void *bus_irq_controller;
void *sfe_irq_controller;
spinlock_t spin_lock;
struct list_head free_payload_list;
struct cam_sfe_bus_rd_irq_evt_payload evt_payload[
CAM_SFE_BUS_RD_PAYLOAD_MAX];
cam_hw_mgr_event_cb_func event_cb;
};
@@ -95,7 +105,6 @@ struct cam_sfe_bus_rd_data {
uint32_t max_height;
struct cam_cdm_utils_ops *cdm_util_ops;
void *priv;
uint32_t status;
uint32_t secure_mode;
uint32_t fs_sync_enable;
uint32_t fs_line_sync_en;
@@ -112,6 +121,8 @@ struct cam_sfe_bus_rd_priv {
struct cam_isp_resource_node sfe_bus_rd[
CAM_SFE_BUS_RD_MAX];
int irq_handle;
int error_irq_handle;
void *tasklet_info;
uint32_t top_irq_shift;
};
@@ -280,6 +291,73 @@ static int cam_sfe_bus_get_rm_idx(
return rm_idx;
}
static int cam_sfe_bus_rd_get_evt_payload(
struct cam_sfe_bus_rd_common_data *common_data,
struct cam_sfe_bus_rd_irq_evt_payload **evt_payload)
{
int rc = 0;
spin_lock(&common_data->spin_lock);
if (list_empty(&common_data->free_payload_list)) {
CAM_ERR_RATE_LIMIT(CAM_SFE,
"No free BUS RD event payload");
*evt_payload = NULL;
rc = -ENODEV;
goto done;
}
*evt_payload = list_first_entry(&common_data->free_payload_list,
struct cam_sfe_bus_rd_irq_evt_payload, list);
list_del_init(&(*evt_payload)->list);
done:
spin_unlock(&common_data->spin_lock);
return rc;
}
static int cam_sfe_bus_rd_put_evt_payload(
struct cam_sfe_bus_rd_common_data *common_data,
struct cam_sfe_bus_rd_irq_evt_payload **evt_payload)
{
unsigned long flags;
if (!common_data) {
CAM_ERR(CAM_SFE, "Invalid param common_data NULL");
return -EINVAL;
}
if (*evt_payload == NULL) {
CAM_ERR(CAM_SFE, "No payload to put");
return -EINVAL;
}
spin_lock_irqsave(&common_data->spin_lock, flags);
list_add_tail(&(*evt_payload)->list,
&common_data->free_payload_list);
spin_unlock_irqrestore(&common_data->spin_lock, flags);
*evt_payload = NULL;
return 0;
}
static int cam_sfe_bus_rd_handle_irq(
uint32_t evt_id,
struct cam_irq_th_payload *th_payload)
{
struct cam_sfe_bus_rd_priv *bus_priv;
int rc = 0;
bus_priv = th_payload->handler_priv;
CAM_DBG(CAM_SFE, "Top Bus RD IRQ Received");
rc = cam_irq_controller_handle_irq(evt_id,
bus_priv->common_data.bus_irq_controller);
return (rc == IRQ_HANDLED) ? 0 : -EINVAL;
}
static int cam_sfe_bus_acquire_rm(
struct cam_sfe_bus_rd_priv *bus_rd_priv,
void *tasklet,
@@ -452,6 +530,99 @@ static int cam_sfe_bus_deinit_rm_resource(
return 0;
}
static int cam_sfe_bus_rd_handle_irq_top_half(uint32_t evt_id,
struct cam_irq_th_payload *th_payload)
{
int i, rc = 0;
struct cam_sfe_bus_rd_priv *bus_priv;
struct cam_sfe_bus_rd_irq_evt_payload *evt_payload = NULL;
bus_priv = th_payload->handler_priv;
rc = cam_sfe_bus_rd_get_evt_payload(
&bus_priv->common_data, &evt_payload);
if (rc)
return rc;
for (i = 0; i < th_payload->num_registers; i++) {
evt_payload->irq_reg_val[i] =
th_payload->evt_status_arr[i];
CAM_DBG(CAM_SFE, "SFE:%d Bus RD IRQ status_%d: 0x%x",
bus_priv->common_data.core_index, i,
th_payload->evt_status_arr[i]);
}
evt_payload->constraint_violation = cam_io_r_mb(
bus_priv->common_data.mem_base +
bus_priv->common_data.common_reg->cons_violation_status);
if (evt_payload->constraint_violation) {
CAM_ERR(CAM_SFE, "SFE:%d constraint violation:0x%x",
bus_priv->common_data.core_index,
evt_payload->constraint_violation);
cam_irq_controller_disable_irq(
bus_priv->common_data.bus_irq_controller,
bus_priv->error_irq_handle);
cam_irq_controller_clear_and_mask(evt_id,
bus_priv->common_data.bus_irq_controller);
}
cam_isp_hw_get_timestamp(&evt_payload->ts);
th_payload->evt_payload_priv = evt_payload;
return 0;
}
static int cam_sfe_bus_rd_handle_irq_bottom_half(
void *handler_priv, void *evt_payload_priv)
{
struct cam_sfe_bus_rd_irq_evt_payload *evt_payload;
struct cam_sfe_bus_rd_priv *bus_priv;
struct cam_sfe_bus_rd_common_data *common_data = NULL;
struct cam_isp_hw_event_info evt_info;
uint32_t status = 0, constraint_violation = 0;
if (!handler_priv || !evt_payload_priv)
return -EINVAL;
bus_priv = (struct cam_sfe_bus_rd_priv *)handler_priv;
evt_payload = (struct cam_sfe_bus_rd_irq_evt_payload *)evt_payload_priv;
common_data = &bus_priv->common_data;
status = evt_payload->irq_reg_val[CAM_SFE_IRQ_BUS_RD_REG_STATUS0];
constraint_violation = evt_payload->constraint_violation;
cam_sfe_bus_rd_put_evt_payload(common_data, &evt_payload);
if (status & 0x2)
CAM_DBG(CAM_SFE, "Received SFE:%d BUS RD RUP",
bus_priv->common_data.core_index);
if (status & 0x4)
CAM_DBG(CAM_SFE, "Received SFE:%d BUS RD0 BUF DONE",
bus_priv->common_data.core_index);
if (status & 0x8)
CAM_DBG(CAM_SFE, "Received SFE:%d BUS RD1 BUF DONE",
bus_priv->common_data.core_index);
if (status & 0x10)
CAM_DBG(CAM_SFE, "Received SFE:%d BUS RD2 BUF DONE",
bus_priv->common_data.core_index);
if (status & 0x1) {
CAM_ERR(CAM_SFE, "SFE:%d Constraint violation status:0x%x",
bus_priv->common_data.core_index,
constraint_violation);
evt_info.hw_idx = bus_priv->common_data.core_index;
evt_info.res_type = CAM_ISP_RESOURCE_SFE_RD;
evt_info.res_id = CAM_SFE_BUS_RD_MAX;
evt_info.err_type = CAM_SFE_IRQ_STATUS_VIOLATION;
if (common_data->event_cb)
common_data->event_cb(NULL,
CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info);
}
return 0;
}
static int cam_sfe_bus_rd_get_secure_mode(void *priv, void *cmd_args,
uint32_t arg_size)
{
@@ -639,7 +810,7 @@ static int cam_sfe_bus_start_bus_rd(
for (i = 0; i < rsrc_data->num_rm; i++)
rc = cam_sfe_bus_start_rm(rsrc_data->rm_res[i]);
/* Subscribe mask for buf_done */
/* TO DO Subscribe mask for buf_done */
sfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
return rc;
@@ -930,19 +1101,52 @@ static int cam_sfe_bus_init_hw(void *hw_priv,
void *init_hw_args, uint32_t arg_size)
{
struct cam_sfe_bus_rd_priv *bus_priv = hw_priv;
uint32_t sfe_top_irq_mask = 0;
uint32_t offset = 0;
struct cam_sfe_bus_rd_reg_offset_common *common_reg;
uint32_t sfe_top_irq_mask[CAM_SFE_IRQ_REGISTERS_MAX] = {0};
if (!bus_priv) {
CAM_ERR(CAM_SFE, "Invalid args");
return -EINVAL;
}
common_reg = bus_priv->common_data.common_reg;
sfe_top_irq_mask = (1 << bus_priv->top_irq_shift);
sfe_top_irq_mask[0] = (1 << bus_priv->top_irq_shift);
/* Subscribe for error IRQs */
/* Subscribe for top IRQ */
bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
bus_priv->common_data.sfe_irq_controller,
CAM_IRQ_PRIORITY_2,
sfe_top_irq_mask,
bus_priv,
cam_sfe_bus_rd_handle_irq,
NULL,
NULL,
NULL);
if (bus_priv->irq_handle < 1) {
CAM_ERR(CAM_SFE,
"Failed to subscribe TOP IRQ for BUS RD");
bus_priv->irq_handle = 0;
return -EFAULT;
}
if (bus_priv->tasklet_info != NULL) {
bus_priv->error_irq_handle = cam_irq_controller_subscribe_irq(
bus_priv->common_data.bus_irq_controller,
CAM_IRQ_PRIORITY_1,
bus_rd_error_irq_mask,
bus_priv,
cam_sfe_bus_rd_handle_irq_top_half,
cam_sfe_bus_rd_handle_irq_bottom_half,
bus_priv->tasklet_info,
&tasklet_bh_api);
if (bus_priv->error_irq_handle < 1) {
CAM_ERR(CAM_SFE, "Failed to subscribe error IRQ");
bus_priv->error_irq_handle = 0;
return -EFAULT;
}
}
/* BUS_RD_TEST_BUS_CTRL disabling test bus */
offset = common_reg->test_bus_ctrl;
cam_io_w_mb(0x0, bus_priv->common_data.mem_base + offset);
@@ -954,7 +1158,6 @@ static int cam_sfe_bus_deinit_hw(void *hw_priv,
void *deinit_hw_args, uint32_t arg_size)
{
struct cam_sfe_bus_rd_priv *bus_priv = hw_priv;
uint32_t sfe_top_irq_mask = 0;
int rc = 0;
if (!bus_priv) {
@@ -962,9 +1165,24 @@ static int cam_sfe_bus_deinit_hw(void *hw_priv,
return -EINVAL;
}
sfe_top_irq_mask = 1 << bus_priv->top_irq_shift;
/* Unsubscribe irqs */
if (bus_priv->irq_handle) {
rc = cam_irq_controller_unsubscribe_irq(
bus_priv->common_data.sfe_irq_controller,
bus_priv->irq_handle);
if (rc)
CAM_ERR(CAM_SFE, "Failed to unsubscribe top irq");
bus_priv->irq_handle = 0;
}
/* Unsubscribe for err irqs */
if (bus_priv->error_irq_handle) {
rc = cam_irq_controller_unsubscribe_irq(
bus_priv->common_data.bus_irq_controller,
bus_priv->error_irq_handle);
if (rc)
CAM_ERR(CAM_SFE, "Failed to unsubscribe error irq");
bus_priv->error_irq_handle = 0;
}
return rc;
}
@@ -1005,6 +1223,7 @@ int cam_sfe_bus_rd_init(
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *bus_hw_info,
void *sfe_irq_controller,
struct cam_sfe_bus **sfe_bus)
{
int i, rc = 0;
@@ -1036,7 +1255,6 @@ int cam_sfe_bus_rd_init(
}
sfe_bus_local->bus_priv = bus_priv;
bus_priv->num_client = bus_rd_hw_info->num_client;
bus_priv->num_bus_rd_resc =
bus_rd_hw_info->num_bus_rd_resc;
@@ -1044,9 +1262,19 @@ int cam_sfe_bus_rd_init(
bus_priv->common_data.mem_base =
CAM_SOC_GET_REG_MAP_START(soc_info, SFE_CORE_BASE_IDX);
bus_priv->common_data.hw_intf = hw_intf;
bus_priv->common_data.sfe_irq_controller = sfe_irq_controller;
bus_priv->common_data.common_reg = &bus_rd_hw_info->common_reg;
bus_priv->top_irq_shift = bus_rd_hw_info->top_irq_shift;
rc = cam_irq_controller_init(drv_name,
bus_priv->common_data.mem_base,
&bus_rd_hw_info->common_reg.irq_reg_info,
&bus_priv->common_data.bus_irq_controller, true);
if (rc) {
CAM_ERR(CAM_SFE, "IRQ controller init failed");
goto free_bus_priv;
}
for (i = 0; i < bus_priv->num_client; i++) {
rc = cam_sfe_bus_init_rm_resource(i, bus_priv, bus_hw_info,
&bus_priv->bus_client[i]);
@@ -1065,12 +1293,21 @@ int cam_sfe_bus_rd_init(
}
}
spin_lock_init(&bus_priv->common_data.spin_lock);
INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
for (i = 0; i < CAM_SFE_BUS_RD_PAYLOAD_MAX; i++) {
INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
list_add_tail(&bus_priv->common_data.evt_payload[i].list,
&bus_priv->common_data.free_payload_list);
}
sfe_bus_local->hw_ops.reserve = cam_sfe_bus_acquire_bus_rd;
sfe_bus_local->hw_ops.release = cam_sfe_bus_release_bus_rd;
sfe_bus_local->hw_ops.start = cam_sfe_bus_start_bus_rd;
sfe_bus_local->hw_ops.stop = cam_sfe_bus_stop_bus_rd;
sfe_bus_local->hw_ops.init = cam_sfe_bus_init_hw;
sfe_bus_local->hw_ops.deinit = cam_sfe_bus_deinit_hw;
sfe_bus_local->top_half_handler = cam_sfe_bus_rd_handle_irq;
sfe_bus_local->bottom_half_handler = NULL;
sfe_bus_local->hw_ops.process_cmd = cam_sfe_bus_rd_process_cmd;
@@ -1090,6 +1327,7 @@ deinit_rm:
for (--i; i >= 0; i--)
cam_sfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]);
free_bus_priv:
kfree(sfe_bus_local->bus_priv);
free_bus_local:
@@ -1103,6 +1341,7 @@ int cam_sfe_bus_rd_deinit(
struct cam_sfe_bus **sfe_bus)
{
int i, rc = 0;
unsigned long flags;
struct cam_sfe_bus_rd_priv *bus_priv = NULL;
struct cam_sfe_bus *sfe_bus_local;
@@ -1119,6 +1358,12 @@ int cam_sfe_bus_rd_deinit(
goto free_bus_local;
}
spin_lock_irqsave(&bus_priv->common_data.spin_lock, flags);
INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
for (i = 0; i < CAM_SFE_BUS_RD_PAYLOAD_MAX; i++)
INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
spin_unlock_irqrestore(&bus_priv->common_data.spin_lock, flags);
for (i = 0; i < bus_priv->num_client; i++) {
rc = cam_sfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]);
if (rc < 0)
@@ -1133,11 +1378,16 @@ int cam_sfe_bus_rd_deinit(
"Deinit SFE RD failed rc=%d", rc);
}
rc = cam_irq_controller_deinit(
&bus_priv->common_data.bus_irq_controller);
if (rc)
CAM_ERR(CAM_SFE,
"Deinit IRQ Controller failed rc=%d", rc);
kfree(sfe_bus_local->bus_priv);
free_bus_local:
kfree(sfe_bus_local);
*sfe_bus = NULL;
return rc;

View File

@@ -29,6 +29,8 @@ struct cam_sfe_bus_rd_reg_offset_common {
uint32_t input_if_cmd;
uint32_t test_bus_ctrl;
uint32_t security_cfg;
uint32_t cons_violation_status;
struct cam_irq_controller_reg_info irq_reg_info;
};
/*
@@ -98,6 +100,7 @@ int cam_sfe_bus_rd_init(
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *bus_hw_info,
void *sfe_irq_controller,
struct cam_sfe_bus **sfe_bus);
/*
@@ -105,7 +108,7 @@ int cam_sfe_bus_rd_init(
*
* @Brief: Deinitialize Bus layer
*
* @vfe_bus: Pointer to sfe_bus structure to deinitialize
* @sfe_bus: Pointer to sfe_bus structure to deinitialize
*
* @Return: 0: Success
* Non-zero: Failure

View File

@@ -37,6 +37,10 @@ static const char drv_name[] = "sfe_bus_wr";
#define MAX_REG_VAL_PAIR_SIZE \
(MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
static uint32_t bus_wr_error_irq_mask[1] = {
0xD0000000,
};
enum cam_sfe_bus_wr_packer_format {
PACKER_FMT_PLAIN_128,
PACKER_FMT_PLAIN_8,
@@ -63,12 +67,16 @@ struct cam_sfe_bus_wr_common_data {
uint32_t hw_version;
void __iomem *mem_base;
struct cam_hw_intf *hw_intf;
void *sfe_irq_controller;
void *buf_done_controller;
void *bus_irq_controller;
struct cam_sfe_bus_reg_offset_common *common_reg;
uint32_t io_buf_update[
MAX_REG_VAL_PAIR_SIZE];
struct list_head free_payload_list;
spinlock_t spin_lock;
struct cam_sfe_bus_wr_irq_evt_payload evt_payload[
CAM_SFE_BUS_WR_PAYLOAD_MAX];
struct mutex bus_mutex;
uint32_t secure_mode;
uint32_t num_sec_out;
@@ -167,10 +175,9 @@ struct cam_sfe_bus_wr_priv {
struct list_head free_comp_grp;
struct list_head used_comp_grp;
//int bus_irq_handle;
//int rup_irq_handle;
//int error_irq_handle;
//void *tasklet_info;
int bus_irq_handle;
int error_irq_handle;
void *tasklet_info;
};
static int cam_sfe_bus_wr_process_cmd(
@@ -235,6 +242,54 @@ static enum cam_sfe_bus_sfe_out_type
}
}
static int cam_sfe_bus_get_comp_sfe_out_res_id_list(
uint32_t comp_mask, uint32_t *out_list, int *num_out)
{
int count = 0;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RDI0))
out_list[count++] = CAM_ISP_SFE_OUT_RES_RDI_0;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RDI1))
out_list[count++] = CAM_ISP_SFE_OUT_RES_RDI_1;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RDI2))
out_list[count++] = CAM_ISP_SFE_OUT_RES_RDI_2;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RDI3))
out_list[count++] = CAM_ISP_SFE_OUT_RES_RDI_3;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RDI4))
out_list[count++] = CAM_ISP_SFE_OUT_RES_RDI_4;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_RAW_DUMP))
out_list[count++] = CAM_ISP_SFE_OUT_RES_RAW_DUMP;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BE_0))
out_list[count++] = CAM_ISP_SFE_OUT_BE_STATS_0;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BHIST_0))
out_list[count++] = CAM_ISP_SFE_OUT_BHIST_STATS_0;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BE_1))
out_list[count++] = CAM_ISP_SFE_OUT_BE_STATS_1;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BHIST_1))
out_list[count++] = CAM_ISP_SFE_OUT_BHIST_STATS_1;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BE_2))
out_list[count++] = CAM_ISP_SFE_OUT_BE_STATS_2;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_BHIST_2))
out_list[count++] = CAM_ISP_SFE_OUT_BHIST_STATS_2;
if (comp_mask & (1 << CAM_SFE_BUS_SFE_OUT_LCR))
out_list[count++] = CAM_ISP_SFE_OUT_RES_LCR;
*num_out = count;
return 0;
}
static enum cam_sfe_bus_wr_packer_format
cam_sfe_bus_get_packer_fmt(uint32_t out_fmt, int wm_index)
{
@@ -766,7 +821,9 @@ static int cam_sfe_bus_start_comp_grp(
if (comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING)
return 0;
/* TO DO Enable top irq */
bus_irq_reg_mask[CAM_SFE_IRQ_BUS_REG_STATUS0] =
(0x1 << (rsrc_data->comp_grp_type +
rsrc_data->common_data->comp_done_shift));
CAM_DBG(CAM_SFE, "Start Done SFE:%d comp_grp:%d",
rsrc_data->common_data->core_index,
@@ -1073,13 +1130,73 @@ static int cam_sfe_bus_release_sfe_out(void *bus_priv, void *release_args,
return 0;
}
static int cam_sfe_bus_wr_get_evt_payload(
struct cam_sfe_bus_wr_common_data *common_data,
struct cam_sfe_bus_wr_irq_evt_payload **evt_payload)
{
int rc;
spin_lock(&common_data->spin_lock);
if (!common_data->hw_init) {
CAM_ERR_RATE_LIMIT(CAM_SFE, "SFE:%d Bus uninitialized",
common_data->core_index);
*evt_payload = NULL;
rc = -EPERM;
goto done;
}
if (list_empty(&common_data->free_payload_list)) {
CAM_ERR_RATE_LIMIT(CAM_SFE, "No free BUS event payload");
*evt_payload = NULL;
rc = -ENODEV;
goto done;
}
*evt_payload = list_first_entry(&common_data->free_payload_list,
struct cam_sfe_bus_wr_irq_evt_payload, list);
list_del_init(&(*evt_payload)->list);
rc = 0;
done:
spin_unlock(&common_data->spin_lock);
return rc;
}
static int cam_sfe_bus_wr_put_evt_payload(
struct cam_sfe_bus_wr_common_data *common_data,
struct cam_sfe_bus_wr_irq_evt_payload **evt_payload)
{
unsigned long flags;
if (!common_data) {
CAM_ERR(CAM_SFE, "Invalid param common_data NULL");
return -EINVAL;
}
if (*evt_payload == NULL) {
CAM_ERR(CAM_SFE, "No payload to put");
return -EINVAL;
}
spin_lock_irqsave(&common_data->spin_lock, flags);
if (common_data->hw_init)
list_add_tail(&(*evt_payload)->list,
&common_data->free_payload_list);
spin_unlock_irqrestore(&common_data->spin_lock, flags);
*evt_payload = NULL;
CAM_DBG(CAM_SFE, "Done");
return 0;
}
static int cam_sfe_bus_start_sfe_out(
struct cam_isp_resource_node *sfe_out)
{
int rc = 0, i;
struct cam_sfe_bus_wr_out_data *rsrc_data = NULL;
struct cam_sfe_bus_wr_common_data *common_data = NULL;
uint32_t bus_irq_reg_mask[2];
uint32_t bus_irq_reg_mask[CAM_SFE_IRQ_REGISTERS_MAX];
uint32_t source_group = 0;
if (!sfe_out) {
@@ -1112,8 +1229,21 @@ static int cam_sfe_bus_start_sfe_out(
if (rsrc_data->is_dual && !rsrc_data->is_master)
goto end;
/* TO DO IRQ handling */
sfe_out->irq_handle = cam_irq_controller_subscribe_irq(
common_data->buf_done_controller,
CAM_IRQ_PRIORITY_1,
bus_irq_reg_mask,
sfe_out,
sfe_out->top_half_handler,
sfe_out->bottom_half_handler,
sfe_out->tasklet_info,
&tasklet_bh_api);
if (sfe_out->irq_handle < 1) {
CAM_ERR(CAM_SFE, "Subscribe IRQ failed for sfe out_res: %d",
sfe_out->res_id);
sfe_out->irq_handle = 0;
return -EFAULT;
}
end:
sfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
return rc;
@@ -1148,10 +1278,161 @@ static int cam_sfe_bus_stop_sfe_out(
rc = cam_sfe_bus_stop_wm(&rsrc_data->wm_res[i]);
/* TO DO any IRQ handling */
if (sfe_out->irq_handle) {
cam_irq_controller_unsubscribe_irq(
common_data->buf_done_controller,
sfe_out->irq_handle);
sfe_out->irq_handle = 0;
}
sfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
return rc;
}
static int cam_sfe_bus_handle_sfe_out_done_top_half(
uint32_t evt_id,
struct cam_irq_th_payload *th_payload)
{
int32_t rc;
int i;
struct cam_isp_resource_node *sfe_out = NULL;
struct cam_sfe_bus_wr_out_data *rsrc_data = NULL;
struct cam_sfe_bus_wr_irq_evt_payload *evt_payload;
struct cam_sfe_bus_wr_comp_grp_data *resource_data;
uint32_t status_0;
sfe_out = th_payload->handler_priv;
if (!sfe_out) {
CAM_ERR_RATE_LIMIT(CAM_SFE, "No resource");
return -ENODEV;
}
rsrc_data = sfe_out->res_priv;
resource_data = rsrc_data->comp_grp->res_priv;
CAM_DBG(CAM_SFE, "SFE:%d Bus IRQ status_0: 0x%X status_1: 0x%X",
rsrc_data->common_data->core_index,
th_payload->evt_status_arr[0],
th_payload->evt_status_arr[1]);
rc = cam_sfe_bus_wr_get_evt_payload(rsrc_data->common_data,
&evt_payload);
if (rc) {
CAM_INFO_RATE_LIMIT(CAM_SFE,
"SFE:%d Bus IRQ status_0: 0x%X status_1: 0x%X",
rsrc_data->common_data->core_index,
th_payload->evt_status_arr[0],
th_payload->evt_status_arr[1]);
return rc;
}
cam_isp_hw_get_timestamp(&evt_payload->ts);
evt_payload->core_index = rsrc_data->common_data->core_index;
evt_payload->evt_id = evt_id;
for (i = 0; i < th_payload->num_registers; i++)
evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
th_payload->evt_payload_priv = evt_payload;
status_0 = th_payload->evt_status_arr[CAM_SFE_IRQ_BUS_REG_STATUS0];
if (status_0 & BIT(resource_data->comp_grp_type +
rsrc_data->common_data->comp_done_shift)) {
trace_cam_log_event("bufdone", "bufdone_IRQ",
status_0, resource_data->comp_grp_type);
}
return rc;
}
static int cam_sfe_bus_handle_comp_done_bottom_half(
void *handler_priv,
void *evt_payload_priv,
uint32_t *comp_mask)
{
int rc = CAM_SFE_IRQ_STATUS_ERR;
struct cam_isp_resource_node *comp_grp = handler_priv;
struct cam_sfe_bus_wr_irq_evt_payload *evt_payload = evt_payload_priv;
struct cam_sfe_bus_wr_comp_grp_data *rsrc_data = comp_grp->res_priv;
uint32_t *cam_ife_irq_regs;
uint32_t status_0;
if (!evt_payload)
return rc;
if (rsrc_data->is_dual && (!rsrc_data->is_master)) {
CAM_ERR(CAM_SFE, "Invalid comp_grp:%u is_master:%u",
rsrc_data->comp_grp_type, rsrc_data->is_master);
return rc;
}
cam_ife_irq_regs = evt_payload->irq_reg_val;
status_0 = cam_ife_irq_regs[CAM_SFE_IRQ_BUS_REG_STATUS0];
if (status_0 & BIT(rsrc_data->comp_grp_type +
rsrc_data->common_data->comp_done_shift)) {
evt_payload->evt_id = CAM_ISP_HW_EVENT_DONE;
rc = CAM_SFE_IRQ_STATUS_SUCCESS;
}
CAM_DBG(CAM_SFE, "SFE:%d comp_grp:%d Bus IRQ status_0: 0x%X rc:%d",
rsrc_data->common_data->core_index, rsrc_data->comp_grp_type,
status_0, rc);
*comp_mask = rsrc_data->composite_mask;
return rc;
}
static int cam_sfe_bus_handle_sfe_out_done_bottom_half(
void *handler_priv,
void *evt_payload_priv)
{
int rc = -EINVAL, num_out = 0, i = 0;
struct cam_isp_resource_node *sfe_out = handler_priv;
struct cam_sfe_bus_wr_out_data *rsrc_data = sfe_out->res_priv;
struct cam_sfe_bus_wr_irq_evt_payload *evt_payload = evt_payload_priv;
struct cam_isp_hw_event_info evt_info;
void *ctx = NULL;
uint32_t evt_id = 0, comp_mask = 0;
uint32_t out_list[CAM_SFE_BUS_SFE_OUT_MAX];
rc = cam_sfe_bus_handle_comp_done_bottom_half(
rsrc_data->comp_grp, evt_payload_priv, &comp_mask);
CAM_DBG(CAM_SFE, "SFE:%d out_type:0x%X rc:%d",
rsrc_data->common_data->core_index, rsrc_data->out_type,
rsrc_data->out_type, rc);
ctx = rsrc_data->priv;
memset(out_list, 0, sizeof(out_list));
switch (rc) {
case CAM_SFE_IRQ_STATUS_SUCCESS:
evt_id = evt_payload->evt_id;
evt_info.res_type = sfe_out->res_type;
evt_info.hw_idx = sfe_out->hw_intf->hw_idx;
rc = cam_sfe_bus_get_comp_sfe_out_res_id_list(
comp_mask, out_list, &num_out);
for (i = 0; i < num_out; i++) {
evt_info.res_id = out_list[i];
if (rsrc_data->common_data->event_cb)
rsrc_data->common_data->event_cb(ctx, evt_id,
(void *)&evt_info);
}
break;
default:
break;
}
cam_sfe_bus_wr_put_evt_payload(rsrc_data->common_data, &evt_payload);
return rc;
}
static int cam_sfe_bus_init_sfe_out_resource(
uint32_t index,
struct cam_sfe_bus_wr_priv *bus_priv,
@@ -1220,11 +1501,12 @@ static int cam_sfe_bus_init_sfe_out_resource(
return rc;
}
/* TO DO top & bh */
sfe_out->start = cam_sfe_bus_start_sfe_out;
sfe_out->stop = cam_sfe_bus_stop_sfe_out;
sfe_out->top_half_handler = NULL;
sfe_out->bottom_half_handler = NULL;
sfe_out->top_half_handler =
cam_sfe_bus_handle_sfe_out_done_top_half;
sfe_out->bottom_half_handler =
cam_sfe_bus_handle_sfe_out_done_bottom_half;
sfe_out->process_cmd = cam_sfe_bus_wr_process_cmd;
sfe_out->hw_intf = bus_priv->common_data.hw_intf;
sfe_out->irq_handle = 0;
@@ -1307,6 +1589,97 @@ static int cam_sfe_bus_wr_print_dimensions(
return 0;
}
static int cam_sfe_bus_wr_handle_bus_irq(uint32_t evt_id,
struct cam_irq_th_payload *th_payload)
{
struct cam_sfe_bus_wr_priv *bus_priv;
int rc = 0;
bus_priv = th_payload->handler_priv;
rc = cam_irq_controller_handle_irq(evt_id,
bus_priv->common_data.bus_irq_controller);
return (rc == IRQ_HANDLED) ? 0 : -EINVAL;
}
static int cam_sfe_bus_wr_err_irq_top_half(uint32_t evt_id,
struct cam_irq_th_payload *th_payload)
{
int i = 0, rc = 0;
struct cam_sfe_bus_wr_priv *bus_priv =
th_payload->handler_priv;
struct cam_sfe_bus_wr_irq_evt_payload *evt_payload;
CAM_ERR_RATE_LIMIT(CAM_ISP, "SFE:%d BUS Err IRQ",
bus_priv->common_data.core_index);
for (i = 0; i < th_payload->num_registers; i++) {
CAM_ERR_RATE_LIMIT(CAM_ISP, "SFE:%d BUS IRQ status_%d: 0x%X",
bus_priv->common_data.core_index, i,
th_payload->evt_status_arr[i]);
}
cam_irq_controller_disable_irq(
bus_priv->common_data.bus_irq_controller,
bus_priv->error_irq_handle);
rc = cam_sfe_bus_wr_get_evt_payload(&bus_priv->common_data,
&evt_payload);
if (rc)
return rc;
for (i = 0; i < th_payload->num_registers; i++)
evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
evt_payload->core_index = bus_priv->common_data.core_index;
evt_payload->ccif_violation_status = cam_io_r_mb(
bus_priv->common_data.mem_base +
bus_priv->common_data.common_reg->ccif_violation_status);
evt_payload->image_size_violation_status = cam_io_r_mb(
bus_priv->common_data.mem_base +
bus_priv->common_data.common_reg->image_size_violation_status);
th_payload->evt_payload_priv = evt_payload;
return rc;
}
static int cam_sfe_bus_wr_irq_bottom_half(
void *handler_priv, void *evt_payload_priv)
{
uint32_t status = 0;
struct cam_sfe_bus_wr_priv *bus_priv = handler_priv;
struct cam_sfe_bus_wr_common_data *common_data;
struct cam_isp_hw_event_info evt_info;
struct cam_sfe_bus_wr_irq_evt_payload *evt_payload = evt_payload_priv;
if (!handler_priv || !evt_payload_priv)
return -EINVAL;
common_data = &bus_priv->common_data;
status = evt_payload->irq_reg_val[CAM_SFE_IRQ_BUS_REG_STATUS0];
CAM_ERR(CAM_SFE,
"SFE:%d status 0x%x Image Size violation status 0x%x CCIF violation status 0x%x",
bus_priv->common_data.core_index, status,
evt_payload->image_size_violation_status,
evt_payload->ccif_violation_status);
cam_sfe_bus_wr_put_evt_payload(common_data, &evt_payload);
evt_info.hw_idx = common_data->core_index;
evt_info.res_type = CAM_ISP_RESOURCE_SFE_OUT;
evt_info.res_id = CAM_SFE_BUS_SFE_OUT_MAX;
evt_info.err_type = CAM_SFE_IRQ_STATUS_VIOLATION;
if (common_data->event_cb)
common_data->event_cb(NULL, CAM_ISP_HW_EVENT_ERROR,
(void *)&evt_info);
return 0;
}
static int cam_sfe_bus_wr_update_wm(void *priv, void *cmd_args,
uint32_t arg_size)
{
@@ -1680,6 +2053,7 @@ static int cam_sfe_bus_wr_init_hw(void *hw_priv,
void *init_hw_args, uint32_t arg_size)
{
struct cam_sfe_bus_wr_priv *bus_priv = hw_priv;
uint32_t top_irq_reg_mask[CAM_SFE_IRQ_REGISTERS_MAX] = {0};
if (!bus_priv) {
CAM_ERR(CAM_SFE, "Invalid args");
@@ -1689,7 +2063,42 @@ static int cam_sfe_bus_wr_init_hw(void *hw_priv,
if (bus_priv->common_data.hw_init)
return 0;
/* To Do Subscribe IRQs */
/* Subscribe top IRQ */
top_irq_reg_mask[0] = (1 << bus_priv->top_irq_shift);
bus_priv->bus_irq_handle = cam_irq_controller_subscribe_irq(
bus_priv->common_data.sfe_irq_controller,
CAM_IRQ_PRIORITY_4,
top_irq_reg_mask,
bus_priv,
cam_sfe_bus_wr_handle_bus_irq,
NULL,
NULL,
NULL);
if (bus_priv->bus_irq_handle < 1) {
CAM_ERR(CAM_SFE, "Failed to subscribe BUS (buf_done) IRQ");
bus_priv->bus_irq_handle = 0;
return -EFAULT;
}
if (bus_priv->tasklet_info != NULL) {
bus_priv->error_irq_handle = cam_irq_controller_subscribe_irq(
bus_priv->common_data.bus_irq_controller,
CAM_IRQ_PRIORITY_0,
bus_wr_error_irq_mask,
bus_priv,
cam_sfe_bus_wr_err_irq_top_half,
cam_sfe_bus_wr_irq_bottom_half,
bus_priv->tasklet_info,
&tasklet_bh_api);
if (bus_priv->error_irq_handle < 1) {
CAM_ERR(CAM_SFE, "Failed to subscribe BUS Error IRQ");
bus_priv->error_irq_handle = 0;
return -EFAULT;
}
}
/* BUS_WR_TEST_BUS_CTRL */
cam_io_w_mb(0x0, bus_priv->common_data.mem_base +
@@ -1787,13 +2196,13 @@ int cam_sfe_bus_wr_init(
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *bus_hw_info,
void *sfe_irq_controller,
struct cam_sfe_bus **sfe_bus)
{
int i, rc = 0;
struct cam_sfe_bus_wr_priv *bus_priv = NULL;
struct cam_sfe_bus *sfe_bus_local;
struct cam_sfe_bus_wr_hw_info *hw_info = bus_hw_info;
struct cam_sfe_soc_private *soc_private = NULL;
CAM_DBG(CAM_SFE, "Enter");
@@ -1805,13 +2214,6 @@ int cam_sfe_bus_wr_init(
goto end;
}
soc_private = soc_info->soc_private;
if (!soc_private) {
CAM_ERR(CAM_SFE, "Invalid soc_private");
rc = -ENODEV;
goto end;
}
sfe_bus_local = kzalloc(sizeof(struct cam_sfe_bus), GFP_KERNEL);
if (!sfe_bus_local) {
CAM_DBG(CAM_SFE, "Failed to alloc for sfe_bus");
@@ -1841,11 +2243,11 @@ int cam_sfe_bus_wr_init(
bus_priv->common_data.common_reg = &hw_info->common_reg;
bus_priv->common_data.comp_done_shift = hw_info->comp_done_shift;
bus_priv->common_data.hw_init = false;
bus_priv->common_data.sfe_irq_controller = sfe_irq_controller;
rc = cam_cpas_get_cpas_hw_version(&bus_priv->common_data.hw_version);
if (rc) {
CAM_ERR(CAM_SFE, "Failed to get hw_version rc:%d", rc);
goto end;
goto free_bus_priv;
}
bus_priv->comp_grp = kzalloc((sizeof(struct cam_isp_resource_node) *
@@ -1865,6 +2267,15 @@ int cam_sfe_bus_wr_init(
}
mutex_init(&bus_priv->common_data.bus_mutex);
rc = cam_irq_controller_init(drv_name,
bus_priv->common_data.mem_base,
&hw_info->common_reg.irq_reg_info,
&bus_priv->common_data.bus_irq_controller,
false);
if (rc) {
CAM_ERR(CAM_SFE, "Init bus_irq_controller failed");
goto free_bus_priv;
}
INIT_LIST_HEAD(&bus_priv->free_comp_grp);
INIT_LIST_HEAD(&bus_priv->used_comp_grp);
@@ -1894,6 +2305,12 @@ int cam_sfe_bus_wr_init(
spin_lock_init(&bus_priv->common_data.spin_lock);
INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
for (i = 0; i < CAM_SFE_BUS_WR_PAYLOAD_MAX; i++) {
INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
list_add_tail(&bus_priv->common_data.evt_payload[i].list,
&bus_priv->common_data.free_payload_list);
}
sfe_bus_local->hw_ops.reserve = cam_sfe_bus_acquire_sfe_out;
sfe_bus_local->hw_ops.release = cam_sfe_bus_release_sfe_out;
sfe_bus_local->hw_ops.start = cam_sfe_bus_wr_start_hw;
@@ -1958,8 +2375,8 @@ int cam_sfe_bus_wr_deinit(
spin_lock_irqsave(&bus_priv->common_data.spin_lock, flags);
INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
//for (i = 0; i < CAM_SFE_BUS_WR_PAYLOAD_MAX; i++)
//INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
for (i = 0; i < CAM_SFE_BUS_WR_PAYLOAD_MAX; i++)
INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
bus_priv->common_data.hw_init = false;
spin_unlock_irqrestore(&bus_priv->common_data.spin_lock, flags);

View File

@@ -7,7 +7,6 @@
#ifndef _CAM_SFE_BUS_WR_H_
#define _CAM_SFE_BUS_WR_H_
#include "cam_irq_controller.h"
#include "cam_sfe_bus.h"
#define CAM_SFE_BUS_WR_MAX_CLIENTS 13
@@ -72,6 +71,7 @@ struct cam_sfe_bus_reg_offset_common {
uint32_t debug_status_top;
uint32_t test_bus_ctrl;
uint32_t top_irq_mask_0;
struct cam_irq_controller_reg_info irq_reg_info;
};
/*
@@ -154,6 +154,7 @@ struct cam_sfe_bus_wr_hw_info {
* @soc_info: Soc Information for the associated HW
* @hw_intf: HW Interface of HW to which this resource belongs
* @bus_hw_info: BUS HW info that contains details of BUS registers
* @sfe_irq_controller: SFE irq controller
* @sfe_bus: Pointer to sfe_bus structure which will be filled
* and returned on successful initialize
*
@@ -164,6 +165,7 @@ int cam_sfe_bus_wr_init(
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *bus_hw_info,
void *sfe_irq_controller,
struct cam_sfe_bus **sfe_bus);
/*

View File

@@ -6,7 +6,6 @@
#ifndef _CAM_SFE_BUS_H_
#define _CAM_SFE_BUS_H_
#include "cam_isp_hw.h"
#include "cam_sfe_hw_intf.h"
#define CAM_SFE_BUS_WR_VER_1_0 0x1000
@@ -50,8 +49,7 @@ enum cam_sfe_bus_type {
* @bottom_half_handler: Bottom Half handler function
*/
struct cam_sfe_bus {
void *bus_priv;
void *bus_priv;
struct cam_hw_ops hw_ops;
CAM_IRQ_HANDLER_TOP_HALF top_half_handler;
CAM_IRQ_HANDLER_BOTTOM_HALF bottom_half_handler;
@@ -67,17 +65,20 @@ struct cam_sfe_bus {
* @soc_info: Soc Information for the associated HW
* @hw_intf: HW Interface of HW to which this resource belongs
* @bus_hw_info: BUS HW info that contains details of BUS registers
* @sfe_irq_controller: SFE irq controller
* @sfe_bus: Pointer to sfe_bus structure which will be filled
* and returned on successful initialize
*
* @Return: 0: Success
* Non-zero: Failure
*/
int cam_sfe_bus_init(uint32_t bus_version,
int cam_sfe_bus_init(
uint32_t bus_version,
int bus_type,
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *bus_hw_info,
void *sfe_irq_controller,
struct cam_sfe_bus **sfe_bus);
/*

View File

@@ -7,9 +7,11 @@
#include "cam_io_util.h"
#include "cam_cdm_util.h"
#include "cam_sfe_hw_intf.h"
#include "cam_tasklet_util.h"
#include "cam_sfe_top.h"
#include "cam_debug_util.h"
#include "cam_sfe_soc.h"
#include "cam_sfe_core.h"
struct cam_sfe_core_cfg {
uint32_t mode_sel;
@@ -18,9 +20,12 @@ struct cam_sfe_core_cfg {
};
struct cam_sfe_top_common_data {
struct cam_hw_soc_info *soc_info;
struct cam_hw_intf *hw_intf;
struct cam_sfe_top_common_reg_offset *common_reg;
struct cam_hw_soc_info *soc_info;
struct cam_hw_intf *hw_intf;
struct cam_sfe_top_common_reg_offset *common_reg;
struct cam_irq_controller *sfe_irq_controller;
struct cam_sfe_top_irq_evt_payload evt_payload[CAM_SFE_EVT_MAX];
struct list_head free_payload_list;
};
struct cam_sfe_top_priv {
@@ -38,20 +43,45 @@ struct cam_sfe_top_priv {
CAM_SFE_TOP_IN_PORT_MAX];
struct cam_sfe_core_cfg core_cfg;
uint32_t sfe_debug_cfg;
spinlock_t spin_lock;
};
struct cam_sfe_path_data {
void __iomem *mem_base;
void *priv;
struct cam_hw_intf *hw_intf;
struct cam_sfe_top_priv *top_priv;
struct cam_sfe_top_common_reg_offset *common_reg;
struct cam_sfe_modules_common_reg_offset *modules_reg;
struct cam_sfe_path_common_reg_data *path_reg_data;
struct cam_hw_soc_info *soc_info;
uint32_t min_hblank_cnt;
int error_irq_handle;
int sof_eof_handle;
cam_hw_mgr_event_cb_func event_cb;
};
static const char *cam_sfe_top_res_id_to_string(
uint32_t res_id)
{
switch (res_id) {
case CAM_ISP_HW_SFE_IN_PIX:
return "PP";
case CAM_ISP_HW_SFE_IN_RDI0:
return "RDI0";
case CAM_ISP_HW_SFE_IN_RDI1:
return "RDI1";
case CAM_ISP_HW_SFE_IN_RDI2:
return "RDI2";
case CAM_ISP_HW_SFE_IN_RDI3:
return "RDI3";
case CAM_ISP_HW_SFE_IN_RDI4:
return "RDI4";
default:
return "";
}
}
static int cam_sfe_top_core_cfg(
struct cam_sfe_top_priv *top_priv,
void *cmd_args, uint32_t arg_size)
@@ -329,6 +359,7 @@ int cam_sfe_top_reserve(void *device_priv,
top_priv->in_rsrc[i].res_priv;
path_data->event_cb = args->event_cb;
path_data->priv = args->priv;
path_data->top_priv = top_priv;
CAM_DBG(CAM_SFE,
"SFE [%u] for rsrc: %u acquired",
top_priv->in_rsrc[i].hw_intf->hw_idx,
@@ -379,6 +410,244 @@ int cam_sfe_top_release(void *device_priv,
return 0;
}
static int cam_sfe_top_get_evt_payload(
struct cam_sfe_top_priv *top_priv,
struct cam_sfe_top_irq_evt_payload **evt_payload)
{
int rc = 0;
spin_lock(&top_priv->spin_lock);
if (list_empty(&top_priv->common_data.free_payload_list)) {
CAM_ERR_RATE_LIMIT(CAM_ISP, "No free CAMIF LITE event payload");
*evt_payload = NULL;
rc = -ENODEV;
goto done;
}
*evt_payload = list_first_entry(
&top_priv->common_data.free_payload_list,
struct cam_sfe_top_irq_evt_payload, list);
list_del_init(&(*evt_payload)->list);
done:
spin_unlock(&top_priv->spin_lock);
return rc;
}
static int cam_sfe_top_put_evt_payload(
struct cam_sfe_top_priv *top_priv,
struct cam_sfe_top_irq_evt_payload **evt_payload)
{
unsigned long flags;
if (!top_priv) {
CAM_ERR(CAM_SFE, "Invalid param core_info NULL");
return -EINVAL;
}
if (*evt_payload == NULL) {
CAM_ERR(CAM_SFE, "No payload to put");
return -EINVAL;
}
spin_lock_irqsave(&top_priv->spin_lock, flags);
list_add_tail(&(*evt_payload)->list,
&top_priv->common_data.free_payload_list);
*evt_payload = NULL;
spin_unlock_irqrestore(&top_priv->spin_lock, flags);
CAM_DBG(CAM_SFE, "Done");
return 0;
}
static void cam_sfe_top_print_debug_reg_info(
struct cam_sfe_path_data *path_data)
{
CAM_INFO(CAM_SFE,
"Debug0: 0x%x Debug1: 0x%x Debug2: 0x%x Debug3: 0x%x",
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_0),
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_1),
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_2),
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_3));
CAM_INFO(CAM_SFE,
"Debug4: 0x%x Debug5: 0x%x Debug6: 0x%x Debug7: 0x%x",
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_4),
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_5),
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_6),
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_7));
CAM_INFO(CAM_SFE,
"Debug8: 0x%x Debug9: 0x%x Debug10: 0x%x Debug11: 0x%x",
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_8),
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_9),
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_10),
cam_io_r_mb(path_data->mem_base +
path_data->common_reg->top_debug_11));
}
static int cam_sfe_top_handle_err_irq_top_half(
uint32_t evt_id,
struct cam_irq_th_payload *th_payload)
{
int rc = 0, i;
uint32_t irq_status = 0;
void __iomem *base = NULL;
struct cam_sfe_top_priv *top_priv;
struct cam_isp_resource_node *res;
struct cam_sfe_path_data *path_data;
struct cam_sfe_top_irq_evt_payload *evt_payload;
res = th_payload->handler_priv;
path_data = res->res_priv;
top_priv = path_data->priv;
CAM_DBG(CAM_SFE, "Top error IRQ Received");
irq_status = th_payload->evt_status_arr[0];
base = path_data->mem_base;
if (irq_status & path_data->path_reg_data->error_irq_mask) {
CAM_ERR(CAM_SFE,
"SFE Violation Detected irq_status: 0x%x",
irq_status);
cam_irq_controller_disable_irq(
top_priv->common_data.sfe_irq_controller,
path_data->error_irq_handle);
cam_irq_controller_clear_and_mask(evt_id,
top_priv->common_data.sfe_irq_controller);
}
rc = cam_sfe_top_get_evt_payload(top_priv, &evt_payload);
if (rc)
return rc;
for (i = 0; i < th_payload->num_registers; i++)
evt_payload->irq_reg_val[i] =
th_payload->evt_status_arr[i];
cam_isp_hw_get_timestamp(&evt_payload->ts);
evt_payload->violation_status =
cam_io_r(base +
top_priv->common_data.common_reg->violation_status);
th_payload->evt_payload_priv = evt_payload;
return rc;
}
static int cam_sfe_top_handle_irq_top_half(uint32_t evt_id,
struct cam_irq_th_payload *th_payload)
{
int rc = 0, i;
uint32_t irq_status = 0;
struct cam_sfe_top_priv *top_priv;
struct cam_isp_resource_node *res;
struct cam_sfe_path_data *path_data;
struct cam_sfe_top_irq_evt_payload *evt_payload;
res = th_payload->handler_priv;
path_data = res->res_priv;
top_priv = path_data->top_priv;
rc = cam_sfe_top_get_evt_payload(top_priv, &evt_payload);
if (rc)
return rc;
irq_status = th_payload->evt_status_arr[0];
CAM_DBG(CAM_SFE, "SFE top irq status: 0x%x",
irq_status);
for (i = 0; i < th_payload->num_registers; i++)
evt_payload->irq_reg_val[i] =
th_payload->evt_status_arr[i];
cam_isp_hw_get_timestamp(&evt_payload->ts);
th_payload->evt_payload_priv = evt_payload;
return rc;
}
static int cam_sfe_top_handle_irq_bottom_half(
void *handler_priv, void *evt_payload_priv)
{
int i;
uint32_t irq_status[CAM_SFE_IRQ_REGISTERS_MAX] = {0};
enum cam_sfe_hw_irq_status ret;
struct cam_isp_hw_event_info evt_info;
struct cam_isp_resource_node *res = handler_priv;
struct cam_sfe_path_data *path_data = res->res_priv;
struct cam_sfe_top_priv *top_priv = path_data->top_priv;
struct cam_sfe_top_irq_evt_payload *payload = evt_payload_priv;
for (i = 0; i < CAM_SFE_IRQ_REGISTERS_MAX; i++)
irq_status[i] = payload->irq_reg_val[i];
evt_info.hw_idx = res->hw_intf->hw_idx;
evt_info.res_id = res->res_id;
evt_info.res_type = res->res_type;
evt_info.reg_val = 0;
if (irq_status[0] &
path_data->path_reg_data->error_irq_mask) {
if (irq_status[0] & 0x4000)
CAM_ERR(CAM_SFE, "PP VIOLATION");
if (irq_status[0] & 0x8000)
CAM_ERR(CAM_SFE, "DIAG VIOLATION");
if (irq_status[0] & 0x10000)
CAM_ERR(CAM_SFE, "LINE SMOOTH VIOLATION");
CAM_INFO(CAM_SFE, "Violation status 0x%x",
payload->violation_status);
evt_info.err_type = CAM_SFE_IRQ_STATUS_VIOLATION;
cam_sfe_top_print_debug_reg_info(path_data);
if (path_data->event_cb)
path_data->event_cb(NULL,
CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info);
ret = CAM_SFE_IRQ_STATUS_VIOLATION;
}
/* To Do Debugfs entry to control the enablement */
if (irq_status[0] & path_data->path_reg_data->subscribe_irq_mask) {
if (irq_status[0] & path_data->path_reg_data->sof_irq_mask) {
CAM_INFO_RATE_LIMIT(CAM_SFE, "SFE:%d Received %s SOF",
evt_info.hw_idx,
cam_sfe_top_res_id_to_string(res->res_id));
}
if (irq_status[0] &
path_data->path_reg_data->eof_irq_mask) {
CAM_INFO_RATE_LIMIT(CAM_SFE, "SFE:%d Received %s EOF",
evt_info.hw_idx,
cam_sfe_top_res_id_to_string(res->res_id));
}
ret = CAM_SFE_IRQ_STATUS_SUCCESS;
}
/* To DO frame counter under debugfs */
CAM_DBG(CAM_SFE,
"SFE:%d SFE_DIAG_SENSOR_STATUS0: 0x%x SFE_DIAG_SENSOR_STATUS1: 0x%x",
evt_info.hw_idx,
cam_io_r(path_data->mem_base +
path_data->common_reg->diag_sensor_status_0),
cam_io_r(path_data->mem_base +
path_data->common_reg->diag_sensor_status_1));
cam_sfe_top_put_evt_payload(top_priv, &payload);
return ret;
}
int cam_sfe_top_start(
void *priv, void *start_args, uint32_t arg_size)
{
@@ -387,6 +656,8 @@ int cam_sfe_top_start(
struct cam_isp_resource_node *sfe_res;
struct cam_hw_info *hw_info = NULL;
struct cam_sfe_path_data *path_data;
uint32_t error_mask[CAM_SFE_IRQ_REGISTERS_MAX];
uint32_t sof_eof_mask[CAM_SFE_IRQ_REGISTERS_MAX];
if (!priv || !start_args) {
CAM_ERR(CAM_SFE, "Invalid args");
@@ -421,13 +692,54 @@ int cam_sfe_top_start(
path_data->common_reg->core_cfg));
/* Enable debug cfg registers */
cam_io_w_mb(path_data->path_reg_data->top_debug_cfg_en,
cam_io_w(path_data->path_reg_data->top_debug_cfg_en,
path_data->mem_base +
path_data->common_reg->top_debug_cfg);
/* Enable sensor diag info */
/* Enable SOF & EOF IRQ based on debug flag */
/* TO DO - debug fs to enable*/
cam_io_w(path_data->path_reg_data->enable_diagnostic_hw,
path_data->mem_base + path_data->common_reg->diag_config);
error_mask[0] = path_data->path_reg_data->error_irq_mask;
/* Enable error IRQ by default */
if (!path_data->error_irq_handle) {
path_data->error_irq_handle = cam_irq_controller_subscribe_irq(
top_priv->common_data.sfe_irq_controller,
CAM_IRQ_PRIORITY_0,
error_mask,
sfe_res,
cam_sfe_top_handle_err_irq_top_half,
cam_sfe_top_handle_irq_bottom_half,
sfe_res->tasklet_info,
&tasklet_bh_api);
if (path_data->error_irq_handle < 1) {
CAM_ERR(CAM_SFE, "Failed to subscribe Top IRQ");
path_data->error_irq_handle = 0;
return -EFAULT;
}
}
/* TO DO define the debugfs to enable/disable sof/eof irq */
if (!path_data->sof_eof_handle) {
sof_eof_mask[0] = path_data->path_reg_data->subscribe_irq_mask;
path_data->sof_eof_handle = cam_irq_controller_subscribe_irq(
top_priv->common_data.sfe_irq_controller,
CAM_IRQ_PRIORITY_1,
sof_eof_mask,
sfe_res,
cam_sfe_top_handle_irq_top_half,
cam_sfe_top_handle_irq_bottom_half,
sfe_res->tasklet_info,
&tasklet_bh_api);
if (path_data->sof_eof_handle < 1) {
CAM_ERR(CAM_SFE, "Failed to subscribe SOF/EOF IRQ");
path_data->sof_eof_handle = 0;
return -EFAULT;
}
}
sfe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
return 0;
@@ -439,6 +751,7 @@ int cam_sfe_top_stop(
int i;
struct cam_sfe_top_priv *top_priv;
struct cam_isp_resource_node *sfe_res;
struct cam_sfe_path_data *path_data;
if (!priv || !stop_args) {
CAM_ERR(CAM_SFE, "Invalid args");
@@ -447,6 +760,7 @@ int cam_sfe_top_stop(
top_priv = (struct cam_sfe_top_priv *)priv;
sfe_res = (struct cam_isp_resource_node *) stop_args;
path_data = sfe_res->res_priv;
if (sfe_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED ||
sfe_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE)
@@ -465,6 +779,18 @@ int cam_sfe_top_stop(
}
}
if (path_data->error_irq_handle > 0) {
cam_irq_controller_unsubscribe_irq(
top_priv->common_data.sfe_irq_controller,
path_data->error_irq_handle);
}
if (path_data->sof_eof_handle > 0) {
cam_irq_controller_unsubscribe_irq(
top_priv->common_data.sfe_irq_controller,
path_data->sof_eof_handle);
}
return 0;
}
@@ -473,6 +799,7 @@ int cam_sfe_top_init(
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *top_hw_info,
void *sfe_irq_controller,
struct cam_sfe_top **sfe_top_ptr)
{
int i, j, rc = 0;
@@ -497,6 +824,7 @@ int cam_sfe_top_init(
}
sfe_top->top_priv = top_priv;
top_priv->common_data.sfe_irq_controller = sfe_irq_controller;
if (sfe_top_hw_info->num_inputs > CAM_SFE_TOP_IN_PORT_MAX) {
CAM_ERR(CAM_SFE,
"Invalid number of input resources: %d max: %d",
@@ -590,6 +918,15 @@ int cam_sfe_top_init(
sfe_top->hw_ops.stop = cam_sfe_top_stop;
sfe_top->hw_ops.reserve = cam_sfe_top_reserve;
sfe_top->hw_ops.release = cam_sfe_top_release;
spin_lock_init(&top_priv->spin_lock);
INIT_LIST_HEAD(&top_priv->common_data.free_payload_list);
for (i = 0; i < CAM_SFE_EVT_MAX; i++) {
INIT_LIST_HEAD(&top_priv->common_data.evt_payload[i].list);
list_add_tail(&top_priv->common_data.evt_payload[i].list,
&top_priv->common_data.free_payload_list);
}
*sfe_top_ptr = sfe_top;
return rc;
@@ -625,6 +962,7 @@ int cam_sfe_top_deinit(
struct cam_sfe_top **sfe_top_ptr)
{
int i, rc = 0;
unsigned long flags;
struct cam_sfe_top *sfe_top;
struct cam_sfe_top_priv *top_priv;
@@ -651,6 +989,13 @@ int cam_sfe_top_deinit(
top_priv->common_data.hw_intf->hw_idx,
hw_version);
spin_lock_irqsave(&top_priv->spin_lock, flags);
INIT_LIST_HEAD(&top_priv->common_data.free_payload_list);
for (i = 0; i < CAM_SFE_EVT_MAX; i++)
INIT_LIST_HEAD(
&top_priv->common_data.evt_payload[i].list);
spin_unlock_irqrestore(&top_priv->spin_lock, flags);
for (i = 0; i < CAM_SFE_TOP_IN_PORT_MAX; i++) {
top_priv->in_rsrc[i].res_state =
CAM_ISP_RESOURCE_STATE_UNAVAILABLE;

View File

@@ -93,6 +93,7 @@ int cam_sfe_top_init(
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *top_hw_info,
void *sfe_irq_controller,
struct cam_sfe_top **sfe_top);
int cam_sfe_top_deinit(