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

Commit 2b17e36c authored by Senthil Kumar Rajagopal's avatar Senthil Kumar Rajagopal Committed by Sreesudhan Ramakrish Ramkumar
Browse files

msm: camera: isp: Implement synchronization for dual vfe



In case of dual vfe, both vfe hardwares are used for same camera
sensor. There are two tasklets serving irqs from each vfe. This
causes synchronization issues if either one of tasklets is delayed.
To fix this, implement synchronization by using only one vfe
to configure the image and stats buffer for both vfes.

Change-Id: If090bb7526c8d4f544f78e6a9378ebd382253940
Signed-off-by: default avatarSenthil Kumar Rajagopal <skrajago@codeaurora.org>
parent 37bc52a5
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -395,7 +395,8 @@ static int msm_isp_buf_unprepare(struct msm_isp_buf_mgr *buf_mgr,
}

static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
	uint32_t bufq_handle, struct msm_isp_buffer **buf_info)
	uint32_t bufq_handle, struct msm_isp_buffer **buf_info,
	uint32_t *buf_cnt)
{
	int rc = -1;
	unsigned long flags;
@@ -416,6 +417,7 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
	}

	*buf_info = NULL;
	*buf_cnt = 0;
	spin_lock_irqsave(&bufq->bufq_lock, flags);
	if (bufq->buf_type == ISP_SHARE_BUF) {
		list_for_each_entry(temp_buf_info,
@@ -423,6 +425,7 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
			if (!temp_buf_info->buf_used[id]) {
				temp_buf_info->buf_used[id] = 1;
				temp_buf_info->buf_get_count++;
				*buf_cnt = temp_buf_info->buf_get_count;
				if (temp_buf_info->buf_get_count ==
					bufq->buf_client_count)
					list_del(
+2 −1
Original line number Diff line number Diff line
@@ -127,7 +127,8 @@ struct msm_isp_buf_ops {
		uint32_t bufq_handle, uint32_t *buf_src);

	int (*get_buf)(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
		uint32_t bufq_handle, struct msm_isp_buffer **buf_info);
		uint32_t bufq_handle, struct msm_isp_buffer **buf_info,
		uint32_t *buf_cnt);

	int (*get_buf_by_index)(struct msm_isp_buf_mgr *buf_mgr,
		uint32_t bufq_handle, uint32_t buf_index,
+7 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ static const struct platform_device_id msm_vfe_dev_id[] = {
static char stat_line[OVERFLOW_LENGTH];

static struct msm_isp_buf_mgr vfe_buf_mgr;
static struct dual_vfe_resource dualvfe;
struct msm_isp_statistics stats;
struct msm_isp_ub_info ub_info;
static int msm_isp_enable_debugfs(struct vfe_device *vfe_dev,
@@ -479,6 +480,12 @@ static int vfe_probe(struct platform_device *pdev)
	ISP_DBG("%s: device id = %d\n", __func__, pdev->id);

	vfe_dev->pdev = pdev;
	vfe_dev->dual_vfe_res = &dualvfe;
	vfe_dev->dual_vfe_res->axi_data[vfe_dev->pdev->id] =
		&vfe_dev->axi_data;
	vfe_dev->dual_vfe_res->stats_data[vfe_dev->pdev->id] =
		&vfe_dev->stats_data;

	rc = vfe_dev->hw_info->vfe_ops.core_ops.get_platform_data(vfe_dev);
	if (rc < 0) {
		pr_err("%s: failed to get platform resources\n", __func__);
+18 −6
Original line number Diff line number Diff line
@@ -58,6 +58,8 @@
#define MSM_ISP_MIN_IB 100000000
#define MAX_BUFFERS_IN_HW 2

#define MAX_VFE 2

struct vfe_device;
struct msm_vfe_axi_stream;
struct msm_vfe_stats_stream;
@@ -119,14 +121,14 @@ struct msm_vfe_irq_ops {
};

struct msm_vfe_axi_ops {
	void (*reload_wm)(struct vfe_device *vfe_dev,
	void (*reload_wm)(struct vfe_device *vfe_dev, void __iomem *vfe_base,
		uint32_t reload_mask);
	void (*enable_wm)(struct vfe_device *vfe_dev,
		uint8_t wm_idx, uint8_t enable);
	int32_t (*cfg_io_format)(struct vfe_device *vfe_dev,
		enum msm_vfe_axi_stream_src stream_src,
		uint32_t io_format);
	void (*cfg_framedrop)(struct vfe_device *vfe_dev,
	void (*cfg_framedrop)(void __iomem *vfe_base,
		struct msm_vfe_axi_stream *stream_info,
		uint32_t framedrop_pattern, uint32_t framedrop_period);
	void (*clear_framedrop)(struct vfe_device *vfe_dev,
@@ -156,7 +158,7 @@ struct msm_vfe_axi_ops {

	void (*read_wm_ping_pong_addr)(struct vfe_device *vfe_dev);

	void (*update_ping_pong_addr)(struct vfe_device *vfe_dev,
	void (*update_ping_pong_addr)(void __iomem *vfe_base,
		uint8_t wm_idx, uint32_t pingpong_status, dma_addr_t paddr,
		int32_t buf_size);

@@ -227,7 +229,7 @@ struct msm_vfe_stats_ops {
	void (*enable_module)(struct vfe_device *vfe_dev,
		uint32_t stats_mask, uint8_t enable);

	void (*update_ping_pong_addr)(struct vfe_device *vfe_dev,
	void (*update_ping_pong_addr)(void __iomem *vfe_base,
		struct msm_vfe_stats_stream *stream_info,
		uint32_t pingpong_status, dma_addr_t paddr);

@@ -270,7 +272,7 @@ struct msm_vfe_axi_hardware_info {
};

enum msm_vfe_axi_state {
	AVALIABLE,
	AVAILABLE,
	INACTIVE,
	ACTIVE,
	PAUSED,
@@ -403,7 +405,7 @@ enum msm_wm_ub_cfg_type {

struct msm_vfe_axi_shared_data {
	struct msm_vfe_axi_hardware_info *hw_info;
	struct msm_vfe_axi_stream stream_info[MAX_NUM_STREAM];
	struct msm_vfe_axi_stream stream_info[VFE_AXI_SRC_MAX];
	uint32_t free_wm[MAX_NUM_WM];
	uint32_t wm_image_size[MAX_NUM_WM];
	enum msm_wm_ub_cfg_type wm_ub_cfg_policy;
@@ -572,6 +574,14 @@ struct msm_vfe_hw_init_parms {
	const char *settings;
};

struct dual_vfe_resource {
	void __iomem *vfe_base[MAX_VFE];
	uint32_t reg_update_mask[MAX_VFE];
	struct msm_vfe_stats_shared_data *stats_data[MAX_VFE];
	struct msm_vfe_axi_shared_data *axi_data[MAX_VFE];
	uint32_t wm_reload_mask[MAX_VFE];
};

struct vfe_device {
	struct platform_device *pdev;
	struct msm_sd_subdev subdev;
@@ -640,6 +650,8 @@ struct vfe_device {
	enum msm_vfe_hvx_streaming_cmd hvx_cmd;
	uint8_t reg_update_requested;
	uint8_t reg_updated;
	struct dual_vfe_resource *dual_vfe_res;
	uint32_t is_split;
};

#endif
+34 −25
Original line number Diff line number Diff line
@@ -275,6 +275,7 @@ static int msm_vfe32_init_hardware(struct vfe_device *vfe_dev)
		pr_err("%s: vfe ioremap failed\n", __func__);
		goto vfe_remap_failed;
	}
	vfe_dev->dual_vfe_res->vfe_base[vfe_dev->pdev->id] = vfe_dev->vfe_base;

	vfe_dev->vfe_vbif_base = ioremap(vfe_dev->vfe_vbif_mem->start,
		resource_size(vfe_dev->vfe_vbif_mem));
@@ -334,6 +335,7 @@ static void msm_vfe32_release_hardware(struct vfe_device *vfe_dev)
		msm_cam_clk_enable(&vfe_dev->pdev->dev,
				msm_vfe32_2_clk_info, vfe_dev->vfe_clk,
				ARRAY_SIZE(msm_vfe32_2_clk_info), 0);
	vfe_dev->dual_vfe_res->vfe_base[vfe_dev->pdev->id] = NULL;
	iounmap(vfe_dev->vfe_base);
	vfe_dev->vfe_base = NULL;
	kfree(vfe_dev->vfe_clk);
@@ -636,7 +638,13 @@ static void msm_vfe32_process_epoch_irq(struct vfe_device *vfe_dev,
static void msm_vfe32_reg_update(struct vfe_device *vfe_dev,
	enum msm_vfe_input_src frame_src)
{
	if (vfe_dev->is_split && vfe_dev->pdev->id == ISP_VFE1) {
		msm_camera_io_w_mb(0xF,
			vfe_dev->dual_vfe_res->vfe_base[ISP_VFE0] + 0x260);
		msm_camera_io_w_mb(0xF, vfe_dev->vfe_base + 0x260);
	} else if (!vfe_dev->is_split) {
		msm_camera_io_w_mb(0xF, vfe_dev->vfe_base + 0x260);
	}
}

static long msm_vfe32_reset_hardware(struct vfe_device *vfe_dev,
@@ -649,19 +657,20 @@ static long msm_vfe32_reset_hardware(struct vfe_device *vfe_dev,
}

static void msm_vfe32_axi_reload_wm(
	struct vfe_device *vfe_dev, uint32_t reload_mask)
	struct vfe_device *vfe_dev, void __iomem *vfe_base,
	uint32_t reload_mask)
{
	if (!vfe_dev->pdev->dev.of_node) {
		/*vfe32 A-family: 8960*/
		msm_camera_io_w_mb(reload_mask, vfe_dev->vfe_base + 0x38);
		msm_camera_io_w_mb(reload_mask, vfe_base + 0x38);
	} else {
		/*vfe32 B-family: 8610*/
		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x24);
		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x28);
		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x20);
		msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x18);
		msm_camera_io_w(0x9AAAAAAA , vfe_dev->vfe_base + 0x600);
		msm_camera_io_w(reload_mask, vfe_dev->vfe_base + 0x38);
		msm_camera_io_w(0x0, vfe_base + 0x24);
		msm_camera_io_w(0x0, vfe_base + 0x28);
		msm_camera_io_w(0x0, vfe_base + 0x20);
		msm_camera_io_w_mb(0x1, vfe_base + 0x18);
		msm_camera_io_w(0x9AAAAAAA , vfe_base + 0x600);
		msm_camera_io_w(reload_mask, vfe_base + 0x38);
	}
}

@@ -730,22 +739,22 @@ static void msm_vfe32_axi_clear_wm_irq_mask(struct vfe_device *vfe_dev,
	msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x1C);
}

static void msm_vfe32_cfg_framedrop(struct vfe_device *vfe_dev,
static void msm_vfe32_cfg_framedrop(void __iomem *vfe_base,
	struct msm_vfe_axi_stream *stream_info, uint32_t framedrop_pattern,
	uint32_t framedrop_period)
{
	if (stream_info->stream_src == PIX_ENCODER) {
		msm_camera_io_w(framedrop_period, vfe_dev->vfe_base + 0x504);
		msm_camera_io_w(framedrop_period, vfe_dev->vfe_base + 0x508);
		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x50C);
		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x510);
		msm_camera_io_w(framedrop_period, vfe_base + 0x504);
		msm_camera_io_w(framedrop_period, vfe_base + 0x508);
		msm_camera_io_w(framedrop_pattern, vfe_base + 0x50C);
		msm_camera_io_w(framedrop_pattern, vfe_base + 0x510);
	} else if (stream_info->stream_src == PIX_VIEWFINDER) {
		msm_camera_io_w(framedrop_period, vfe_dev->vfe_base + 0x514);
		msm_camera_io_w(framedrop_period, vfe_dev->vfe_base + 0x518);
		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x51C);
		msm_camera_io_w(framedrop_pattern, vfe_dev->vfe_base + 0x520);
		msm_camera_io_w(framedrop_period, vfe_base + 0x514);
		msm_camera_io_w(framedrop_period, vfe_base + 0x518);
		msm_camera_io_w(framedrop_pattern, vfe_base + 0x51C);
		msm_camera_io_w(framedrop_pattern, vfe_base + 0x520);
	}
	msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x260);
	msm_camera_io_w_mb(0x1, vfe_base + 0x260);
}

static void msm_vfe32_clear_framedrop(struct vfe_device *vfe_dev,
@@ -1146,12 +1155,12 @@ static void msm_vfe32_cfg_axi_ub(struct vfe_device *vfe_dev)
		msm_vfe32_cfg_axi_ub_equal_default(vfe_dev);
}

static void msm_vfe32_update_ping_pong_addr(struct vfe_device *vfe_dev,
		uint8_t wm_idx, uint32_t pingpong_status,
		dma_addr_t paddr, int32_t buffer_size)
static void msm_vfe32_update_ping_pong_addr(void __iomem *vfe_base,
	uint8_t wm_idx, uint32_t pingpong_status, dma_addr_t paddr,
	int32_t buf_size)
{
	uint32_t paddr32 = (paddr & 0xFFFFFFFF);
	msm_camera_io_w(paddr32, vfe_dev->vfe_base +
	msm_camera_io_w(paddr32, vfe_base +
		VFE32_PING_PONG_BASE(wm_idx, pingpong_status));
}

@@ -1331,13 +1340,13 @@ static void msm_vfe32_stats_enable_module(struct vfe_device *vfe_dev,
	msm_camera_io_w(module_cfg, vfe_dev->vfe_base + 0x10);
}

static void msm_vfe32_stats_update_ping_pong_addr(struct vfe_device *vfe_dev,
static void msm_vfe32_stats_update_ping_pong_addr(void __iomem *vfe_base,
	struct msm_vfe_stats_stream *stream_info, uint32_t pingpong_status,
	dma_addr_t paddr)
{
	uint32_t paddr32 = (paddr & 0xFFFFFFFF);
	int stats_idx = STATS_IDX(stream_info->stream_handle);
	msm_camera_io_w(paddr32, vfe_dev->vfe_base +
	msm_camera_io_w(paddr32, vfe_base +
		VFE32_STATS_PING_PONG_BASE(stats_idx, pingpong_status));
}

Loading