media: rockchip: vicap support get error info
Change-Id: I61fc0834e3574876f40d563290222044550594a4 Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
This commit is contained in:
@@ -6912,20 +6912,8 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
|
||||
ret = dev->pipe.close(&dev->pipe);
|
||||
if (ret < 0)
|
||||
v4l2_err(v4l2_dev, "pipeline close failed error:%d\n", ret);
|
||||
if (dev->hdr.hdr_mode == HDR_X2) {
|
||||
if (dev->stream[RKCIF_STREAM_MIPI_ID0].state == RKCIF_STATE_READY &&
|
||||
dev->stream[RKCIF_STREAM_MIPI_ID1].state == RKCIF_STATE_READY) {
|
||||
dev->can_be_reset = true;
|
||||
}
|
||||
} else if (dev->hdr.hdr_mode == HDR_X3) {
|
||||
if (dev->stream[RKCIF_STREAM_MIPI_ID0].state == RKCIF_STATE_READY &&
|
||||
dev->stream[RKCIF_STREAM_MIPI_ID1].state == RKCIF_STATE_READY &&
|
||||
dev->stream[RKCIF_STREAM_MIPI_ID2].state == RKCIF_STATE_READY) {
|
||||
dev->can_be_reset = true;
|
||||
}
|
||||
} else {
|
||||
if (atomic_read(&dev->pipe.stream_cnt) == 0)
|
||||
dev->can_be_reset = true;
|
||||
}
|
||||
mutex_lock(&hw_dev->dev_lock);
|
||||
for (i = 0; i < hw_dev->dev_num; i++) {
|
||||
if (atomic_read(&hw_dev->cif_dev[i]->pipe.stream_cnt) != 0) {
|
||||
@@ -9903,6 +9891,55 @@ void rkcif_flip_end_wait_work(struct work_struct *work)
|
||||
mutex_unlock(&dev->stream_lock);
|
||||
}
|
||||
|
||||
static int rkcif_get_error_info(struct rkcif_device *cif_dev,
|
||||
struct rkmodule_error_info *err_info)
|
||||
{
|
||||
int count = 0;
|
||||
int is_dvp = (cif_dev->inf_id == RKCIF_DVP);
|
||||
|
||||
memset(err_info, 0, sizeof(*err_info));
|
||||
|
||||
if (is_dvp)
|
||||
count = snprintf(err_info->detail, sizeof(err_info->detail), "rkcif_dvp:");
|
||||
else
|
||||
count = snprintf(err_info->detail, sizeof(err_info->detail), "rkcif_mipi%d:", cif_dev->csi_host_idx);
|
||||
|
||||
#define APPEND_STAT(field) \
|
||||
do {\
|
||||
ssize_t remaining = sizeof(err_info->detail) - count;\
|
||||
if (remaining > 0) { \
|
||||
int written = snprintf(err_info->detail + count, remaining, "%lld,", cif_dev->irq_stats.field); \
|
||||
if (written >= 0) { \
|
||||
count += written; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
APPEND_STAT(bus0_err);
|
||||
APPEND_STAT(bus1_err);
|
||||
|
||||
if (is_dvp) {
|
||||
APPEND_STAT(dvp_overflow_cnt);
|
||||
APPEND_STAT(dvp_bwidth_lack_cnt);
|
||||
APPEND_STAT(dvp_size_err_cnt);
|
||||
} else {
|
||||
APPEND_STAT(csi_overflow_cnt);
|
||||
APPEND_STAT(csi_bwidth_lack_cnt);
|
||||
APPEND_STAT(csi_size_err_cnt);
|
||||
}
|
||||
|
||||
count += snprintf(err_info->detail + count, sizeof(err_info->detail) - count,
|
||||
"%lld,%lld,%lld,%lld,",
|
||||
cif_dev->irq_stats.not_active_buf_cnt[0],
|
||||
cif_dev->irq_stats.not_active_buf_cnt[1],
|
||||
cif_dev->irq_stats.not_active_buf_cnt[2],
|
||||
cif_dev->irq_stats.not_active_buf_cnt[3]);
|
||||
|
||||
err_info->err_code = cif_dev->irq_stats.all_err_cnt ? BIT(0) : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rkcif_do_reset_work(struct rkcif_device *cif_dev,
|
||||
enum rkmodule_reset_src reset_src);
|
||||
|
||||
@@ -9933,6 +9970,7 @@ static long rkcif_ioctl_default(struct file *file, void *fh,
|
||||
u32 vblank = 0;
|
||||
struct rkisp_vicap_mode vicap_mode;
|
||||
struct v4l2_subdev *sd = NULL;
|
||||
struct rkmodule_error_info *err_info;
|
||||
|
||||
switch (cmd) {
|
||||
case RKCIF_CMD_GET_CSI_MEMORY_MODE:
|
||||
@@ -10235,6 +10273,10 @@ static long rkcif_ioctl_default(struct file *file, void *fh,
|
||||
else
|
||||
dev->is_support_get_exp = false;
|
||||
break;
|
||||
case RKMODULE_GET_ERROR_INFO:
|
||||
err_info = (struct rkmodule_error_info *)arg;
|
||||
ret = rkcif_get_error_info(dev, err_info);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -14102,12 +14144,16 @@ unsigned int rkcif_irq_global(struct rkcif_device *cif_dev)
|
||||
v4l2_err(&cif_dev->v4l2_dev,
|
||||
"ERROR: AXI0 bus err intstat_glb:0x%x !!\n",
|
||||
intstat_glb);
|
||||
cif_dev->irq_stats.bus0_err++;
|
||||
cif_dev->irq_stats.all_err_cnt++;
|
||||
return 0;
|
||||
}
|
||||
if (cif_dev->chip_id == CHIP_RK3588_CIF && intstat_glb & SCALE_TOISP_AXI1_ERR) {
|
||||
v4l2_err(&cif_dev->v4l2_dev,
|
||||
"ERROR: AXI1 bus err intstat_glb:0x%x !!\n",
|
||||
intstat_glb);
|
||||
cif_dev->irq_stats.bus1_err++;
|
||||
cif_dev->irq_stats.all_err_cnt++;
|
||||
return 0;
|
||||
}
|
||||
return intstat_glb;
|
||||
@@ -15029,12 +15075,14 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
|
||||
if (cif_dev->chip_id >= CHIP_RV1103B_CIF)
|
||||
rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_CTRL, ~0x000f0000);
|
||||
}
|
||||
cif_dev->irq_stats.all_err_cnt++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (intstat & CSI_FIFO_OVERFLOW_V1) {
|
||||
cif_dev->irq_stats.csi_overflow_cnt++;
|
||||
cif_dev->err_state |= RKCIF_ERR_OVERFLOW;
|
||||
cif_dev->irq_stats.all_err_cnt++;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -398,6 +398,8 @@ struct rkcif_irq_stats {
|
||||
u64 frm_end_cnt[RKCIF_MAX_STREAM_MIPI];
|
||||
u64 not_active_buf_cnt[RKCIF_MAX_STREAM_MIPI];
|
||||
u64 trig_simult_cnt[RKCIF_MAX_STREAM_MIPI];
|
||||
u64 bus0_err;
|
||||
u64 bus1_err;
|
||||
u64 all_err_cnt;
|
||||
};
|
||||
|
||||
|
||||
@@ -641,12 +641,51 @@ static void csi2_quick_stream_off(struct csi2_dev *csi2)
|
||||
}
|
||||
}
|
||||
|
||||
static int csi2_get_error_info(struct csi2_dev *csi2,
|
||||
struct rkmodule_error_info *err_info)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
memset(err_info, 0, sizeof(*err_info));
|
||||
|
||||
count = snprintf(err_info->detail, sizeof(err_info->detail), "%s:", csi2->dev_name);
|
||||
|
||||
#define APPEND_STAT(field) \
|
||||
do {\
|
||||
ssize_t remaining = sizeof(err_info->detail) - count;\
|
||||
if (remaining > 0) { \
|
||||
int written = snprintf(err_info->detail + count, remaining, "%u,", csi2->err_list[field].cnt); \
|
||||
if (written >= 0) { \
|
||||
count += written; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
APPEND_STAT(RK_CSI2_ERR_SOTSYN);
|
||||
APPEND_STAT(RK_CSI2_ERR_FS_FE_MIS);
|
||||
APPEND_STAT(RK_CSI2_ERR_FRM_SEQ_ERR);
|
||||
APPEND_STAT(RK_CSI2_ERR_CRC_ONCE);
|
||||
APPEND_STAT(RK_CSI2_ERR_CRC);
|
||||
APPEND_STAT(RK_CSI2_ERR_ECC2);
|
||||
APPEND_STAT(RK_CSI2_ERR_CTRL);
|
||||
APPEND_STAT(RK_CSI2_ERR_ULPM);
|
||||
APPEND_STAT(RK_CSI2_ERR_SOT);
|
||||
APPEND_STAT(RK_CSI2_ERR_ECC);
|
||||
APPEND_STAT(RK_CSI2_ERR_ID);
|
||||
APPEND_STAT(RK_CSI2_ERR_CODE);
|
||||
|
||||
err_info->err_code = csi2->err_list[RK_CSI2_ERR_ALL].cnt ? BIT(0) : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long rkcif_csi2_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
{
|
||||
struct csi2_dev *csi2 = sd_to_dev(sd);
|
||||
struct v4l2_subdev *sensor = get_remote_sensor(sd);
|
||||
long ret = 0;
|
||||
int i = 0;
|
||||
struct rkmodule_error_info *err_info;
|
||||
|
||||
switch (cmd) {
|
||||
case RKCIF_CMD_SET_CSI_IDX:
|
||||
@@ -667,6 +706,10 @@ static long rkcif_csi2_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg
|
||||
else
|
||||
csi2_quick_stream_off(csi2);
|
||||
break;
|
||||
case RKMODULE_GET_ERROR_INFO:
|
||||
err_info = (struct rkmodule_error_info *)arg;
|
||||
ret = csi2_get_error_info(csi2, err_info);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
@@ -683,6 +726,7 @@ static long rkcif_csi2_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
struct rkcif_csi_info csi_info;
|
||||
int sw_dbg = 0;
|
||||
long ret;
|
||||
struct rkmodule_error_info *err_info;
|
||||
|
||||
switch (cmd) {
|
||||
case RKCIF_CMD_SET_CSI_IDX:
|
||||
@@ -697,6 +741,22 @@ static long rkcif_csi2_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
|
||||
ret = rkcif_csi2_ioctl(sd, cmd, &sw_dbg);
|
||||
break;
|
||||
case RKMODULE_GET_ERROR_INFO:
|
||||
err_info = kzalloc(sizeof(*err_info), GFP_KERNEL);
|
||||
if (!err_info) {
|
||||
ret = -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rkcif_csi2_ioctl(sd, cmd, err_info);
|
||||
if (!ret) {
|
||||
if (copy_to_user(up, err_info, sizeof(*err_info))) {
|
||||
kfree(err_info);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
kfree(err_info);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
@@ -960,6 +1020,7 @@ static irqreturn_t rk_csirx_irq2_handler(int irq, void *ctx)
|
||||
char err_str[CSI_ERRSTR_LEN] = {0};
|
||||
char vc_info[CSI_VCINFO_LEN] = {0};
|
||||
u64 cur_timestamp = ktime_get_ns();
|
||||
struct csi2_err_stats *err_list = NULL;
|
||||
|
||||
if (!csi2_hw) {
|
||||
disable_irq_nosync(irq);
|
||||
@@ -975,26 +1036,36 @@ static irqreturn_t rk_csirx_irq2_handler(int irq, void *ctx)
|
||||
val = read_csihost_reg(csi2_hw->base, CSIHOST_ERR2);
|
||||
if (val) {
|
||||
if (val & CSIHOST_ERR2_PHYERR_ESC) {
|
||||
err_list = &csi2->err_list[RK_CSI2_ERR_ULPM];
|
||||
err_list->cnt++;
|
||||
csi2_find_err_vc(val & 0xf, vc_info);
|
||||
snprintf(cur_str, CSI_ERRSTR_LEN, "(ULPM,lane:%s) ", vc_info);
|
||||
csi2_err_strncat(err_str, cur_str);
|
||||
}
|
||||
if (val & CSIHOST_ERR2_PHYERR_SOTHS) {
|
||||
err_list = &csi2->err_list[RK_CSI2_ERR_SOT];
|
||||
err_list->cnt++;
|
||||
csi2_find_err_vc((val >> 4) & 0xf, vc_info);
|
||||
snprintf(cur_str, CSI_ERRSTR_LEN, "(sot,lane:%s) ", vc_info);
|
||||
csi2_err_strncat(err_str, cur_str);
|
||||
}
|
||||
if (val & CSIHOST_ERR2_ECC_CORRECTED) {
|
||||
err_list = &csi2->err_list[RK_CSI2_ERR_ECC];
|
||||
err_list->cnt++;
|
||||
csi2_find_err_vc((val >> 8) & 0xf, vc_info);
|
||||
snprintf(cur_str, CSI_ERRSTR_LEN, "(ecc,vc:%s) ", vc_info);
|
||||
csi2_err_strncat(err_str, cur_str);
|
||||
}
|
||||
if (val & CSIHOST_ERR2_ERR_ID) {
|
||||
err_list = &csi2->err_list[RK_CSI2_ERR_ID];
|
||||
err_list->cnt++;
|
||||
csi2_find_err_vc((val >> 12) & 0xf, vc_info);
|
||||
snprintf(cur_str, CSI_ERRSTR_LEN, "(err id,vc:%s) ", vc_info);
|
||||
csi2_err_strncat(err_str, cur_str);
|
||||
}
|
||||
if (val & CSIHOST_ERR2_PHYERR_CODEHS) {
|
||||
err_list = &csi2->err_list[RK_CSI2_ERR_CODE];
|
||||
err_list->cnt++;
|
||||
snprintf(cur_str, CSI_ERRSTR_LEN, "(err code) ");
|
||||
csi2_err_strncat(err_str, cur_str);
|
||||
}
|
||||
|
||||
@@ -115,6 +115,11 @@ enum csi2_err {
|
||||
RK_CSI2_ERR_CRC,
|
||||
RK_CSI2_ERR_ECC2,
|
||||
RK_CSI2_ERR_CTRL,
|
||||
RK_CSI2_ERR_ULPM,
|
||||
RK_CSI2_ERR_SOT,
|
||||
RK_CSI2_ERR_ECC,
|
||||
RK_CSI2_ERR_ID,
|
||||
RK_CSI2_ERR_CODE,
|
||||
RK_CSI2_ERR_ALL,
|
||||
RK_CSI2_ERR_MAX
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user