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

Commit 90c3f2de authored by Abhishek Kondaveeti's avatar Abhishek Kondaveeti Committed by Gerrit - the friendly Code Review server
Browse files

msm: isp: Add support to multipass offline ISP



Process the input image in multiple passes using
single ISP.

Change-Id: I2b004c149b90ad03acf41d73e825976507a9a274
Signed-off-by: default avatarAbhishek Kondaveeti <akondave@codeaurora.org>
parent 0579bfa1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -243,6 +243,8 @@ struct msm_vfe_core_ops {
	bool (*is_module_cfg_lock_needed)(uint32_t reg_offset);
	int (*ahb_clk_cfg)(struct vfe_device *vfe_dev,
			struct msm_isp_ahb_clk_cfg *ahb_cfg);
	int (*start_fetch_eng_multi_pass)(struct vfe_device *vfe_dev,
		void *arg);
};
struct msm_vfe_stats_ops {
	int (*get_stats_idx)(enum msm_isp_stats_type stats_type);
+81 −2
Original line number Diff line number Diff line
@@ -1054,11 +1054,72 @@ static int msm_vfe40_start_fetch_engine(struct vfe_device *vfe_dev,
	return 0;
}

static int msm_vfe40_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev,
	void *arg)
{
	int rc = 0;
	uint32_t bufq_handle = 0;
	struct msm_isp_buffer *buf = NULL;
	struct msm_vfe_fetch_eng_multi_pass_start *fe_cfg = arg;
	struct msm_isp_buffer_mapped_info mapped_info;

	if (vfe_dev->fetch_engine_info.is_busy == 1) {
		pr_err("%s: fetch engine busy\n", __func__);
		return -EINVAL;
	}
	memset(&mapped_info, 0, sizeof(struct msm_isp_buffer_mapped_info));
	/* There is other option of passing buffer address from user,
	 * in such case, driver needs to map the buffer and use it
	 */
	vfe_dev->fetch_engine_info.session_id = fe_cfg->session_id;
	vfe_dev->fetch_engine_info.stream_id = fe_cfg->stream_id;
	vfe_dev->fetch_engine_info.offline_mode = fe_cfg->offline_mode;
	vfe_dev->fetch_engine_info.fd = fe_cfg->fd;

	if (!fe_cfg->offline_mode) {
		bufq_handle = vfe_dev->buf_mgr->ops->get_bufq_handle(
				vfe_dev->buf_mgr, fe_cfg->session_id,
				fe_cfg->stream_id);
		vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;

		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
		if (rc < 0 || !buf) {
			pr_err("%s: No fetch buffer rc= %d buf= %p\n",
				__func__, rc, buf);
			return -EINVAL;
		}
		mapped_info = buf->mapped_info[0];
		buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
	} else {
		rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
			&mapped_info, fe_cfg->fd);
		if (rc < 0) {
			pr_err("%s: can not map buffer\n", __func__);
			return -EINVAL;
		}
	}
	vfe_dev->fetch_engine_info.buf_idx = fe_cfg->buf_idx;
	vfe_dev->fetch_engine_info.is_busy = 1;

	msm_camera_io_w(mapped_info.paddr + fe_cfg->input_buf_offset,
		vfe_dev->vfe_base + 0x228);

	msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x378);

	msm_camera_io_w_mb(0x10000, vfe_dev->vfe_base + 0x4C);
	msm_camera_io_w_mb(0x20000, vfe_dev->vfe_base + 0x4C);

	ISP_DBG("%s:VFE%d Fetch Engine ready\n", __func__, vfe_dev->pdev->id);
	return 0;
}

static void msm_vfe40_cfg_fetch_engine(struct vfe_device *vfe_dev,
	struct msm_vfe_pix_cfg *pix_cfg)
{
	uint32_t x_size_word;
	uint32_t temp = 0;
	uint32_t main_unpack_pattern = 0;
	struct msm_vfe_fetch_engine_cfg *fe_cfg = NULL;

	if (pix_cfg->input_mux != EXTERNAL_READ) {
@@ -1089,10 +1150,14 @@ static void msm_vfe40_cfg_fetch_engine(struct vfe_device *vfe_dev,
	/* need to update to use formulae to calculate X_SIZE_WORD*/
	x_size_word = msm_isp_cal_word_per_line(
		vfe_dev->axi_data.src_info[VFE_PIX_0].input_format,
		fe_cfg->fetch_width);
		fe_cfg->buf_width);

	msm_camera_io_w((x_size_word - 1) << 16, vfe_dev->vfe_base + 0x23C);

	x_size_word = msm_isp_cal_word_per_line(
		vfe_dev->axi_data.src_info[VFE_PIX_0].input_format,
		fe_cfg->fetch_width);

	temp = msm_camera_io_r(vfe_dev->vfe_base + 0x1C);
	temp |= 2 << 16 | pix_cfg->pixel_pattern;
	msm_camera_io_w(temp, vfe_dev->vfe_base + 0x1C);
@@ -1118,7 +1183,19 @@ static void msm_vfe40_cfg_fetch_engine(struct vfe_device *vfe_dev,
	}

	/* need to use formulae to calculate MAIN_UNPACK_PATTERN*/
	msm_camera_io_w(0xF6543210, vfe_dev->vfe_base + 0x248);
	switch (vfe_dev->axi_data.src_info[VFE_PIX_0].input_format) {
	case V4L2_PIX_FMT_P16BGGR10:
	case V4L2_PIX_FMT_P16GBRG10:
	case V4L2_PIX_FMT_P16GRBG10:
	case V4L2_PIX_FMT_P16RGGB10:
		main_unpack_pattern = 0xB210;
		break;
	default:
		main_unpack_pattern = 0xF6543210;
		break;
	}
	msm_camera_io_w(main_unpack_pattern,
		vfe_dev->vfe_base + 0x248);
	msm_camera_io_w(0xF, vfe_dev->vfe_base + 0x264);

	return;
@@ -2261,6 +2338,8 @@ struct msm_vfe_hardware_info vfe40_hw_info = {
			.is_module_cfg_lock_needed =
				msm_vfe40_is_module_cfg_lock_needed,
			.ahb_clk_cfg = NULL,
			.start_fetch_eng_multi_pass =
				msm_vfe40_start_fetch_engine_multi_pass,
		},
		.stats_ops = {
			.get_stats_idx = msm_vfe40_get_stats_idx,
+78 −2
Original line number Diff line number Diff line
@@ -1077,11 +1077,70 @@ int msm_vfe47_start_fetch_engine(struct vfe_device *vfe_dev,
	return 0;
}

int msm_vfe47_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev,
	void *arg)
{
	int rc = 0;
	uint32_t bufq_handle = 0;
	struct msm_isp_buffer *buf = NULL;
	struct msm_vfe_fetch_eng_multi_pass_start *fe_cfg = arg;
	struct msm_isp_buffer_mapped_info mapped_info;

	if (vfe_dev->fetch_engine_info.is_busy == 1) {
		pr_err("%s: fetch engine busy\n", __func__);
		return -EINVAL;
	}

	memset(&mapped_info, 0, sizeof(struct msm_isp_buffer_mapped_info));

	vfe_dev->fetch_engine_info.session_id = fe_cfg->session_id;
	vfe_dev->fetch_engine_info.stream_id = fe_cfg->stream_id;
	vfe_dev->fetch_engine_info.offline_mode = fe_cfg->offline_mode;
	vfe_dev->fetch_engine_info.fd = fe_cfg->fd;

	if (!fe_cfg->offline_mode) {
		bufq_handle = vfe_dev->buf_mgr->ops->get_bufq_handle(
			vfe_dev->buf_mgr, fe_cfg->session_id,
			fe_cfg->stream_id);
		vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;

		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
		if (rc < 0 || !buf) {
			pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
				__func__, rc, buf);
			return -EINVAL;
		}
		mapped_info = buf->mapped_info[0];
		buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
	} else {
		rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
			&mapped_info, fe_cfg->fd);
		if (rc < 0) {
			pr_err("%s: can not map buffer\n", __func__);
			return -EINVAL;
		}
	}

	vfe_dev->fetch_engine_info.buf_idx = fe_cfg->buf_idx;
	vfe_dev->fetch_engine_info.is_busy = 1;

	msm_camera_io_w(mapped_info.paddr + fe_cfg->input_buf_offset,
		vfe_dev->vfe_base + 0x2F4);
	msm_camera_io_w_mb(0x100000, vfe_dev->vfe_base + 0x80);
	msm_camera_io_w_mb(0x200000, vfe_dev->vfe_base + 0x80);

	ISP_DBG("%s:VFE%d Fetch Engine ready\n", __func__, vfe_dev->pdev->id);

	return 0;
}

void msm_vfe47_cfg_fetch_engine(struct vfe_device *vfe_dev,
	struct msm_vfe_pix_cfg *pix_cfg)
{
	uint32_t x_size_word, temp;
	struct msm_vfe_fetch_engine_cfg *fe_cfg = NULL;
	uint32_t main_unpack_pattern = 0;

	if (pix_cfg->input_mux == EXTERNAL_READ) {
		fe_cfg = &pix_cfg->fetch_engine_cfg;
@@ -1107,10 +1166,13 @@ void msm_vfe47_cfg_fetch_engine(struct vfe_device *vfe_dev,

		x_size_word = msm_isp_cal_word_per_line(
			vfe_dev->axi_data.src_info[VFE_PIX_0].input_format,
			fe_cfg->fetch_width);
			fe_cfg->buf_width);
		msm_camera_io_w((x_size_word - 1) << 16,
			vfe_dev->vfe_base + 0x30c);

		x_size_word = msm_isp_cal_word_per_line(
			vfe_dev->axi_data.src_info[VFE_PIX_0].input_format,
			fe_cfg->fetch_width);
		msm_camera_io_w(x_size_word << 16 |
			(temp & 0x3FFF) << 2 | VFE47_FETCH_BURST_LEN,
			vfe_dev->vfe_base + 0x310);
@@ -1120,7 +1182,19 @@ void msm_vfe47_cfg_fetch_engine(struct vfe_device *vfe_dev,
		msm_camera_io_w(temp, vfe_dev->vfe_base + 0x314);

		/* need to use formulae to calculate MAIN_UNPACK_PATTERN*/
		msm_camera_io_w(0xF6543210, vfe_dev->vfe_base + 0x318);
		switch (vfe_dev->axi_data.src_info[VFE_PIX_0].input_format) {
		case V4L2_PIX_FMT_P16BGGR10:
		case V4L2_PIX_FMT_P16GBRG10:
		case V4L2_PIX_FMT_P16GRBG10:
		case V4L2_PIX_FMT_P16RGGB10:
			main_unpack_pattern = 0xB210;
			break;
		default:
			main_unpack_pattern = 0xF6543210;
			break;
		}
		msm_camera_io_w(main_unpack_pattern,
			vfe_dev->vfe_base + 0x318);
		msm_camera_io_w(0xF, vfe_dev->vfe_base + 0x334);

		temp = msm_camera_io_r(vfe_dev->vfe_base + 0x50);
@@ -2721,6 +2795,8 @@ struct msm_vfe_hardware_info vfe47_hw_info = {
			.is_module_cfg_lock_needed =
				msm_vfe47_is_module_cfg_lock_needed,
			.ahb_clk_cfg = msm_isp47_ahb_clk_cfg,
			.start_fetch_eng_multi_pass =
				msm_vfe47_start_fetch_engine_multi_pass,
		},
		.stats_ops = {
			.get_stats_idx = msm_vfe47_get_stats_idx,
+2 −0
Original line number Diff line number Diff line
@@ -65,6 +65,8 @@ int32_t msm_vfe47_cfg_io_format(struct vfe_device *vfe_dev,
	enum msm_vfe_axi_stream_src stream_src, uint32_t io_format);
int msm_vfe47_start_fetch_engine(struct vfe_device *vfe_dev,
	void *arg);
int msm_vfe47_start_fetch_engine_multi_pass(struct vfe_device *vfe_dev,
	void *arg);
void msm_vfe47_cfg_fetch_engine(struct vfe_device *vfe_dev,
	struct msm_vfe_pix_cfg *pix_cfg);
void msm_vfe47_cfg_testgen(struct vfe_device *vfe_dev,
+2 −0
Original line number Diff line number Diff line
@@ -309,6 +309,8 @@ struct msm_vfe_hardware_info vfe48_hw_info = {
			.is_module_cfg_lock_needed =
				msm_vfe47_is_module_cfg_lock_needed,
			.ahb_clk_cfg = msm_isp47_ahb_clk_cfg,
			.start_fetch_eng_multi_pass =
				msm_vfe47_start_fetch_engine_multi_pass,
		},
		.stats_ops = {
			.get_stats_idx = msm_vfe47_get_stats_idx,
Loading