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

Commit faf4a8b1 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "disp: msm: dsi: add debug ability to read TE read pointer line count"

parents 48da17d6 3deb5c35
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -80,6 +80,10 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
		ctrl->ops.schedule_dma_cmd = NULL;
		ctrl->ops.kickoff_command_non_embedded_mode = NULL;
		ctrl->ops.config_clk_gating = NULL;
		ctrl->ops.configure_cmddma_window = NULL;
		ctrl->ops.reset_trig_ctrl = NULL;
		ctrl->ops.map_mdp_regs = NULL;
		ctrl->ops.log_line_count = NULL;
		break;
	case DSI_CTRL_VERSION_2_0:
		ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map;
@@ -95,6 +99,10 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
		ctrl->ops.schedule_dma_cmd = NULL;
		ctrl->ops.kickoff_command_non_embedded_mode = NULL;
		ctrl->ops.config_clk_gating = NULL;
		ctrl->ops.configure_cmddma_window = NULL;
		ctrl->ops.reset_trig_ctrl = NULL;
		ctrl->ops.map_mdp_regs = NULL;
		ctrl->ops.log_line_count = NULL;
		break;
	case DSI_CTRL_VERSION_2_2:
	case DSI_CTRL_VERSION_2_3:
@@ -116,6 +124,12 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
		ctrl->ops.schedule_dma_cmd = dsi_ctrl_hw_22_schedule_dma_cmd;
		ctrl->ops.kickoff_command_non_embedded_mode =
			dsi_ctrl_hw_kickoff_non_embedded_mode;
		ctrl->ops.configure_cmddma_window =
			dsi_ctrl_hw_22_configure_cmddma_window;
		ctrl->ops.reset_trig_ctrl =
			dsi_ctrl_hw_22_reset_trigger_controls;
		ctrl->ops.map_mdp_regs = dsi_ctrl_hw_22_map_mdp_regs;
		ctrl->ops.log_line_count = dsi_ctrl_hw_22_log_line_count;
		break;
	default:
		break;
+9 −0
Original line number Diff line number Diff line
@@ -274,4 +274,13 @@ void dsi_phy_hw_v4_0_dyn_refresh_pipe_delay(struct dsi_phy_hw *phy,

int dsi_phy_hw_v4_0_cache_phy_timings(struct dsi_phy_per_lane_cfgs *timings,
				      u32 *dst, u32 size);

void dsi_ctrl_hw_22_configure_cmddma_window(struct dsi_ctrl_hw *ctrl,
		struct dsi_ctrl_cmd_dma_info *cmd,
		u32 line_no, u32 window);
void dsi_ctrl_hw_22_reset_trigger_controls(struct dsi_ctrl_hw *ctrl,
				       struct dsi_host_common_cfg *cfg);
int dsi_ctrl_hw_22_map_mdp_regs(struct platform_device *pdev,
		struct dsi_ctrl_hw *ctrl);
u32 dsi_ctrl_hw_22_log_line_count(struct dsi_ctrl_hw *ctrl, bool cmd_mode);
#endif /* _DSI_CATALOG_H_ */
+190 −18
Original line number Diff line number Diff line
@@ -194,6 +194,58 @@ static ssize_t debugfs_reg_dump_read(struct file *file,
	return len;
}

static ssize_t debugfs_line_count_read(struct file *file,
				 char __user *user_buf,
				 size_t user_len,
				 loff_t *ppos)
{
	struct dsi_ctrl *dsi_ctrl = file->private_data;
	char *buf;
	int rc = 0;
	u32 len = 0;
	size_t max_len = min_t(size_t, user_len, SZ_4K);

	if (!dsi_ctrl)
		return -ENODEV;

	if (*ppos)
		return 0;

	buf = kzalloc(max_len, GFP_KERNEL);
	if (ZERO_OR_NULL_PTR(buf))
		return -ENOMEM;

	mutex_lock(&dsi_ctrl->ctrl_lock);

	len += scnprintf(buf, max_len, "Command triggered at line: %04x\n",
			dsi_ctrl->cmd_trigger_line);
	len += scnprintf((buf + len), max_len - len,
			"Command triggered at frame: %04x\n",
			dsi_ctrl->cmd_trigger_frame);
	len += scnprintf((buf + len), max_len - len,
			"Command successful at line: %04x\n",
			dsi_ctrl->cmd_success_line);
	len += scnprintf((buf + len), max_len - len,
			"Command successful at frame: %04x\n",
			dsi_ctrl->cmd_success_frame);

	mutex_unlock(&dsi_ctrl->ctrl_lock);

	if (len > max_len)
		len = max_len;

	if (copy_to_user(user_buf, buf, len)) {
		rc = -EFAULT;
		goto error;
	}

	*ppos += len;

error:
	kfree(buf);
	return len;
}

static const struct file_operations state_info_fops = {
	.open = simple_open,
	.read = debugfs_state_info_read,
@@ -204,11 +256,16 @@ static const struct file_operations reg_dump_fops = {
	.read = debugfs_reg_dump_read,
};

static const struct file_operations cmd_dma_stats_fops = {
	.open = simple_open,
	.read = debugfs_line_count_read,
};

static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl,
				 struct dentry *parent)
{
	int rc = 0;
	struct dentry *dir, *state_file, *reg_dump;
	struct dentry *dir, *state_file, *reg_dump, *cmd_dma_logs;
	char dbg_name[DSI_DEBUG_NAME_LEN];

	if (!dsi_ctrl || !parent) {
@@ -246,6 +303,30 @@ static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl,
		goto error_remove_dir;
	}

	cmd_dma_logs = debugfs_create_bool("enable_cmd_dma_stats",
				       0600,
				       dir,
				       &dsi_ctrl->enable_cmd_dma_stats);
	if (IS_ERR_OR_NULL(cmd_dma_logs)) {
		rc = PTR_ERR(cmd_dma_logs);
		DSI_CTRL_ERR(dsi_ctrl,
				"enable cmd dma stats failed, rc=%d\n",
				rc);
		goto error_remove_dir;
	}

	cmd_dma_logs = debugfs_create_file("cmd_dma_stats",
				       0444,
				       dir,
				       dsi_ctrl,
				       &cmd_dma_stats_fops);
	if (IS_ERR_OR_NULL(cmd_dma_logs)) {
		rc = PTR_ERR(cmd_dma_logs);
		DSI_CTRL_ERR(dsi_ctrl, "Line count file failed, rc=%d\n",
				rc);
		goto error_remove_dir;
	}

	dsi_ctrl->debugfs_root = dir;

	snprintf(dbg_name, DSI_DEBUG_NAME_LEN, "dsi%d_ctrl",
@@ -1177,6 +1258,60 @@ int dsi_message_validate_tx_mode(struct dsi_ctrl *dsi_ctrl,
	return rc;
}

static void dsi_configure_command_scheduling(struct dsi_ctrl *dsi_ctrl,
		struct dsi_ctrl_cmd_dma_info *cmd_mem)
{
	u32 line_no = 0, window = 0, sched_line_no = 0;
	struct dsi_ctrl_hw_ops dsi_hw_ops = dsi_ctrl->hw.ops;
	struct dsi_mode_info *timing = &(dsi_ctrl->host_config.video_timing);

	line_no = dsi_ctrl->host_config.common_config.dma_sched_line;
	window = dsi_ctrl->host_config.common_config.dma_sched_window;

	SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_ENTRY, line_no, window);
	/*
	 * In case of command scheduling in video mode, the line at which
	 * the command is scheduled can revert to the default value i.e. 1
	 * for the following cases:
	 *	1) No schedule line defined by the panel.
	 *	2) schedule line defined is greater than VFP.
	 */
	if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) &&
		dsi_hw_ops.schedule_dma_cmd &&
		(dsi_ctrl->current_state.vid_engine_state ==
					DSI_CTRL_ENGINE_ON)) {
		sched_line_no = (line_no == 0) ? 1 : line_no;

		if (timing) {
			if (sched_line_no >= timing->v_front_porch)
				sched_line_no = 1;
			sched_line_no += timing->v_back_porch +
				timing->v_sync_width + timing->v_active;
		}
		dsi_hw_ops.schedule_dma_cmd(&dsi_ctrl->hw, sched_line_no);
	}

	/*
	 * In case of command scheduling in command mode, the window size
	 * is reset to zero, if the total scheduling window is greater
	 * than the panel height.
	 */
	if ((dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) &&
			dsi_hw_ops.configure_cmddma_window) {
		sched_line_no = line_no;

		if ((sched_line_no + window) > timing->v_active)
			window = 0;

		sched_line_no += timing->v_active;

		dsi_hw_ops.configure_cmddma_window(&dsi_ctrl->hw, cmd_mem,
				sched_line_no, window);
	}
	SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_EXIT,
			sched_line_no, window);
}

static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
				const struct mipi_dsi_msg *msg,
				struct dsi_ctrl_cmd_dma_fifo_info *cmd,
@@ -1184,27 +1319,20 @@ static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
				u32 flags)
{
	u32 hw_flags = 0;
	u32 line_no = 0x1;
	struct dsi_mode_info *timing;
	struct dsi_ctrl_hw_ops dsi_hw_ops = dsi_ctrl->hw.ops;

	SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_ENTRY, flags);
	/* check if custom dma scheduling line needed */
	if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) &&
		(flags & DSI_CTRL_CMD_CUSTOM_DMA_SCHED))
		line_no = dsi_ctrl->host_config.u.video_engine.dma_sched_line;

	timing = &(dsi_ctrl->host_config.video_timing);
	if (timing)
		line_no += timing->v_back_porch + timing->v_sync_width +
				timing->v_active;
	if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) &&
		dsi_hw_ops.schedule_dma_cmd &&
		(dsi_ctrl->current_state.vid_engine_state ==
					DSI_CTRL_ENGINE_ON))
		dsi_hw_ops.schedule_dma_cmd(&dsi_ctrl->hw,
				line_no);
	if (dsi_ctrl->hw.reset_trig_ctrl)
		dsi_hw_ops.reset_trig_ctrl(&dsi_ctrl->hw,
				&dsi_ctrl->host_config.common_config);

	/* check if custom dma scheduling line needed */
	if (flags & DSI_CTRL_CMD_CUSTOM_DMA_SCHED)
		dsi_configure_command_scheduling(dsi_ctrl, cmd_mem);

	dsi_ctrl->cmd_mode = (dsi_ctrl->host_config.panel_mode ==
			DSI_OP_CMD_MODE);
	hw_flags |= (flags & DSI_CTRL_CMD_DEFER_TRIGGER) ?
			DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER : 0;

@@ -1259,6 +1387,17 @@ static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
							      cmd,
							      hw_flags);
		}

		if (dsi_ctrl->enable_cmd_dma_stats) {
			u32 reg = dsi_hw_ops.log_line_count(&dsi_ctrl->hw,
					dsi_ctrl->cmd_mode);
			dsi_ctrl->cmd_trigger_line = (reg & 0xFFFF);
			dsi_ctrl->cmd_trigger_frame = ((reg >> 16) & 0xFFFF);
			SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_CASE1,
					dsi_ctrl->cmd_trigger_line,
					dsi_ctrl->cmd_trigger_frame);
		}

		if (flags & DSI_CTRL_CMD_ASYNC_WAIT) {
			dsi_ctrl->dma_wait_queued = true;
			queue_work(dsi_ctrl->dma_cmd_workq,
@@ -1921,6 +2060,9 @@ static int dsi_ctrl_dev_probe(struct platform_device *pdev)
		goto fail_clks;
	}

	if (dsi_ctrl->hw.ops.map_mdp_regs)
		dsi_ctrl->hw.ops.map_mdp_regs(pdev, &dsi_ctrl->hw);

	item->ctrl = dsi_ctrl;
	sde_dbg_dsi_ctrl_register(dsi_ctrl->hw.base, dsi_ctrl->name);

@@ -2584,6 +2726,15 @@ static irqreturn_t dsi_ctrl_isr(int irq, void *ptr)
		dsi_ctrl_handle_error_status(dsi_ctrl, errors);

	if (status & DSI_CMD_MODE_DMA_DONE) {
		if (dsi_ctrl->enable_cmd_dma_stats) {
			u32 reg = dsi_ctrl->hw.ops.log_line_count(&dsi_ctrl->hw,
						dsi_ctrl->cmd_mode);
			dsi_ctrl->cmd_success_line = (reg & 0xFFFF);
			dsi_ctrl->cmd_success_frame = ((reg >> 16) & 0xFFFF);
			SDE_EVT32(dsi_ctrl->cell_index,	SDE_EVTLOG_FUNC_CASE1,
					dsi_ctrl->cmd_success_line,
					dsi_ctrl->cmd_success_frame);
		}
		atomic_set(&dsi_ctrl->dma_irq_trig, 1);
		dsi_ctrl_disable_status_interrupt(dsi_ctrl,
					DSI_SINT_CMD_MODE_DMA_DONE);
@@ -3191,8 +3342,18 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)

	mutex_lock(&dsi_ctrl->ctrl_lock);

	if (!(flags & DSI_CTRL_CMD_BROADCAST_MASTER))
	if (!(flags & DSI_CTRL_CMD_BROADCAST_MASTER)) {
		dsi_hw_ops.trigger_command_dma(&dsi_ctrl->hw);
		if (dsi_ctrl->enable_cmd_dma_stats) {
			u32 reg = dsi_hw_ops.log_line_count(&dsi_ctrl->hw,
					dsi_ctrl->cmd_mode);
			dsi_ctrl->cmd_trigger_line = (reg & 0xFFFF);
			dsi_ctrl->cmd_trigger_frame = ((reg >> 16) & 0xFFFF);
			SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_CASE1,
					dsi_ctrl->cmd_trigger_line,
					dsi_ctrl->cmd_trigger_frame);
		}
	}

	if ((flags & DSI_CTRL_CMD_BROADCAST) &&
		(flags & DSI_CTRL_CMD_BROADCAST_MASTER)) {
@@ -3207,6 +3368,17 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)

		/* trigger command */
		dsi_hw_ops.trigger_command_dma(&dsi_ctrl->hw);

		if (dsi_ctrl->enable_cmd_dma_stats) {
			u32 reg = dsi_hw_ops.log_line_count(&dsi_ctrl->hw,
					dsi_ctrl->cmd_mode);
			dsi_ctrl->cmd_trigger_line = (reg & 0xFFFF);
			dsi_ctrl->cmd_trigger_frame = ((reg >> 16) & 0xFFFF);
			SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_CASE1,
					dsi_ctrl->cmd_trigger_line,
					dsi_ctrl->cmd_trigger_frame);
		}

		if (flags & DSI_CTRL_CMD_ASYNC_WAIT) {
			dsi_ctrl->dma_wait_queued = true;
			queue_work(dsi_ctrl->dma_cmd_workq,
+19 −0
Original line number Diff line number Diff line
@@ -229,6 +229,19 @@ struct dsi_ctrl_interrupts {
 *                           insert null packet.
 * @modeupdated:	  Boolean to send new roi if mode is updated.
 * @split_link_supported: Boolean to check if hw supports split link.
 * @enable_cmd_dma_stats: Boolean to indicate the verbose logging during
 *				CMD transfer.
 *				count.
 * @cmd_mode:			Boolean to indicate if panel is running in
 *				command mode.
 * @cmd_trigger_line:		unsigned integer that indicates the line at
 *				which command gets triggered.
 * @cmd_trigger_frame:		unsigned integer that indicates the frame at
 *				which command gets triggered.
 * @cmd_success_line:		unsigned integer that indicates the line at
 *				which command transfer is successful.
 * @cmd_success_frame:		unsigned integer that indicates the frame at
 *				which command transfer is successful.
 */
struct dsi_ctrl {
	struct platform_device *pdev;
@@ -289,6 +302,12 @@ struct dsi_ctrl {
	bool null_insertion_enabled;
	bool modeupdated;
	bool split_link_supported;
	bool enable_cmd_dma_stats;
	bool cmd_mode;
	u32 cmd_trigger_line;
	u32 cmd_trigger_frame;
	u32 cmd_success_line;
	u32 cmd_success_frame;
};

/**
+47 −0
Original line number Diff line number Diff line
@@ -831,6 +831,41 @@ struct dsi_ctrl_hw_ops {
	 * @sel_phy:	Bool to control whether to select phy or controller
	 */
	void (*hs_req_sel)(struct dsi_ctrl_hw *ctrl, bool sel_phy);

	/**
	 * hw.ops.configure_cmddma_window() - configure DMA window for CMD TX
	 * @ctrl:	Pointer to the controller host hardware.
	 * @cmd:	Pointer to the DSI DMA command info.
	 * @line_no:	Line number at which the CMD needs to be triggered.
	 * @window:	Width of the DMA CMD window.
	 */
	void (*configure_cmddma_window)(struct dsi_ctrl_hw *ctrl,
			struct dsi_ctrl_cmd_dma_info *cmd,
			u32 line_no, u32 window);

	/**
	 * hw.ops.reset_trig_ctrl() - resets trigger control of DSI controller
	 * @ctrl:	Pointer to the controller host hardware.
	 * @cfg:	Common configuration parameters.
	 */
	void (*reset_trig_ctrl)(struct dsi_ctrl_hw *ctrl,
			struct dsi_host_common_cfg *cfg);

	/**
	 * hw.ops.map_mdp_regs() - maps MDP interface line count registers.
	 * @pdev:	Pointer to platform device.
	 * @ctrl:	Pointer to the controller host hardware.
	 */
	int (*map_mdp_regs)(struct platform_device *pdev,
			struct dsi_ctrl_hw *ctrl);

	/**
	 * hw.ops.log_line_count() - reads the MDP interface line count
	 *			     registers.
	 * @ctrl:	Pointer to the controller host hardware.
	 * @cmd_mode:	Boolean to indicate command mode operation.
	 */
	u32 (*log_line_count)(struct dsi_ctrl_hw *ctrl, bool cmd_mode);
};

/*
@@ -841,6 +876,13 @@ struct dsi_ctrl_hw_ops {
 * @mmss_misc_length:       Length of mmss_misc register map.
 * @disp_cc_base:           Base address of disp_cc register map.
 * @disp_cc_length:         Length of disp_cc register map.
 * @te_rd_ptr_reg:	    Address of MDP_TEAR_INTF_TEAR_LINE_COUNT. This
 *			    register is used for testing and validating the RD
 *			    ptr value when a CMD is triggered and it succeeds.
 * @line_count_reg:	    Address of MDP_TEAR_INTF_LINE_COUNT. This
 *			    register is used for testing and validating the
 *			    line count value when a CMD is triggered and it
 *			    succeeds.
 * @index:                  Instance ID of the controller.
 * @feature_map:            Features supported by the DSI controller.
 * @ops:                    Function pointers to the operations supported by the
@@ -852,6 +894,8 @@ struct dsi_ctrl_hw_ops {
 * @null_insertion_enabled:  A boolean property to allow dsi controller to
 *                           insert null packet.
 * @widebus_support:        48 bit wide data bus is supported.
 * @reset_trig_ctrl:		Boolean to indicate if trigger control needs to
 *				be reset to default.
 */
struct dsi_ctrl_hw {
	void __iomem *base;
@@ -859,6 +903,8 @@ struct dsi_ctrl_hw {
	void __iomem *mmss_misc_base;
	u32 mmss_misc_length;
	void __iomem *disp_cc_base;
	void __iomem *te_rd_ptr_reg;
	void __iomem *line_count_reg;
	u32 disp_cc_length;
	u32 index;

@@ -873,6 +919,7 @@ struct dsi_ctrl_hw {
	bool phy_isolation_enabled;
	bool null_insertion_enabled;
	bool widebus_support;
	bool reset_trig_ctrl;
};

#endif /* _DSI_CTRL_HW_H_ */
Loading