Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f8c217c authored by Petar Sivenov's avatar Petar Sivenov Committed by Sreesudhan Ramakrish Ramkumar
Browse files

msm: camera: isp: protect burst streams from invalid write



To ensure correct number of output frames, burst streams are
configured to skip all frames after delivering the last requested one.
However, the framedrop period and pattern registers are double
buffered and current implementation does not guarantee that register
update will happen on each frame. Thus, if reg update miss last frame
the burst stream write masters will make invalid write. This change
configures frame skip pattern in such manner, that all frames after
last required to be skipped. This will ensure that no extra frames
will be written and there will be enough time to receive reg update
command.

Change-Id: I3c8107bb4a426b62eb9c4a8f87857c0497b32f2c
Signed-off-by: default avatarPetar Sivenov <psiven@codeaurora.org>
parent f235a4bd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -329,6 +329,7 @@ struct msm_vfe_axi_stream {
	enum msm_vfe_frame_skip_pattern frame_skip_pattern;
	uint32_t framedrop_period;
	uint32_t framedrop_pattern;
	uint32_t framedrop_altern_cnt;
	uint32_t num_burst_capture;/*number of frame to capture*/
	uint32_t init_frame_drop;
	uint32_t burst_frame_count;/*number of sof before burst stop*/
+28 −6
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
	(VFE_RAW_0 + src - RDI_INTF_0))

#define HANDLE_TO_IDX(handle) (handle & 0xFF)
/* at how many frames to add frame skip pattern */
#define BURST_SKIP_THRESHOLD              (16)

int msm_isp_axi_create_stream(
	struct msm_vfe_axi_shared_data *axi_data,
@@ -402,10 +404,25 @@ void msm_isp_cfg_framedrop_reg(struct vfe_device *vfe_dev,
		framedrop_period = stream_info->framedrop_period;
	}

	if (stream_info->stream_type == BURST_STREAM &&
			stream_info->runtime_burst_frame_count == 0) {
	if (stream_info->stream_type == BURST_STREAM) {
		if (stream_info->runtime_burst_frame_count == 0) {
			framedrop_pattern = 0;
			framedrop_period = 0;
		} else if ((stream_info->runtime_burst_frame_count > 0) &&
			   (stream_info->runtime_burst_frame_count <
							BURST_SKIP_THRESHOLD)) {
			/* configure to skip the frames after requested ones to
			 * ensure that no frame will came after last, even if
			 * userspace reg update is delayed */
			framedrop_pattern =
			      (1 << stream_info->runtime_burst_frame_count) - 1;
			/* Alternate maximum two values for period to ensure
			 * that two identical consecutive patterns will still be
			 * applied. Otherwise HW cannot detect that we make 2
			 * different configurations */
			framedrop_period = 30 +
				(stream_info->framedrop_altern_cnt++ & 1);
		}
	}

	ISP_DBG("%s: stream %x framedrop pattern %x period %u\n", __func__,
@@ -450,13 +467,18 @@ void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev,
				msm_isp_cfg_framedrop_reg(vfe_dev, stream_info);
			} else {
				stream_info->runtime_burst_frame_count--;
				if (stream_info->runtime_burst_frame_count == 0)
				if ((stream_info->
					runtime_burst_frame_count <
						  BURST_SKIP_THRESHOLD) &&
				    (stream_info->
					runtime_burst_frame_count >= 0)) {
					msm_isp_cfg_framedrop_reg(vfe_dev,
						stream_info);
				}
			}
		}
	}
}

void msm_isp_reset_framedrop(struct vfe_device *vfe_dev,
	struct msm_vfe_axi_stream *stream_info)
@@ -678,7 +700,7 @@ int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg)
			return rc;
		}
	}

	stream_info->framedrop_altern_cnt = 0;
	msm_isp_calculate_framedrop(&vfe_dev->axi_data, stream_cfg_cmd);
	stream_info->vt_enable = stream_cfg_cmd->vt_enable;
	if (stream_info->vt_enable) {