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

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

Merge "disp: msm: read mdp intf line count and trigger dma accordingly"

parents 1fb3bd16 beea6cd2
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/errno.h>
@@ -81,6 +81,8 @@ 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.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;
@@ -96,6 +98,8 @@ 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.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 +120,8 @@ 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.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;
+6 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _DSI_CATALOG_H_
@@ -270,4 +270,9 @@ 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);

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_ */
+71 −10
Original line number Diff line number Diff line
@@ -1219,6 +1219,24 @@ int dsi_message_validate_tx_mode(struct dsi_ctrl *dsi_ctrl,

	return rc;
}
static u32 calculate_schedule_line(struct dsi_ctrl *dsi_ctrl, u32 flags)
{
	u32 line_no = 0x1;
	struct dsi_mode_info *timing;

	/* 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;

	return line_no;
}

static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
				const struct mipi_dsi_msg *msg,
@@ -1228,20 +1246,13 @@ static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
{
	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,
		msg->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;
	line_no = calculate_schedule_line(dsi_ctrl, flags);

	if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) &&
		dsi_hw_ops.schedule_dma_cmd &&
		(dsi_ctrl->current_state.vid_engine_state ==
@@ -1249,6 +1260,8 @@ static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
		dsi_hw_ops.schedule_dma_cmd(&dsi_ctrl->hw,
				line_no);

	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;

@@ -1967,6 +1980,9 @@ static int dsi_ctrl_dev_probe(struct platform_device *pdev)
		DSI_CTRL_DEBUG(dsi_ctrl, "failed to init axi bus client, rc = %d\n",
				rc);

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

	item->ctrl = dsi_ctrl;

	mutex_lock(&dsi_ctrl_list_lock);
@@ -3298,6 +3314,10 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)
{
	int rc = 0;
	struct dsi_ctrl_hw_ops dsi_hw_ops;
	u32 v_total = 0, fps = 0, cur_line = 0, mem_latency_us = 100;
	u32 line_time = 0, schedule_line = 0x1, latency_by_line = 0;
	struct dsi_mode_info *timing;
	unsigned long flag;

	if (!dsi_ctrl) {
		DSI_CTRL_ERR(dsi_ctrl, "Invalid params\n");
@@ -3313,6 +3333,18 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)

	mutex_lock(&dsi_ctrl->ctrl_lock);

	timing = &(dsi_ctrl->host_config.video_timing);

	if (timing &&
		(dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE)) {
		v_total = timing->v_sync_width + timing->v_back_porch +
			timing->v_front_porch + timing->v_active;
		fps = timing->refresh_rate;
		schedule_line = calculate_schedule_line(dsi_ctrl, flags);
		line_time = (1000000 / fps) / v_total;
		latency_by_line = CEIL(mem_latency_us, line_time);
	}

	if (!(flags & DSI_CTRL_CMD_BROADCAST_MASTER))
		dsi_hw_ops.trigger_command_dma(&dsi_ctrl->hw);

@@ -3325,7 +3357,36 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)
		reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done);

		/* trigger command */
		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)) {
			/*
			 * This change reads the video line count from
			 * MDP_INTF_LINE_COUNT register and checks whether
			 * DMA trigger happens close to the schedule line.
			 * If it is not close to the schedule line, then DMA
			 * command transfer is triggered.
			 */
			while (1) {
				local_irq_save(flag);
				cur_line =
				dsi_hw_ops.log_line_count(&dsi_ctrl->hw,
					dsi_ctrl->cmd_mode);
				if (cur_line <
					(schedule_line - latency_by_line) ||
					cur_line > (schedule_line + 1)) {
					dsi_hw_ops.trigger_command_dma(
						&dsi_ctrl->hw);
					local_irq_restore(flag);
					break;
				}
				local_irq_restore(flag);
				udelay(1000);
			}
		} else
			dsi_hw_ops.trigger_command_dma(&dsi_ctrl->hw);

		if (flags & DSI_CTRL_CMD_ASYNC_WAIT) {
			dsi_ctrl->dma_wait_queued = true;
			queue_work(dsi_ctrl->dma_cmd_workq,
+3 −0
Original line number Diff line number Diff line
@@ -239,6 +239,8 @@ 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.
 * @cmd_mode:		Boolean to indicate if panel is running in
			command mode.
 */
struct dsi_ctrl {
	struct platform_device *pdev;
@@ -299,6 +301,7 @@ struct dsi_ctrl {
	bool null_insertion_enabled;
	bool modeupdated;
	bool split_link_supported;
	bool cmd_mode;
};

/**
+25 −0
Original line number Diff line number Diff line
@@ -838,6 +838,22 @@ 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.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);
};

/*
@@ -848,6 +864,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
@@ -865,6 +888,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;

Loading