forked from rubenslte/android_kernel_samsung_msm8226
Merge "msm📷 Bus overflow recovery mechanism"
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
commit
bd512f549b
@@ -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;
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -478,7 +478,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
|
||||
@@ -1331,9 +1332,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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user