From 9b73f1d3cd03cabf7cc1dc73d13465f91c745241 Mon Sep 17 00:00:00 2001 From: Abhishek Kondaveeti Date: Fri, 25 Apr 2014 10:43:56 +0530 Subject: [PATCH] msm:camera: Bus overflow recovery mechanism Add bus overflow recovery mechanism in the isp driver. When the bus overflow happens we will halt the bus, reset the isp and burst count and restart the stream. Change-Id: I7a1a4e1c28e346036405db4ce9a2362109bd4f95 Signed-off-by: Abhishek Kondaveeti --- .../platform/msm/camera_v2/isp/msm_isp.h | 22 ++- .../platform/msm/camera_v2/isp/msm_isp32.c | 56 +++++++- .../platform/msm/camera_v2/isp/msm_isp40.c | 69 +++++++-- .../msm/camera_v2/isp/msm_isp_axi_util.c | 7 +- .../msm/camera_v2/isp/msm_isp_axi_util.h | 4 + .../platform/msm/camera_v2/isp/msm_isp_util.c | 135 +++++++++++++++++- 6 files changed, 268 insertions(+), 25 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index 4700469ff7a..e9820a0f80c 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -147,13 +147,13 @@ struct msm_vfe_axi_ops { uint32_t (*get_wm_mask) (uint32_t irq_status0, uint32_t irq_status1); uint32_t (*get_comp_mask) (uint32_t irq_status0, uint32_t irq_status1); uint32_t (*get_pingpong_status) (struct vfe_device *vfe_dev); - long (*halt) (struct vfe_device *vfe_dev); + long (*halt) (struct vfe_device *vfe_dev, uint32_t blocking); }; struct msm_vfe_core_ops { void (*reg_update) (struct vfe_device *vfe_dev); long (*reset_hw) (struct vfe_device *vfe_dev, - enum msm_isp_reset_type reset_type); + enum msm_isp_reset_type reset_type, uint32_t blocking); int (*init_hw) (struct vfe_device *vfe_dev); void (*init_hw_reg) (struct vfe_device *vfe_dev); void (*release_hw) (struct vfe_device *vfe_dev); @@ -167,6 +167,12 @@ struct msm_vfe_core_ops { int (*get_platform_data) (struct vfe_device *vfe_dev); void (*get_error_mask) (uint32_t *error_mask0, uint32_t *error_mask1); void (*process_error_status) (struct vfe_device *vfe_dev); + void (*get_overflow_mask) (uint32_t *overflow_mask); + void (*get_irq_mask) (struct vfe_device *vfe_dev, + uint32_t *irq0_mask, uint32_t *irq1_mask); + void (*restore_irq_mask) (struct vfe_device *vfe_dev); + void (*get_halt_restart_mask) (uint32_t *irq0_mask, + uint32_t *irq1_mask); }; struct msm_vfe_stats_ops { int (*get_stats_idx) (enum msm_isp_stats_type stats_type); @@ -298,6 +304,15 @@ struct msm_vfe_axi_stream { uint32_t runtime_num_burst_capture; uint8_t runtime_framedrop_update; uint32_t runtime_output_format; + enum msm_vfe_frame_skip_pattern frame_skip_pattern; + +}; + +enum msm_vfe_overflow_state { + NO_OVERFLOW, + OVERFLOW_DETECTED, + HALT_REQUESTED, + RESTART_REQUESTED, }; struct msm_vfe_axi_composite_info { @@ -393,6 +408,9 @@ struct msm_vfe_tasklet_queue_cmd { #define MSM_VFE_TASKLETQ_SIZE 200 struct msm_vfe_error_info { + atomic_t overflow_state; + uint32_t overflow_recover_irq_mask0; + uint32_t overflow_recover_irq_mask1; uint32_t error_mask0; uint32_t error_mask1; uint32_t violation_status; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c index cf76131c570..ba1e58c0f51 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c @@ -393,19 +393,25 @@ static uint32_t msm_vfe32_reset_values[ISP_RST_MAX] = }; static long msm_vfe32_reset_hardware(struct vfe_device *vfe_dev , - enum msm_isp_reset_type reset_type) + enum msm_isp_reset_type reset_type, uint32_t blocking) { uint32_t rst_val; + long rc = 0; if (reset_type >= ISP_RST_MAX) { pr_err("%s: Error Invalid parameter\n", __func__); reset_type = ISP_RST_HARD; } rst_val = msm_vfe32_reset_values[reset_type]; init_completion(&vfe_dev->reset_complete); - msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0x4); - return wait_for_completion_timeout( - &vfe_dev->reset_complete, msecs_to_jiffies(50)); + if (blocking) { + msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0x4); + rc = wait_for_completion_timeout( + &vfe_dev->reset_complete, msecs_to_jiffies(50)); + } else { + msm_camera_io_w_mb(0x3EF, vfe_dev->vfe_base + 0x4); + } + return rc; } static void msm_vfe32_axi_reload_wm( @@ -659,6 +665,7 @@ static void msm_vfe32_update_camif_state( val &= 0xFFFFFF3F; val = val | bus_en << 7 | vfe_en << 6; msm_camera_io_w(val, vfe_dev->vfe_base + 0x1E4); + msm_camera_io_w_mb(0x4, vfe_dev->vfe_base + 0x1E0); msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1E0); vfe_dev->axi_data.src_info[VFE_PIX_0].active = 1; } else if (update_state == DISABLE_CAMIF) { @@ -891,12 +898,15 @@ static void msm_vfe32_update_ping_pong_addr(struct vfe_device *vfe_dev, VFE32_PING_PONG_BASE(wm_idx, pingpong_status)); } -static long msm_vfe32_axi_halt(struct vfe_device *vfe_dev) +static long msm_vfe32_axi_halt(struct vfe_device *vfe_dev, + uint32_t blocking) { uint32_t halt_mask; - uint32_t axi_busy_flag = true; - + uint32_t axi_busy_flag = false; msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1D8); + if (blocking) { + axi_busy_flag = true; + } while (axi_busy_flag) { if (msm_camera_io_r( vfe_dev->vfe_base + 0x1DC) & 0x1) @@ -1067,6 +1077,33 @@ static uint32_t msm_vfe32_stats_get_wm_mask(uint32_t irq_status0, return (irq_status0 >> 13) & 0x7F; } +static void msm_vfe32_get_overflow_mask(uint32_t *overflow_mask) +{ + *overflow_mask = 0x002FFF7E; +} + +static void msm_vfe32_get_irq_mask(struct vfe_device *vfe_dev, + uint32_t *irq0_mask, uint32_t *irq1_mask) +{ + *irq0_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x1C); + *irq1_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x20); +} + +static void msm_vfe32_restore_irq_mask(struct vfe_device *vfe_dev) +{ + msm_camera_io_w(vfe_dev->error_info.overflow_recover_irq_mask0, + vfe_dev->vfe_base + 0x1C); + msm_camera_io_w(vfe_dev->error_info.overflow_recover_irq_mask1, + vfe_dev->vfe_base + 0x20); +} + +static void msm_vfe32_get_halt_restart_mask(uint32_t *irq0_mask, + uint32_t *irq1_mask) +{ + *irq0_mask = 0x0; + *irq1_mask = 0x01800000; +} + static uint32_t msm_vfe32_stats_get_comp_mask(uint32_t irq_status0, uint32_t irq_status1) { @@ -1220,6 +1257,11 @@ struct msm_vfe_hardware_info vfe32_hw_info = { .release_hw = msm_vfe32_release_hardware, .get_platform_data = msm_vfe32_get_platform_data, .get_error_mask = msm_vfe32_get_error_mask, + .get_overflow_mask = msm_vfe32_get_overflow_mask, + .get_irq_mask = msm_vfe32_get_irq_mask, + .restore_irq_mask = msm_vfe32_restore_irq_mask, + .get_halt_restart_mask = + msm_vfe32_get_halt_restart_mask, .process_error_status = msm_vfe32_process_error_status, }, .stats_ops = { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c index 04136d04955..81e9c7407cf 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c @@ -620,18 +620,24 @@ static uint32_t msm_vfe40_reset_values[ISP_RST_MAX] = static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev , - enum msm_isp_reset_type reset_type) + enum msm_isp_reset_type reset_type, uint32_t blocking) { uint32_t rst_val; + long rc = 0; if (reset_type >= ISP_RST_MAX) { pr_err("%s: Error Invalid parameter\n", __func__); reset_type = ISP_RST_HARD; } rst_val = msm_vfe40_reset_values[reset_type]; init_completion(&vfe_dev->reset_complete); - msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0xC); - return wait_for_completion_timeout( - &vfe_dev->reset_complete, msecs_to_jiffies(50)); + if (blocking) { + msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0xC); + rc = wait_for_completion_timeout( + &vfe_dev->reset_complete, msecs_to_jiffies(50)); + } else { + msm_camera_io_w_mb(0x1EF, vfe_dev->vfe_base + 0xC); + } + return rc; } static void msm_vfe40_axi_reload_wm( @@ -924,6 +930,7 @@ static void msm_vfe40_update_camif_state(struct vfe_device *vfe_dev, val &= 0xFFFFFF3F; val = val | bus_en << 7 | vfe_en << 6; msm_camera_io_w(val, vfe_dev->vfe_base + 0x2F8); + msm_camera_io_w_mb(0x4, vfe_dev->vfe_base + 0x2F4); msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2F4); vfe_dev->axi_data.src_info[VFE_PIX_0].active = 1; } else if (update_state == DISABLE_CAMIF) { @@ -1165,16 +1172,24 @@ static void msm_vfe40_update_ping_pong_addr( VFE40_PING_PONG_BASE(wm_idx, pingpong_status)); } -static long msm_vfe40_axi_halt(struct vfe_device *vfe_dev) +static long msm_vfe40_axi_halt(struct vfe_device *vfe_dev, + uint32_t blocking) { - uint32_t halt_mask; - halt_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x2C); - halt_mask |= (1 << 8); - msm_camera_io_w_mb(halt_mask, vfe_dev->vfe_base + 0x2C); + long rc = 0; + /* Keep only restart mask and halt mask*/ + msm_camera_io_w(BIT(31), vfe_dev->vfe_base + 0x28); + msm_camera_io_w(BIT(8), vfe_dev->vfe_base + 0x2C); + /* Clear IRQ Status*/ + msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x30); + msm_camera_io_w(0xFEFFFFFF, vfe_dev->vfe_base + 0x34); init_completion(&vfe_dev->halt_complete); msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2C0); - return wait_for_completion_interruptible_timeout( - &vfe_dev->halt_complete, msecs_to_jiffies(500)); + if (blocking) { + atomic_set(&vfe_dev->error_info.overflow_state, NO_OVERFLOW); + rc = wait_for_completion_interruptible_timeout( + &vfe_dev->halt_complete, msecs_to_jiffies(500)); + } + return rc; } static uint32_t msm_vfe40_get_wm_mask( @@ -1183,6 +1198,33 @@ static uint32_t msm_vfe40_get_wm_mask( return (irq_status0 >> 8) & 0x7F; } +static void msm_vfe40_get_overflow_mask(uint32_t *overflow_mask) +{ + *overflow_mask = 0x00FFFE7E; +} + +static void msm_vfe40_get_irq_mask(struct vfe_device *vfe_dev, + uint32_t *irq0_mask, uint32_t *irq1_mask) +{ + *irq0_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28); + *irq1_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x2C); +} + +static void msm_vfe40_restore_irq_mask(struct vfe_device *vfe_dev) +{ + msm_camera_io_w(vfe_dev->error_info.overflow_recover_irq_mask0, + vfe_dev->vfe_base + 0x28); + msm_camera_io_w(vfe_dev->error_info.overflow_recover_irq_mask1, + vfe_dev->vfe_base + 0x2C); +} + +static void msm_vfe40_get_halt_restart_mask(uint32_t *irq0_mask, + uint32_t *irq1_mask) +{ + *irq0_mask = BIT(31); + *irq1_mask = BIT(8); +} + static uint32_t msm_vfe40_get_comp_mask( uint32_t irq_status0, uint32_t irq_status1) { @@ -1519,6 +1561,11 @@ struct msm_vfe_hardware_info vfe40_hw_info = { .release_hw = msm_vfe40_release_hardware, .get_platform_data = msm_vfe40_get_platform_data, .get_error_mask = msm_vfe40_get_error_mask, + .get_overflow_mask = msm_vfe40_get_overflow_mask, + .get_irq_mask = msm_vfe40_get_irq_mask, + .restore_irq_mask = msm_vfe40_restore_irq_mask, + .get_halt_restart_mask = + msm_vfe40_get_halt_restart_mask, .process_error_status = msm_vfe40_process_error_status, }, .stats_ops = { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 508bcec737e..83dc33010e9 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -475,7 +475,8 @@ void msm_isp_calculate_framedrop( framedrop_period = msm_isp_get_framedrop_period( stream_cfg_cmd->frame_skip_pattern); - + stream_info->frame_skip_pattern = + stream_cfg_cmd->frame_skip_pattern; if (stream_cfg_cmd->frame_skip_pattern == SKIP_ALL) stream_info->framedrop_pattern = 0x0; else @@ -1318,9 +1319,9 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev, if (cur_stream_cnt == 0) { vfe_dev->ignore_error = 1; if (camif_update == DISABLE_CAMIF_IMMEDIATELY) { - vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev); + vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 1); } - vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, ISP_RST_HARD); + vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, ISP_RST_HARD, 1); vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev); vfe_dev->ignore_error = 0; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h index 7d282bdeeda..2314300bdbb 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h @@ -37,6 +37,10 @@ int msm_isp_axi_check_stream_state( struct vfe_device *vfe_dev, struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd); +void msm_isp_calculate_framedrop( + struct msm_vfe_axi_shared_data *axi_data, + struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd); + int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg); int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg); int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index cb46e9cdc47..28760b05c23 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -981,6 +981,125 @@ static inline void msm_isp_update_error_info(struct vfe_device *vfe_dev, vfe_dev->error_info.error_count++; } +static inline void msm_isp_process_overflow_irq( + struct vfe_device *vfe_dev, + uint32_t *irq_status0, uint32_t *irq_status1) +{ + uint32_t overflow_mask; + uint32_t halt_restart_mask0, halt_restart_mask1; + /*Mask out all other irqs if recovery is started*/ + if (atomic_read(&vfe_dev->error_info.overflow_state) != + NO_OVERFLOW) { + vfe_dev->hw_info->vfe_ops.core_ops. + get_halt_restart_mask(&halt_restart_mask0, + &halt_restart_mask1); + *irq_status0 &= halt_restart_mask0; + *irq_status1 &= halt_restart_mask1; + return; + } + + /*Check if any overflow bit is set*/ + vfe_dev->hw_info->vfe_ops.core_ops. + get_overflow_mask(&overflow_mask); + overflow_mask &= *irq_status1; + if (overflow_mask) { + pr_warning("%s: Bus overflow detected: 0x%x\n", + __func__, overflow_mask); + atomic_set(&vfe_dev->error_info.overflow_state, + OVERFLOW_DETECTED); + pr_warning("%s: Start bus overflow recovery\n", __func__); + /*Store current IRQ mask*/ + vfe_dev->hw_info->vfe_ops.core_ops.get_irq_mask(vfe_dev, + &vfe_dev->error_info.overflow_recover_irq_mask0, + &vfe_dev->error_info.overflow_recover_irq_mask1); + /*Stop CAMIF Immediately*/ + vfe_dev->hw_info->vfe_ops.core_ops. + update_camif_state(vfe_dev, DISABLE_CAMIF_IMMEDIATELY); + /*Halt the hardware & Clear all other IRQ mask*/ + vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 0); + /*Update overflow state*/ + atomic_set(&vfe_dev->error_info.overflow_state, HALT_REQUESTED); + *irq_status0 = 0; + *irq_status1 = 0; + } +} + +static inline void msm_isp_reset_burst_count( + struct vfe_device *vfe_dev) +{ + int i; + struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; + struct msm_vfe_axi_stream *stream_info; + struct msm_vfe_axi_stream_request_cmd framedrop_info; + for (i = 0; i < MAX_NUM_STREAM; i++) { + stream_info = &axi_data->stream_info[i]; + if (stream_info->state != ACTIVE) + continue; + if (stream_info->stream_type == BURST_STREAM && + stream_info->num_burst_capture != 0) { + framedrop_info.burst_count = + stream_info->num_burst_capture; + framedrop_info.frame_skip_pattern = + stream_info->frame_skip_pattern; + framedrop_info.init_frame_drop = 0; + msm_isp_calculate_framedrop(&vfe_dev->axi_data, + &framedrop_info); + } + } +} + +static void msm_isp_process_overflow_recovery( + struct vfe_device *vfe_dev, + uint32_t irq_status0, uint32_t irq_status1) +{ + uint32_t halt_restart_mask0, halt_restart_mask1; + vfe_dev->hw_info->vfe_ops.core_ops. + get_halt_restart_mask(&halt_restart_mask0, + &halt_restart_mask1); + irq_status0 &= halt_restart_mask0; + irq_status1 &= halt_restart_mask1; + if (irq_status0 == 0 && irq_status1 == 0) + return; + + switch (atomic_read(&vfe_dev->error_info.overflow_state)) { + case HALT_REQUESTED: { + pr_err("%s: Halt done, Restart Pending\n", __func__); + /*Reset the hardware*/ + vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, + ISP_RST_SOFT, 0); + /*Update overflow state*/ + atomic_set(&vfe_dev->error_info.overflow_state, + RESTART_REQUESTED); + } + break; + case RESTART_REQUESTED: { + pr_err("%s: Restart done, Resuming\n", __func__); + /*Reset the burst stream frame drop pattern, in the + *case where bus overflow happens during the burstshot, + *the framedrop pattern might be updated after reg update + *to skip all the frames after the burst shot. The burst shot + *might not be completed due to the overflow, so the framedrop + *pattern need to change back to the original settings in order + *to recovr from overflow. + */ + msm_isp_reset_burst_count(vfe_dev); + vfe_dev->hw_info->vfe_ops.axi_ops. + reload_wm(vfe_dev, 0xFFFFFFFF); + vfe_dev->hw_info->vfe_ops.core_ops.restore_irq_mask(vfe_dev); + vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev); + memset(&vfe_dev->error_info, 0, sizeof(vfe_dev->error_info)); + atomic_set(&vfe_dev->error_info.overflow_state, NO_OVERFLOW); + vfe_dev->hw_info->vfe_ops.core_ops. + update_camif_state(vfe_dev, ENABLE_CAMIF); + } + break; + case NO_OVERFLOW: + case OVERFLOW_DETECTED: + default: + break; + } +} + irqreturn_t msm_isp_process_irq(int irq_num, void *data) { unsigned long flags; @@ -991,6 +1110,8 @@ irqreturn_t msm_isp_process_irq(int irq_num, void *data) vfe_dev->hw_info->vfe_ops.irq_ops. read_irq_status(vfe_dev, &irq_status0, &irq_status1); + msm_isp_process_overflow_irq(vfe_dev, + &irq_status0, &irq_status1); vfe_dev->hw_info->vfe_ops.core_ops. get_error_mask(&error_mask0, &error_mask1); error_mask0 &= irq_status0; @@ -1055,6 +1176,13 @@ void msm_isp_do_tasklet(unsigned long data) irq_status1 = queue_cmd->vfeInterruptStatus1; ts = queue_cmd->ts; spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags); + if (atomic_read(&vfe_dev->error_info.overflow_state) != + NO_OVERFLOW) { + pr_err("There is Overflow, kicking up recovery !!!!"); + msm_isp_process_overflow_recovery(vfe_dev, + irq_status0, irq_status1); + continue; + } ISP_DBG("%s: status0: 0x%x status1: 0x%x\n", __func__, irq_status0, irq_status1); irq_ops->process_reset_irq(vfe_dev, @@ -1105,7 +1233,10 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return -EBUSY; } - rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, ISP_RST_HARD); + memset(&vfe_dev->error_info, 0, sizeof(vfe_dev->error_info)); + atomic_set(&vfe_dev->error_info.overflow_state, NO_OVERFLOW); + rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, + ISP_RST_HARD, 1); if (rc <= 0) { pr_err("%s: reset timeout\n", __func__); mutex_unlock(&vfe_dev->core_mutex); @@ -1157,7 +1288,7 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return -ENODEV; } - rc = vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev); + rc = vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 1); if (rc <= 0) pr_err("%s: halt timeout rc=%ld\n", __func__, rc);