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:

committed by
Gerrit - the friendly Code Review server

parent
1232bfaa25
commit
e4b180abaf
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -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",
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
/*
|
||||
|
@@ -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);
|
||||
|
||||
/*
|
||||
|
@@ -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;
|
||||
|
@@ -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(
|
||||
|
Reference in New Issue
Block a user