msm: camera: isp: Add support for custom CSID

This change adds support for custom csid HW and
programming of user defined interfaces (UDI) in
custom csid block.

CRs-Fixed: 2515662
Change-Id: I4b226b3a3787fbc3e56eb285e9a4dbd6d62edefa
Signed-off-by: Karthik Anantha Ram <kartanan@codeaurora.org>
このコミットが含まれているのは:
Karthik Anantha Ram
2019-08-26 16:21:55 -07:00
committed by Gerrit - the friendly Code Review server
コミット 7642380776
6個のファイルの変更737行の追加51行の削除

ファイルの表示

@@ -445,6 +445,11 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw)
soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr);
for (i = 0 ; i < csid_reg->cmn_reg->num_udis; i++)
cam_io_w_mb(csid_reg->cmn_reg->udi_irq_mask_all,
soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[i]->csid_udi_irq_clear_addr);
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
csid_reg->cmn_reg->csid_irq_cmd_addr);
@@ -571,7 +576,10 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw,
val |= CSID_PATH_INFO_RST_DONE;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->ppp_reg->csid_pxl_irq_mask_addr);
} else {
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) {
id = res->res_id;
if (!csid_reg->rdi_reg[id]) {
CAM_ERR(CAM_ISP, "CSID:%d RDI res not supported :%d",
@@ -591,6 +599,31 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw,
val |= CSID_PATH_INFO_RST_DONE;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) {
id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0;
if (!csid_reg->udi_reg[id]) {
CAM_ERR(CAM_ISP, "CSID:%d UDI res not supported :%d",
csid_hw->hw_intf->hw_idx,
res->res_id);
return -EINVAL;
}
reset_strb_addr =
csid_reg->udi_reg[id]->csid_udi_rst_strobes_addr;
complete =
&csid_hw->csid_udin_complete[id];
/* Enable path reset done interrupt */
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_irq_mask_addr);
val |= CSID_PATH_INFO_RST_DONE;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_irq_mask_addr);
} else {
CAM_ERR(CAM_ISP, "Invalid res_id %u", res->res_id);
return -EINVAL;
}
init_completion(complete);
@@ -623,10 +656,10 @@ end:
}
static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
struct cam_csid_hw_reserve_resource_args *cid_reserv)
{
int rc = 0, i;
int rc = 0, i, id;
struct cam_ife_csid_cid_data *cid_data;
uint32_t camera_hw_version;
uint32_t valid_vc_dt;
@@ -819,6 +852,20 @@ static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
goto end;
}
break;
case CAM_IFE_PIX_PATH_RES_UDI_0:
case CAM_IFE_PIX_PATH_RES_UDI_1:
case CAM_IFE_PIX_PATH_RES_UDI_2:
id = cid_reserv->res_id - CAM_IFE_PIX_PATH_RES_UDI_0;
if (csid_hw->udi_res[id].res_state !=
CAM_ISP_RESOURCE_STATE_AVAILABLE) {
CAM_ERR(CAM_ISP,
"CSID:%d UDI:%d resource not available",
csid_hw->hw_intf->hw_idx,
cid_reserv->res_id);
rc = -EINVAL;
goto end;
}
break;
default:
CAM_ERR(CAM_ISP, "CSID%d: Invalid csid path",
csid_hw->hw_intf->hw_idx);
@@ -894,11 +941,10 @@ end:
return rc;
}
static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
struct cam_csid_hw_reserve_resource_args *reserve)
{
int rc = 0, i;
int rc = 0, i, id;
struct cam_ife_csid_path_cfg *path_data;
struct cam_isp_resource_node *res;
@@ -998,6 +1044,28 @@ static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
res->res_id);
}
break;
case CAM_IFE_PIX_PATH_RES_UDI_0:
case CAM_IFE_PIX_PATH_RES_UDI_1:
case CAM_IFE_PIX_PATH_RES_UDI_2:
id = reserve->res_id - CAM_IFE_PIX_PATH_RES_UDI_0;
if (csid_hw->udi_res[id].res_state !=
CAM_ISP_RESOURCE_STATE_AVAILABLE) {
CAM_ERR(CAM_ISP,
"CSID:%d UDI:%d resource not available %d",
csid_hw->hw_intf->hw_idx,
reserve->res_id,
csid_hw->udi_res[id].res_state);
rc = -EINVAL;
goto end;
} else {
res = &csid_hw->udi_res[id];
CAM_DBG(CAM_ISP,
"CSID:%d UDI resource:%d acquire success",
csid_hw->hw_intf->hw_idx,
res->res_id);
}
break;
default:
CAM_ERR(CAM_ISP, "CSID:%d Invalid res id:%d",
@@ -1020,6 +1088,7 @@ static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
path_data->drop_enable = reserve->drop_enable;
path_data->horizontal_bin = reserve->in_port->horizontal_bin;
path_data->qcfa_bin = reserve->in_port->qcfa_bin;
path_data->num_bytes_out = reserve->in_port->num_bytes_out;
CAM_DBG(CAM_ISP,
"Res id: %d height:%d line_start %d line_stop %d crop_en %d",
@@ -1155,6 +1224,11 @@ static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw)
soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr);
for (i = 0; i < csid_reg->cmn_reg->num_udis; i++)
cam_io_w_mb(csid_reg->cmn_reg->udi_irq_mask_all,
soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[i]->csid_udi_irq_clear_addr);
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
csid_reg->cmn_reg->csid_irq_cmd_addr);
@@ -2185,6 +2259,207 @@ static int cam_ife_csid_init_config_rdi_path(
return rc;
}
static int cam_ife_csid_init_config_udi_path(
struct cam_ife_csid_hw *csid_hw,
struct cam_isp_resource_node *res)
{
int rc = 0;
struct cam_ife_csid_path_cfg *path_data;
const struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
uint32_t path_format = 0, plain_fmt = 0, val = 0, val1, id;
uint32_t format_measure_addr;
path_data = (struct cam_ife_csid_path_cfg *)res->res_priv;
csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info;
id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0;
if ((id >= CAM_IFE_CSID_UDI_MAX) || (!csid_reg->udi_reg[id])) {
CAM_ERR(CAM_ISP, "CSID:%d UDI:%d is not supported on HW",
csid_hw->hw_intf->hw_idx, id);
return -EINVAL;
}
rc = cam_ife_csid_get_format_rdi(path_data->in_format,
path_data->out_format, &path_format, &plain_fmt);
if (rc) {
CAM_ERR(CAM_ISP,
"Failed to get format in_format: %u out_format: %u rc: %d",
path_data->in_format, path_data->out_format, rc);
return rc;
}
/* if path decode format is payload only then UDI crop is not applied */
if (path_format == 0xF)
path_data->crop_enable = false;
/*
* UDI path config and enable the time stamp capture
* Enable the measurement blocks
*/
val = (path_data->vc << csid_reg->cmn_reg->vc_shift_val) |
(path_data->dt << csid_reg->cmn_reg->dt_shift_val) |
(path_data->cid << csid_reg->cmn_reg->dt_id_shift_val) |
(path_format << csid_reg->cmn_reg->fmt_shift_val) |
(plain_fmt << csid_reg->cmn_reg->plain_fmt_shit_val) |
(path_data->crop_enable <<
csid_reg->cmn_reg->crop_h_en_shift_val) |
(path_data->crop_enable <<
csid_reg->cmn_reg->crop_v_en_shift_val) |
(1 << 2) | 3;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_cfg0_addr);
/* select the post irq sub sample strobe for time stamp capture */
val1 = CSID_TIMESTAMP_STB_POST_IRQ;
/* select the num bytes out per cycle */
val1 |= (path_data->num_bytes_out <<
csid_reg->cmn_reg->num_bytes_out_shift_val);
cam_io_w_mb(val1, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_cfg1_addr);
/* Enable Error Detection */
if (csid_reg->udi_reg[id]->overflow_ctrl_en) {
val = csid_reg->udi_reg[id]->overflow_ctrl_en;
/* Overflow ctrl mode: 2 -> Detect overflow */
val |= 0x8;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_err_recovery_cfg0_addr);
}
/* set frame drop pattern to 0 and period to 1 */
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_frm_drop_period_addr);
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_frm_drop_pattern_addr);
/* set IRQ sum sabmple */
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_irq_subsample_period_addr);
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_irq_subsample_pattern_addr);
/* set pixel drop pattern to 0 and period to 1 */
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_rpp_pix_drop_pattern_addr);
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_rpp_pix_drop_period_addr);
/* set line drop pattern to 0 and period to 1 */
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_rpp_line_drop_pattern_addr);
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_rpp_line_drop_period_addr);
/* Configure the halt mode */
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_ctrl_addr);
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_cfg0_addr);
val |= (1 << csid_reg->cmn_reg->path_en_shift_val);
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO)
val |= csid_reg->cmn_reg->format_measure_en_val;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_cfg0_addr);
format_measure_addr =
csid_reg->udi_reg[id]->csid_udi_format_measure_cfg0_addr;
/* Enable the HBI/VBI counter */
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) {
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
format_measure_addr);
val |= csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask;
cam_io_w_mb(val,
soc_info->reg_map[0].mem_base + format_measure_addr);
}
/* configure the rx packet capture based on csid debug set */
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE)
val = ((1 <<
csid_reg->csi2_reg->csi2_capture_short_pkt_en_shift) |
(path_data->vc <<
csid_reg->csi2_reg->csi2_capture_short_pkt_vc_shift));
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE)
val |= ((1 <<
csid_reg->csi2_reg->csi2_capture_long_pkt_en_shift) |
(path_data->dt <<
csid_reg->csi2_reg->csi2_capture_long_pkt_dt_shift) |
(path_data->vc <<
csid_reg->csi2_reg->csi2_capture_long_pkt_vc_shift));
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE)
val |= ((1 <<
csid_reg->csi2_reg->csi2_capture_cphy_pkt_en_shift) |
(path_data->dt <<
csid_reg->csi2_reg->csi2_capture_cphy_pkt_dt_shift) |
(path_data->vc <<
csid_reg->csi2_reg->csi2_capture_cphy_pkt_vc_shift));
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_capture_ctrl_addr);
res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
return rc;
}
static int cam_ife_csid_deinit_udi_path(
struct cam_ife_csid_hw *csid_hw,
struct cam_isp_resource_node *res)
{
int rc = 0;
uint32_t id, val, format_measure_addr;
const struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info;
id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0;
if ((res->res_id < CAM_IFE_PIX_PATH_RES_UDI_0) ||
(res->res_id > CAM_IFE_PIX_PATH_RES_UDI_2) ||
(res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) ||
(!csid_reg->udi_reg[id])) {
CAM_ERR(CAM_ISP, "CSID:%d Invalid res id%d state:%d",
csid_hw->hw_intf->hw_idx, res->res_id,
res->res_state);
return -EINVAL;
}
/* Disable Error Recovery */
if (csid_reg->udi_reg[id]->overflow_ctrl_en) {
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_err_recovery_cfg0_addr);
}
format_measure_addr =
csid_reg->udi_reg[id]->csid_udi_format_measure_cfg0_addr;
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_HBI_VBI_INFO) {
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_cfg0_addr);
val &= ~csid_reg->cmn_reg->format_measure_en_val;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_cfg0_addr);
/* Disable the HBI/VBI counter */
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
format_measure_addr);
val &= ~csid_reg->cmn_reg->measure_en_hbi_vbi_cnt_mask;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
format_measure_addr);
}
res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
return rc;
}
static int cam_ife_csid_deinit_rdi_path(
struct cam_ife_csid_hw *csid_hw,
struct cam_isp_resource_node *res)
@@ -2284,6 +2559,56 @@ static int cam_ife_csid_enable_rdi_path(
return 0;
}
static int cam_ife_csid_enable_udi_path(
struct cam_ife_csid_hw *csid_hw,
struct cam_isp_resource_node *res)
{
const struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
uint32_t id, val;
csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info;
id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0;
if ((res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) ||
(res->res_id > CAM_IFE_PIX_PATH_RES_UDI_2) ||
(res->res_id < CAM_IFE_PIX_PATH_RES_UDI_0) ||
(!csid_reg->udi_reg[id])) {
CAM_ERR(CAM_ISP,
"CSID:%d invalid res type:%d res_id:%d state%d",
csid_hw->hw_intf->hw_idx,
res->res_type, res->res_id, res->res_state);
return -EINVAL;
}
/*resume at frame boundary */
cam_io_w_mb(CAM_CSID_RESUME_AT_FRAME_BOUNDARY,
soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_ctrl_addr);
/* Enable the required UDI interrupts */
val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
if (csid_reg->udi_reg[id]->ccif_violation_en)
val |= CSID_PATH_ERROR_CCIF_VIOLATION;
if (csid_reg->udi_reg[id]->overflow_ctrl_en)
val |= CSID_PATH_OVERFLOW_RECOVERY;
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)
val |= CSID_PATH_INFO_INPUT_SOF;
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)
val |= CSID_PATH_INFO_INPUT_EOF;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_irq_mask_addr);
res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
return 0;
}
static int cam_ife_csid_disable_rdi_path(
struct cam_ife_csid_hw *csid_hw,
@@ -2347,11 +2672,74 @@ static int cam_ife_csid_disable_rdi_path(
return rc;
}
static int cam_ife_csid_disable_udi_path(
struct cam_ife_csid_hw *csid_hw,
struct cam_isp_resource_node *res,
enum cam_ife_csid_halt_cmd stop_cmd)
{
int rc = 0;
uint32_t id, val = 0;
const struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info;
id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0;
if ((res->res_id > CAM_IFE_PIX_PATH_RES_UDI_2) ||
(res->res_id < CAM_IFE_PIX_PATH_RES_UDI_0) ||
(!csid_reg->udi_reg[id])) {
CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d Invalid res id%d",
csid_hw->hw_intf->hw_idx, res->res_id);
return -EINVAL;
}
if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW ||
res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
"CSID:%d Res:%d already in stopped state:%d",
csid_hw->hw_intf->hw_idx,
res->res_id, res->res_state);
return rc;
}
if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
"CSID:%d Res:%d Invalid res_state%d",
csid_hw->hw_intf->hw_idx, res->res_id,
res->res_state);
return -EINVAL;
}
if (stop_cmd != CAM_CSID_HALT_AT_FRAME_BOUNDARY &&
stop_cmd != CAM_CSID_HALT_IMMEDIATELY) {
CAM_ERR(CAM_ISP, "CSID:%d un supported stop command:%d",
csid_hw->hw_intf->hw_idx, stop_cmd);
return -EINVAL;
}
CAM_DBG(CAM_ISP, "CSID:%d res_id:%d",
csid_hw->hw_intf->hw_idx, res->res_id);
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_irq_mask_addr);
/* Halt the UDI path */
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_ctrl_addr);
val &= ~0x3;
val |= stop_cmd;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[id]->csid_udi_ctrl_addr);
return rc;
}
static int cam_ife_csid_poll_stop_status(
struct cam_ife_csid_hw *csid_hw,
uint32_t res_mask)
{
int rc = 0;
int rc = 0, id;
uint32_t csid_status_addr = 0, val = 0, res_id = 0;
const struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
@@ -2370,9 +2758,22 @@ static int cam_ife_csid_poll_stop_status(
} else if (res_id == CAM_IFE_PIX_PATH_RES_PPP) {
csid_status_addr =
csid_reg->ppp_reg->csid_pxl_status_addr;
} else {
} else if (res_id == CAM_IFE_PIX_PATH_RES_RDI_0 ||
res_id == CAM_IFE_PIX_PATH_RES_RDI_1 ||
res_id == CAM_IFE_PIX_PATH_RES_RDI_2 ||
res_id == CAM_IFE_PIX_PATH_RES_RDI_3) {
csid_status_addr =
csid_reg->rdi_reg[res_id]->csid_rdi_status_addr;
} else if (res_id == CAM_IFE_PIX_PATH_RES_UDI_0 ||
res_id == CAM_IFE_PIX_PATH_RES_UDI_1 ||
res_id == CAM_IFE_PIX_PATH_RES_UDI_2) {
id = res_id - CAM_IFE_PIX_PATH_RES_UDI_0;
csid_status_addr =
csid_reg->udi_reg[id]->csid_udi_status_addr;
} else {
CAM_ERR(CAM_ISP, "Invalid res_id: %u", res_id);
rc = -EINVAL;
break;
}
CAM_DBG(CAM_ISP, "start polling CSID:%d res_id:%d",
@@ -2400,8 +2801,10 @@ static int cam_ife_csid_get_hbi_vbi(
struct cam_isp_resource_node *res)
{
uint32_t hbi, vbi;
int32_t id;
const struct cam_ife_csid_reg_offset *csid_reg;
const struct cam_ife_csid_rdi_reg_offset *rdi_reg;
const struct cam_ife_csid_udi_reg_offset *udi_reg;
struct cam_hw_soc_info *soc_info;
csid_reg = csid_hw->csid_info->csid_reg;
@@ -2432,12 +2835,27 @@ static int cam_ife_csid_get_hbi_vbi(
csid_reg->ppp_reg->csid_pxl_format_measure1_addr);
vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->ppp_reg->csid_pxl_format_measure2_addr);
} else {
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) {
rdi_reg = csid_reg->rdi_reg[res->res_id];
hbi = cam_io_r_mb(soc_info->reg_map[0].mem_base +
rdi_reg->csid_rdi_format_measure1_addr);
vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base +
rdi_reg->csid_rdi_format_measure2_addr);
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) {
id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0;
udi_reg = csid_reg->udi_reg[id];
hbi = cam_io_r_mb(soc_info->reg_map[0].mem_base +
udi_reg->csid_udi_format_measure1_addr);
vbi = cam_io_r_mb(soc_info->reg_map[0].mem_base +
udi_reg->csid_udi_format_measure2_addr);
} else {
CAM_ERR(CAM_ISP, "Invalid res_id: %u", res->res_id);
return -EINVAL;
}
CAM_INFO_RATE_LIMIT(CAM_ISP,
@@ -2448,7 +2866,6 @@ static int cam_ife_csid_get_hbi_vbi(
return 0;
}
static int cam_ife_csid_get_time_stamp(
struct cam_ife_csid_hw *csid_hw, void *cmd_args)
{
@@ -2457,6 +2874,7 @@ static int cam_ife_csid_get_time_stamp(
const struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
const struct cam_ife_csid_rdi_reg_offset *rdi_reg;
const struct cam_ife_csid_udi_reg_offset *udi_reg;
struct timespec64 ts;
uint32_t time_32, id;
@@ -2494,7 +2912,10 @@ static int cam_ife_csid_get_time_stamp(
time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32;
time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->ppp_reg->csid_pxl_timestamp_curr0_sof_addr);
} else {
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) {
id = res->res_id;
rdi_reg = csid_reg->rdi_reg[id];
time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
@@ -2504,6 +2925,21 @@ static int cam_ife_csid_get_time_stamp(
time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
rdi_reg->csid_rdi_timestamp_curr0_sof_addr);
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) {
id = res->res_id - CAM_IFE_PIX_PATH_RES_UDI_0;
udi_reg = csid_reg->udi_reg[id];
time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
udi_reg->csid_udi_timestamp_curr1_sof_addr);
time_stamp->time_stamp_val = (uint64_t) time_32;
time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32;
time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
udi_reg->csid_udi_timestamp_curr0_sof_addr);
} else {
CAM_ERR(CAM_ISP, "Invalid res_id: %u", res->res_id);
return -EINVAL;
}
time_stamp->time_stamp_val |= (uint64_t) time_32;
@@ -2532,7 +2968,7 @@ static int cam_ife_csid_set_csid_debug(struct cam_ife_csid_hw *csid_hw,
return 0;
}
static int cam_ife_csid_get_hw_caps(void *hw_priv,
int cam_ife_csid_get_hw_caps(void *hw_priv,
void *get_hw_cap_args, uint32_t arg_size)
{
int rc = 0;
@@ -2567,7 +3003,7 @@ static int cam_ife_csid_get_hw_caps(void *hw_priv,
return rc;
}
static int cam_ife_csid_reset(void *hw_priv,
int cam_ife_csid_reset(void *hw_priv,
void *reset_args, uint32_t arg_size)
{
struct cam_ife_csid_hw *csid_hw;
@@ -2602,7 +3038,7 @@ static int cam_ife_csid_reset(void *hw_priv,
return rc;
}
static int cam_ife_csid_reserve(void *hw_priv,
int cam_ife_csid_reserve(void *hw_priv,
void *reserve_args, uint32_t arg_size)
{
int rc = 0;
@@ -2641,7 +3077,7 @@ static int cam_ife_csid_reserve(void *hw_priv,
return rc;
}
static int cam_ife_csid_release(void *hw_priv,
int cam_ife_csid_release(void *hw_priv,
void *release_args, uint32_t arg_size)
{
int rc = 0;
@@ -2762,7 +3198,7 @@ static int cam_ife_csid_reset_retain_sw_reg(
return rc;
}
static int cam_ife_csid_init_hw(void *hw_priv,
int cam_ife_csid_init_hw(void *hw_priv,
void *init_args, uint32_t arg_size)
{
int rc = 0;
@@ -2819,10 +3255,22 @@ static int cam_ife_csid_init_hw(void *hw_priv,
break;
case CAM_ISP_RESOURCE_PIX_PATH:
if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP ||
res->res_id == CAM_IFE_PIX_PATH_RES_PPP)
res->res_id == CAM_IFE_PIX_PATH_RES_PPP) {
rc = cam_ife_csid_init_config_pxl_path(csid_hw, res);
else
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) {
rc = cam_ife_csid_init_config_rdi_path(csid_hw, res);
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) {
rc = cam_ife_csid_init_config_udi_path(csid_hw, res);
} else {
CAM_ERR(CAM_ISP, "Invalid res_id: %u", res->res_id);
rc = -EINVAL;
goto end;
}
break;
default:
@@ -2847,7 +3295,7 @@ end:
return rc;
}
static int cam_ife_csid_deinit_hw(void *hw_priv,
int cam_ife_csid_deinit_hw(void *hw_priv,
void *deinit_args, uint32_t arg_size)
{
int rc = 0;
@@ -2882,10 +3330,22 @@ static int cam_ife_csid_deinit_hw(void *hw_priv,
case CAM_ISP_RESOURCE_PIX_PATH:
CAM_DBG(CAM_ISP, "De-Init Pix Path: %d\n", res->res_id);
if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP ||
res->res_id == CAM_IFE_PIX_PATH_RES_PPP)
res->res_id == CAM_IFE_PIX_PATH_RES_PPP) {
rc = cam_ife_csid_deinit_pxl_path(csid_hw, res);
else
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) {
rc = cam_ife_csid_deinit_rdi_path(csid_hw, res);
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) {
rc = cam_ife_csid_deinit_udi_path(csid_hw, res);
} else {
CAM_ERR(CAM_ISP, "Invalid res_id: %u", res->res_id);
rc = -EINVAL;
goto end;
}
break;
default:
@@ -2905,7 +3365,7 @@ end:
return rc;
}
static int cam_ife_csid_start(void *hw_priv, void *start_args,
int cam_ife_csid_start(void *hw_priv, void *start_args,
uint32_t arg_size)
{
int rc = 0;
@@ -2950,10 +3410,23 @@ static int cam_ife_csid_start(void *hw_priv, void *start_args,
break;
case CAM_ISP_RESOURCE_PIX_PATH:
if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP ||
res->res_id == CAM_IFE_PIX_PATH_RES_PPP)
res->res_id == CAM_IFE_PIX_PATH_RES_PPP) {
rc = cam_ife_csid_enable_pxl_path(csid_hw, res);
else
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) {
rc = cam_ife_csid_enable_rdi_path(csid_hw, res);
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) {
rc = cam_ife_csid_enable_udi_path(csid_hw, res);
} else {
CAM_ERR(CAM_ISP, "Invalid res_id: %u", res->res_id);
rc = -EINVAL;
goto end;
}
break;
default:
CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
@@ -2965,7 +3438,7 @@ end:
return rc;
}
static int cam_ife_csid_stop(void *hw_priv,
int cam_ife_csid_stop(void *hw_priv,
void *stop_args, uint32_t arg_size)
{
int rc = 0;
@@ -3008,12 +3481,25 @@ static int cam_ife_csid_stop(void *hw_priv,
case CAM_ISP_RESOURCE_PIX_PATH:
res_mask |= (1 << res->res_id);
if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP ||
res->res_id == CAM_IFE_PIX_PATH_RES_PPP)
res->res_id == CAM_IFE_PIX_PATH_RES_PPP) {
rc = cam_ife_csid_disable_pxl_path(csid_hw,
res, csid_stop->stop_cmd);
else
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_RDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_2 ||
res->res_id == CAM_IFE_PIX_PATH_RES_RDI_3) {
rc = cam_ife_csid_disable_rdi_path(csid_hw,
res, csid_stop->stop_cmd);
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_UDI_0 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_1 ||
res->res_id == CAM_IFE_PIX_PATH_RES_UDI_2) {
rc = cam_ife_csid_disable_udi_path(csid_hw,
res, csid_stop->stop_cmd);
} else {
CAM_ERR(CAM_ISP, "Invalid res_id: %u",
res->res_id);
return -EINVAL;
}
break;
default:
@@ -3038,7 +3524,7 @@ static int cam_ife_csid_stop(void *hw_priv,
}
static int cam_ife_csid_read(void *hw_priv,
int cam_ife_csid_read(void *hw_priv,
void *read_args, uint32_t arg_size)
{
CAM_ERR(CAM_ISP, "CSID: un supported");
@@ -3046,7 +3532,7 @@ static int cam_ife_csid_read(void *hw_priv,
return -EINVAL;
}
static int cam_ife_csid_write(void *hw_priv,
int cam_ife_csid_write(void *hw_priv,
void *write_args, uint32_t arg_size)
{
CAM_ERR(CAM_ISP, "CSID: un supported");
@@ -3107,6 +3593,21 @@ static int cam_ife_csid_sof_irq_debug(
}
}
for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) {
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[i]->csid_udi_irq_mask_addr);
if (val) {
if (sof_irq_enable)
val |= CSID_PATH_INFO_INPUT_SOF;
else
val &= ~CSID_PATH_INFO_INPUT_SOF;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[i]->csid_udi_irq_mask_addr);
val = 0;
}
}
if (sof_irq_enable) {
csid_hw->csid_debug |= CSID_DEBUG_ENABLE_SOF_IRQ;
csid_hw->sof_irq_triggered = true;
@@ -3210,7 +3711,8 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
const struct cam_ife_csid_reg_offset *csid_reg;
const struct cam_ife_csid_csi2_rx_reg_offset *csi2_reg;
uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0;
uint32_t irq_status_rdi[4] = {0, 0, 0, 0};
uint32_t irq_status_rdi[CAM_IFE_CSID_RDI_MAX] = {0, 0, 0, 0};
uint32_t irq_status_udi[CAM_IFE_CSID_UDI_MAX] = {0, 0, 0};
uint32_t val, irq_status_ppp = 0;
bool fatal_err_detected = false;
uint32_t sof_irq_debug_en = 0;
@@ -3244,10 +3746,21 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
irq_status_ppp = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->ppp_reg->csid_pxl_irq_status_addr);
if (csid_reg->cmn_reg->num_rdis <= CAM_IFE_CSID_RDI_MAX) {
for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) {
irq_status_rdi[i] =
cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[i]->csid_rdi_irq_status_addr);
}
}
for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++)
irq_status_rdi[i] = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[i]->csid_rdi_irq_status_addr);
if (csid_reg->cmn_reg->num_udis <= CAM_IFE_CSID_UDI_MAX) {
for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) {
irq_status_udi[i] =
cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[i]->csid_udi_irq_status_addr);
}
}
/* clear */
cam_io_w_mb(irq_status_rx, soc_info->reg_map[0].mem_base +
@@ -3260,10 +3773,22 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
cam_io_w_mb(irq_status_ppp, soc_info->reg_map[0].mem_base +
csid_reg->ppp_reg->csid_pxl_irq_clear_addr);
for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) {
cam_io_w_mb(irq_status_rdi[i], soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr);
if (csid_reg->cmn_reg->num_rdis <= CAM_IFE_CSID_RDI_MAX) {
for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) {
cam_io_w_mb(irq_status_rdi[i],
soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr);
}
}
if (csid_reg->cmn_reg->num_udis <= CAM_IFE_CSID_UDI_MAX) {
for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) {
cam_io_w_mb(irq_status_udi[i],
soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[i]->csid_udi_irq_clear_addr);
}
}
cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
csid_reg->cmn_reg->csid_irq_cmd_addr);
@@ -3271,9 +3796,12 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", irq_status_rx);
CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", irq_status_ipp);
CAM_DBG(CAM_ISP, "irq_status_ppp = 0x%x", irq_status_ppp);
CAM_DBG(CAM_ISP, "irq_status_rdi0= 0x%x", irq_status_rdi[0]);
CAM_DBG(CAM_ISP, "irq_status_rdi1= 0x%x", irq_status_rdi[1]);
CAM_DBG(CAM_ISP, "irq_status_rdi2= 0x%x", irq_status_rdi[2]);
CAM_DBG(CAM_ISP,
"irq_status_rdi0= 0x%x irq_status_rdi1= 0x%x irq_status_rdi2= 0x%x",
irq_status_rdi[0], irq_status_rdi[1], irq_status_rdi[2]);
CAM_DBG(CAM_ISP,
"irq_status_udi0= 0x%x irq_status_udi1= 0x%x irq_status_udi2= 0x%x",
irq_status_udi[0], irq_status_udi[1], irq_status_udi[2]);
if (irq_status_rx & BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) {
CAM_DBG(CAM_ISP, "csi rx reset complete");
@@ -3578,6 +4106,46 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
}
}
for (i = 0; i < csid_reg->cmn_reg->num_udis; i++) {
if (irq_status_udi[i] &
BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) {
CAM_DBG(CAM_ISP, "CSID UDI%d reset complete", i);
complete(&csid_hw->csid_udin_complete[i]);
}
if ((irq_status_udi[i] & CSID_PATH_INFO_INPUT_SOF) &&
(csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)) {
CAM_INFO_RATE_LIMIT(CAM_ISP,
"CSID UDI:%d SOF received", i);
if (csid_hw->sof_irq_triggered)
csid_hw->irq_debug_cnt++;
}
if ((irq_status_udi[i] & CSID_PATH_INFO_INPUT_EOF) &&
(csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ))
CAM_INFO_RATE_LIMIT(CAM_ISP,
"CSID UDI:%d EOF received", i);
if ((irq_status_udi[i] & CSID_PATH_ERROR_CCIF_VIOLATION))
CAM_WARN_RATE_LIMIT(CAM_ISP,
"CSID UDI :%d CCIF violation", i);
if ((irq_status_udi[i] & CSID_PATH_OVERFLOW_RECOVERY))
CAM_WARN_RATE_LIMIT(CAM_ISP,
"CSID UDI :%d Overflow due to back pressure",
i);
if (irq_status_udi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
"CSID:%d UDI fifo over flow",
csid_hw->hw_intf->hw_idx);
/* Stop UDI path immediately */
cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
soc_info->reg_map[0].mem_base +
csid_reg->udi_reg[i]->csid_udi_ctrl_addr);
}
}
if (csid_hw->irq_debug_cnt >= CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX) {
cam_ife_csid_sof_irq_debug(csid_hw, &sof_irq_debug_en);
csid_hw->irq_debug_cnt = 0;
@@ -3588,7 +4156,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
}
int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
uint32_t csid_idx)
uint32_t csid_idx, bool is_custom)
{
int rc = -EINVAL;
uint32_t i;
@@ -3627,9 +4195,11 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
for (i = 0; i < CAM_IFE_CSID_RDI_MAX; i++)
init_completion(&ife_csid_hw->csid_rdin_complete[i]);
for (i = 0; i < CAM_IFE_CSID_UDI_MAX; i++)
init_completion(&ife_csid_hw->csid_udin_complete[i]);
rc = cam_ife_csid_init_soc_resources(&ife_csid_hw->hw_info->soc_info,
cam_ife_csid_irq, ife_csid_hw);
cam_ife_csid_irq, ife_csid_hw, is_custom);
if (rc < 0) {
CAM_ERR(CAM_ISP, "CSID:%d Failed to init_soc", csid_idx);
goto err;
@@ -3651,7 +4221,8 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
ife_csid_hw->hw_intf->hw_ops.process_cmd = cam_ife_csid_process_cmd;
num_paths = ife_csid_hw->csid_info->csid_reg->cmn_reg->num_pix +
ife_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis;
ife_csid_hw->csid_info->csid_reg->cmn_reg->num_rdis +
ife_csid_hw->csid_info->csid_reg->cmn_reg->num_udis;
/* Initialize the CID resource */
for (i = 0; i < num_paths; i++) {
ife_csid_hw->cid_res[i].res_type = CAM_ISP_RESOURCE_CID;
@@ -3721,6 +4292,27 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
ife_csid_hw->rdi_res[i].res_priv = path_data;
}
/* Initialize the UDI resource */
for (i = 0; i < ife_csid_hw->csid_info->csid_reg->cmn_reg->num_udis;
i++) {
/* res type is from UDI0 to UDI3 */
ife_csid_hw->udi_res[i].res_type =
CAM_ISP_RESOURCE_PIX_PATH;
ife_csid_hw->udi_res[i].res_id = i +
CAM_IFE_PIX_PATH_RES_UDI_0;
ife_csid_hw->udi_res[i].res_state =
CAM_ISP_RESOURCE_STATE_AVAILABLE;
ife_csid_hw->udi_res[i].hw_intf = ife_csid_hw->hw_intf;
path_data = kzalloc(sizeof(*path_data),
GFP_KERNEL);
if (!path_data) {
rc = -ENOMEM;
goto err;
}
ife_csid_hw->udi_res[i].res_priv = path_data;
}
ife_csid_hw->csid_debug = 0;
ife_csid_hw->error_irq_count = 0;
@@ -3734,6 +4326,11 @@ err:
i++)
kfree(ife_csid_hw->rdi_res[i].res_priv);
for (i = 0; i <
ife_csid_hw->csid_info->csid_reg->cmn_reg->num_udis;
i++)
kfree(ife_csid_hw->udi_res[i].res_priv);
for (i = 0; i < CAM_IFE_CSID_CID_MAX; i++)
kfree(ife_csid_hw->cid_res[i].res_priv);
@@ -3741,7 +4338,7 @@ err:
return rc;
}
EXPORT_SYMBOL(cam_ife_csid_hw_probe_init);
int cam_ife_csid_hw_deinit(struct cam_ife_csid_hw *ife_csid_hw)
{
@@ -3761,6 +4358,11 @@ int cam_ife_csid_hw_deinit(struct cam_ife_csid_hw *ife_csid_hw)
i++) {
kfree(ife_csid_hw->rdi_res[i].res_priv);
}
for (i = 0; i <
ife_csid_hw->csid_info->csid_reg->cmn_reg->num_udis;
i++) {
kfree(ife_csid_hw->udi_res[i].res_priv);
}
for (i = 0; i < CAM_IFE_CSID_CID_MAX; i++)
kfree(ife_csid_hw->cid_res[i].res_priv);
@@ -3768,3 +4370,4 @@ int cam_ife_csid_hw_deinit(struct cam_ife_csid_hw *ife_csid_hw)
return 0;
}
EXPORT_SYMBOL(cam_ife_csid_hw_deinit);

ファイルの表示

@@ -9,6 +9,7 @@
#include "cam_hw.h"
#include "cam_ife_csid_hw_intf.h"
#include "cam_ife_csid_soc.h"
#include "cam_ife_csid_core.h"
#define CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED BIT(0)
#define CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED BIT(1)
@@ -192,6 +193,59 @@ struct cam_ife_csid_rdi_reg_offset {
uint32_t overflow_ctrl_en;
};
struct cam_ife_csid_udi_reg_offset {
uint32_t csid_udi_irq_status_addr;
uint32_t csid_udi_irq_mask_addr;
uint32_t csid_udi_irq_clear_addr;
uint32_t csid_udi_irq_set_addr;
/* UDI N register address */
uint32_t csid_udi_cfg0_addr;
uint32_t csid_udi_cfg1_addr;
uint32_t csid_udi_ctrl_addr;
uint32_t csid_udi_frm_drop_pattern_addr;
uint32_t csid_udi_frm_drop_period_addr;
uint32_t csid_udi_irq_subsample_pattern_addr;
uint32_t csid_udi_irq_subsample_period_addr;
uint32_t csid_udi_rpp_hcrop_addr;
uint32_t csid_udi_rpp_vcrop_addr;
uint32_t csid_udi_rpp_pix_drop_pattern_addr;
uint32_t csid_udi_rpp_pix_drop_period_addr;
uint32_t csid_udi_rpp_line_drop_pattern_addr;
uint32_t csid_udi_rpp_line_drop_period_addr;
uint32_t csid_udi_yuv_chroma_conversion_addr;
uint32_t csid_udi_rst_strobes_addr;
uint32_t csid_udi_status_addr;
uint32_t csid_udi_misr_val0_addr;
uint32_t csid_udi_misr_val1_addr;
uint32_t csid_udi_misr_val2_addr;
uint32_t csid_udi_misr_val3_addr;
uint32_t csid_udi_format_measure_cfg0_addr;
uint32_t csid_udi_format_measure_cfg1_addr;
uint32_t csid_udi_format_measure0_addr;
uint32_t csid_udi_format_measure1_addr;
uint32_t csid_udi_format_measure2_addr;
uint32_t csid_udi_timestamp_curr0_sof_addr;
uint32_t csid_udi_timestamp_curr1_sof_addr;
uint32_t csid_udi_timestamp_prev0_sof_addr;
uint32_t csid_udi_timestamp_prev1_sof_addr;
uint32_t csid_udi_timestamp_curr0_eof_addr;
uint32_t csid_udi_timestamp_curr1_eof_addr;
uint32_t csid_udi_timestamp_prev0_eof_addr;
uint32_t csid_udi_timestamp_prev1_eof_addr;
uint32_t csid_udi_err_recovery_cfg0_addr;
uint32_t csid_udi_err_recovery_cfg1_addr;
uint32_t csid_udi_err_recovery_cfg2_addr;
uint32_t csid_udi_multi_vcdt_cfg0_addr;
uint32_t csid_udi_byte_cntr_ping_addr;
uint32_t csid_udi_byte_cntr_pong_addr;
/* configuration */
uint32_t packing_format;
uint32_t ccif_violation_en;
uint32_t overflow_ctrl_en;
};
struct cam_ife_csid_csi2_rx_reg_offset {
uint32_t csid_csi2_rx_irq_status_addr;
uint32_t csid_csi2_rx_irq_mask_addr;
@@ -288,6 +342,7 @@ struct cam_ife_csid_common_reg_offset {
uint32_t major_version;
uint32_t minor_version;
uint32_t version_incr;
uint32_t num_udis;
uint32_t num_rdis;
uint32_t num_pix;
uint32_t num_ppp;
@@ -310,8 +365,10 @@ struct cam_ife_csid_common_reg_offset {
uint32_t ipp_irq_mask_all;
uint32_t rdi_irq_mask_all;
uint32_t ppp_irq_mask_all;
uint32_t udi_irq_mask_all;
uint32_t measure_en_hbi_vbi_cnt_mask;
uint32_t format_measure_en_val;
uint32_t num_bytes_out_shift_val;
};
/**
@@ -320,7 +377,9 @@ struct cam_ife_csid_common_reg_offset {
* @cmn_reg: csid common registers info
* @ipp_reg: ipp register offset information
* @ppp_reg: ppp register offset information
* @rdi_reg: rdi register offser information
* @rdi_reg: rdi register offset information
* @udi_reg: udi register offset information
* @tpg_reg: tpg register offset information
*
*/
struct cam_ife_csid_reg_offset {
@@ -329,6 +388,7 @@ struct cam_ife_csid_reg_offset {
const struct cam_ife_csid_pxl_reg_offset *ipp_reg;
const struct cam_ife_csid_pxl_reg_offset *ppp_reg;
const struct cam_ife_csid_rdi_reg_offset *rdi_reg[CAM_IFE_CSID_RDI_MAX];
const struct cam_ife_csid_udi_reg_offset *udi_reg[CAM_IFE_CSID_UDI_MAX];
const struct cam_ife_csid_csi2_tpg_reg_offset *tpg_reg;
};
@@ -427,6 +487,7 @@ struct cam_ife_csid_cid_data {
* @master_idx: For Slave reservation, Give master IFE instance Index.
* Slave will synchronize with master Start and stop operations
* @clk_rate Clock rate
* @num_bytes_out: Number of output bytes per cycle
*
*/
struct cam_ife_csid_path_cfg {
@@ -451,6 +512,7 @@ struct cam_ife_csid_path_cfg {
uint64_t clk_rate;
uint32_t horizontal_bin;
uint32_t qcfa_bin;
uint32_t num_bytes_out;
};
/**
@@ -468,12 +530,14 @@ struct cam_ife_csid_path_cfg {
* @ipp_res: image pixel path resource
* @ppp_res: phase pxl path resource
* @rdi_res: raw dump image path resources
* @udi_res: udi path resources
* @cid_res: cid resources state
* @csid_top_reset_complete: csid top reset completion
* @csid_csi2_reset_complete: csi2 reset completion
* @csid_ipp_reset_complete: ipp reset completion
* @csid_ppp_complete: ppp reset completion
* @csid_rdin_reset_complete: rdi n completion
* @csid_udin_reset_complete: udi n completion
* @csid_debug: csid debug information to enable the SOT, EOT,
* SOF, EOF, measure etc in the csid hw
* @clk_rate Clock rate
@@ -499,12 +563,14 @@ struct cam_ife_csid_hw {
struct cam_isp_resource_node ipp_res;
struct cam_isp_resource_node ppp_res;
struct cam_isp_resource_node rdi_res[CAM_IFE_CSID_RDI_MAX];
struct cam_isp_resource_node udi_res[CAM_IFE_CSID_UDI_MAX];
struct cam_isp_resource_node cid_res[CAM_IFE_CSID_CID_MAX];
struct completion csid_top_complete;
struct completion csid_csi2_complete;
struct completion csid_ipp_complete;
struct completion csid_ppp_complete;
struct completion csid_rdin_complete[CAM_IFE_CSID_RDI_MAX];
struct completion csid_udin_complete[CAM_IFE_CSID_UDI_MAX];
uint64_t csid_debug;
uint64_t clk_rate;
bool sof_irq_triggered;
@@ -517,8 +583,14 @@ struct cam_ife_csid_hw {
};
int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
uint32_t csid_idx);
uint32_t csid_idx, bool is_custom);
int cam_ife_csid_hw_deinit(struct cam_ife_csid_hw *ife_csid_hw);
int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
struct cam_csid_hw_reserve_resource_args *cid_reserv);
int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
struct cam_csid_hw_reserve_resource_args *reserve);
#endif /* _CAM_IFE_CSID_HW_H_ */

ファイルの表示

@@ -76,7 +76,7 @@ int cam_ife_csid_probe(struct platform_device *pdev)
/* need to setup the pdev before call the ife hw probe init */
csid_dev->csid_info = csid_hw_data;
rc = cam_ife_csid_hw_probe_init(csid_hw_intf, csid_dev_idx);
rc = cam_ife_csid_hw_probe_init(csid_hw_intf, csid_dev_idx, false);
if (rc)
goto free_dev;

ファイルの表示

@@ -39,7 +39,7 @@ static int cam_ife_csid_request_platform_resource(
}
int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info,
irq_handler_t csid_irq_handler, void *irq_data)
irq_handler_t csid_irq_handler, void *irq_data, bool is_custom)
{
int rc = 0;
struct cam_cpas_register_params cpas_register_param;
@@ -66,8 +66,13 @@ int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info,
}
memset(&cpas_register_param, 0, sizeof(cpas_register_param));
strlcpy(cpas_register_param.identifier, "csid",
CAM_HW_IDENTIFIER_LENGTH);
if (is_custom)
strlcpy(cpas_register_param.identifier, "csid-custom",
CAM_HW_IDENTIFIER_LENGTH);
else
strlcpy(cpas_register_param.identifier, "csid",
CAM_HW_IDENTIFIER_LENGTH);
cpas_register_param.cell_index = soc_info->index;
cpas_register_param.dev = soc_info->dev;
rc = cam_cpas_register_client(&cpas_register_param);

ファイルの表示

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_IFE_CSID_SOC_H_
@@ -39,10 +39,11 @@ struct csid_device_soc_info {
* @soc_info: soc info structure pointer
* @csid_irq_handler: irq handler function to be registered
* @irq_data: irq data for the callback function
* @is_custom: for custom csid hw
*
*/
int cam_ife_csid_init_soc_resources(struct cam_hw_soc_info *soc_info,
irq_handler_t csid_irq_handler, void *irq_data);
irq_handler_t csid_irq_handler, void *irq_data, bool is_custom);
/**

ファイルの表示

@@ -12,6 +12,7 @@
/* MAX IFE CSID instance */
#define CAM_IFE_CSID_HW_NUM_MAX 7
#define CAM_IFE_CSID_RDI_MAX 4
#define CAM_IFE_CSID_UDI_MAX 3
/**
* enum cam_ife_pix_path_res_id - Specify the csid patch
@@ -23,6 +24,9 @@ enum cam_ife_pix_path_res_id {
CAM_IFE_PIX_PATH_RES_RDI_3,
CAM_IFE_PIX_PATH_RES_IPP,
CAM_IFE_PIX_PATH_RES_PPP,
CAM_IFE_PIX_PATH_RES_UDI_0,
CAM_IFE_PIX_PATH_RES_UDI_1,
CAM_IFE_PIX_PATH_RES_UDI_2,
CAM_IFE_PIX_PATH_RES_MAX,
};
@@ -97,6 +101,7 @@ struct cam_isp_in_port_generic_info {
uint32_t num_out_res;
uint32_t horizontal_bin;
uint32_t qcfa_bin;
uint32_t num_bytes_out;
struct cam_isp_out_port_generic_info *data;
};