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

Commit 4b9f2a23 authored by Govinda Rajulu Chenna's avatar Govinda Rajulu Chenna
Browse files

drm/msm/sde: use intf te in sde encoder for sde 5.0.0



sde encoder module depends on SDE_INTF_TE flag to route
the te configuration to either hw_intf or hw_pp module.
This change enables SDE_INTF_TE flag for sde 5.0.0 and
also implements the te ops routing call based on this flag.
This change configures vsync selection for intf te.

Change-Id: I21427bea6855ce197eda92bfd2bb02926727700f
Signed-off-by: default avatarGovinda Rajulu Chenna <gchenna@codeaurora.org>
parent bd4c3359
Loading
Loading
Loading
Loading
+43 −12
Original line number Diff line number Diff line
@@ -1558,8 +1558,8 @@ static int _sde_encoder_dsc_setup(struct sde_encoder_virt *sde_enc,
	return ret;
}

static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
			struct msm_display_info *disp_info, bool is_dummy)
void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc,
			u32 vsync_source, bool is_dummy)
{
	struct sde_vsync_source_cfg vsync_cfg = { 0 };
	struct msm_drm_private *priv;
@@ -1567,11 +1567,11 @@ static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
	struct sde_hw_mdp *hw_mdptop;
	struct drm_encoder *drm_enc;
	struct msm_mode_info mode_info;
	struct sde_encoder_virt *sde_enc;
	int i, rc = 0;

	if (!sde_enc || !disp_info) {
		SDE_ERROR("invalid param sde_enc:%d or disp_info:%d\n",
					sde_enc != NULL, disp_info != NULL);
	if (!sde_enc) {
		SDE_ERROR("invalid param sde_enc:%d\n", sde_enc != NULL);
		return;
	} else if (sde_enc->num_phys_encs > ARRAY_SIZE(sde_enc->hw_pp)) {
		SDE_ERROR("invalid num phys enc %d/%d\n",
@@ -1580,6 +1580,8 @@ static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
		return;
	}

	sde_enc = to_sde_encoder_virt(phys_enc->parent);

	drm_enc = &sde_enc->base;
	/* this pointers are checked in virt_enable_helper */
	priv = drm_enc->dev->dev_private;
@@ -1602,22 +1604,51 @@ static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
		return;
	}

	if (hw_mdptop->ops.setup_vsync_source &&
			disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) {
	if (hw_mdptop->ops.setup_vsync_source) {
		for (i = 0; i < sde_enc->num_phys_encs; i++)
			vsync_cfg.ppnumber[i] = sde_enc->hw_pp[i]->idx;

		vsync_cfg.pp_count = sde_enc->num_phys_encs;
		vsync_cfg.frame_rate = mode_info.frame_rate;
		vsync_cfg.is_dummy = is_dummy;

		hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg);
	}
}

static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
			struct msm_display_info *disp_info, bool is_dummy)
{
	struct sde_encoder_phys *phys;
	int i, rc = 0;
	u32 vsync_source;

	if (!sde_enc || !disp_info) {
		SDE_ERROR("invalid param sde_enc:%d or disp_info:%d\n",
					sde_enc != NULL, disp_info != NULL);
		return;
	} else if (sde_enc->num_phys_encs > ARRAY_SIZE(sde_enc->hw_pp)) {
		SDE_ERROR("invalid num phys enc %d/%d\n",
				sde_enc->num_phys_encs,
				(int) ARRAY_SIZE(sde_enc->hw_pp));
		return;
	}

	if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) {
		if (is_dummy)
			vsync_cfg.vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_1;
			vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_1;
		else if (disp_info->is_te_using_watchdog_timer)
			vsync_cfg.vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_0;
			vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_0;
		else
			vsync_cfg.vsync_source = SDE_VSYNC0_SOURCE_GPIO;
		vsync_cfg.is_dummy = is_dummy;
			vsync_source = SDE_VSYNC0_SOURCE_GPIO;

		hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg);
		for (i = 0; i < sde_enc->num_phys_encs; i++) {
			phys = sde_enc->phys_encs[i];

			if (phys && phys->ops.setup_vsync_source)
				phys->ops.setup_vsync_source(phys,
					vsync_source, is_dummy);
		}
	}
}

+15 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -137,6 +137,7 @@ struct sde_encoder_virt_ops {
 * @wait_dma_trigger:		Returns true if lut dma has to trigger and wait
 *                              unitl transaction is complete.
 * @wait_for_active:		Wait for display scan line to be in active area
 * @setup_vsync_source:		Configure vsync source selection for cmd mode.
 */

struct sde_encoder_phys_ops {
@@ -186,6 +187,8 @@ struct sde_encoder_phys_ops {
	int (*get_wr_line_count)(struct sde_encoder_phys *phys);
	bool (*wait_dma_trigger)(struct sde_encoder_phys *phys);
	int (*wait_for_active)(struct sde_encoder_phys *phys);
	void (*setup_vsync_source)(struct sde_encoder_phys *phys,
			u32 vsync_source, bool is_dummy);
};

/**
@@ -265,6 +268,7 @@ struct sde_encoder_irq {
 *                              fences that have to be signalled.
 * @pending_kickoff_wq:		Wait queue for blocking until kickoff completes
 * @irq:			IRQ tracking structures
 * @has_intf_te:		Interface TE configuration support
 */
struct sde_encoder_phys {
	struct drm_encoder *parent;
@@ -295,6 +299,7 @@ struct sde_encoder_phys {
	atomic_t pending_retire_fence_cnt;
	wait_queue_head_t pending_kickoff_wq;
	struct sde_encoder_irq irq[INTR_IDX_MAX];
	bool has_intf_te;
};

static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys)
@@ -497,6 +502,15 @@ void sde_encoder_helper_trigger_flush(struct sde_encoder_phys *phys_enc);
 */
void sde_encoder_helper_trigger_start(struct sde_encoder_phys *phys_enc);

/**
 * sde_encoder_helper_vsync_config - configure vsync source for cmd mode
 * @phys_enc: Pointer to physical encoder structure
 * @vsync_source: vsync source selection
 * @is_dummy: used only for RSC
 */
void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc,
			u32 vsync_source, bool is_dummy);

/**
 * sde_encoder_helper_wait_event_timeout - wait for event with timeout
 *	taking into account that jiffies may jump between reads leading to
+216 −69
Original line number Diff line number Diff line
@@ -93,10 +93,11 @@ static void _sde_encoder_phys_cmd_config_autorefresh(
	struct sde_encoder_phys_cmd *cmd_enc =
			to_sde_encoder_phys_cmd(phys_enc);
	struct sde_hw_pingpong *hw_pp = phys_enc->hw_pp;
	struct sde_hw_intf *hw_intf = phys_enc->hw_intf;
	struct drm_connector *conn = phys_enc->connector;
	struct sde_hw_autorefresh *cfg_cur, cfg_nxt;

	if (!conn || !conn->state || !hw_pp)
	if (!conn || !conn->state || !hw_pp || !hw_intf)
		return;

	cfg_cur = &cmd_enc->autorefresh.cfg;
@@ -108,15 +109,18 @@ static void _sde_encoder_phys_cmd_config_autorefresh(

	SDE_DEBUG_CMDENC(cmd_enc, "autorefresh state %d->%d framecount %d\n",
			cfg_cur->enable, cfg_nxt.enable, cfg_nxt.frame_count);
	SDE_EVT32(DRMID(phys_enc->parent), hw_pp->idx, cfg_cur->enable,
			cfg_nxt.enable, cfg_nxt.frame_count);
	SDE_EVT32(DRMID(phys_enc->parent), hw_pp->idx, hw_intf->idx,
			cfg_cur->enable, cfg_nxt.enable, cfg_nxt.frame_count);

	/* only proceed on state changes */
	if (cfg_nxt.enable == cfg_cur->enable)
		return;

	memcpy(cfg_cur, &cfg_nxt, sizeof(*cfg_cur));
	if (hw_pp->ops.setup_autorefresh)

	if (phys_enc->has_intf_te && hw_intf->ops.setup_autorefresh)
		hw_intf->ops.setup_autorefresh(hw_intf, cfg_cur);
	else if (hw_pp->ops.setup_autorefresh)
		hw_pp->ops.setup_autorefresh(hw_pp, cfg_cur);
}

@@ -256,13 +260,13 @@ static void sde_encoder_phys_cmd_autorefresh_done_irq(void *arg, int irq_idx)
	wake_up_all(&cmd_enc->autorefresh.kickoff_wq);
}

static void sde_encoder_phys_cmd_pp_rd_ptr_irq(void *arg, int irq_idx)
static void sde_encoder_phys_cmd_te_rd_ptr_irq(void *arg, int irq_idx)
{
	struct sde_encoder_phys *phys_enc = arg;
	struct sde_encoder_phys_cmd *cmd_enc;
	u32 event = 0;

	if (!phys_enc || !phys_enc->hw_pp)
	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf)
		return;

	SDE_ATRACE_BEGIN("rd_ptr_irq");
@@ -284,7 +288,9 @@ static void sde_encoder_phys_cmd_pp_rd_ptr_irq(void *arg, int irq_idx)
	}

	SDE_EVT32_IRQ(DRMID(phys_enc->parent),
			phys_enc->hw_pp->idx - PINGPONG_0, event, 0xfff);
			phys_enc->hw_pp->idx - PINGPONG_0,
			phys_enc->hw_intf->idx - INTF_0,
			event, 0xfff);

	if (phys_enc->parent_ops.handle_vblank_virt)
		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
@@ -370,6 +376,9 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
{
	struct sde_encoder_irq *irq;

	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf)
		return;

	irq = &phys_enc->irq[INTR_IDX_CTL_START];
	irq->hw_idx = phys_enc->hw_ctl->idx;
	irq->irq_idx = -EINVAL;
@@ -379,16 +388,22 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
	irq->irq_idx = -EINVAL;

	irq = &phys_enc->irq[INTR_IDX_RDPTR];
	irq->hw_idx = phys_enc->hw_pp->idx;
	irq->irq_idx = -EINVAL;
	if (phys_enc->has_intf_te)
		irq->hw_idx = phys_enc->hw_intf->idx;
	else
		irq->hw_idx = phys_enc->hw_pp->idx;

	irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
	irq->hw_idx = phys_enc->intf_idx;
	irq->irq_idx = -EINVAL;

	irq = &phys_enc->irq[INTR_IDX_AUTOREFRESH_DONE];
	irq->hw_idx = phys_enc->hw_pp->idx;
	irq->irq_idx = -EINVAL;
	if (phys_enc->has_intf_te)
		irq->hw_idx = phys_enc->hw_intf->idx;
	else
		irq->hw_idx = phys_enc->hw_pp->idx;
}

static void sde_encoder_phys_cmd_cont_splash_mode_set(
@@ -535,36 +550,58 @@ static int _sde_encoder_phys_cmd_poll_write_pointer_started(
	struct sde_encoder_phys_cmd *cmd_enc =
			to_sde_encoder_phys_cmd(phys_enc);
	struct sde_hw_pingpong *hw_pp = phys_enc->hw_pp;
	struct sde_hw_intf *hw_intf = phys_enc->hw_intf;
	struct sde_hw_pp_vsync_info info;
	u32 timeout_us = SDE_ENC_WR_PTR_START_TIMEOUT_US;
	int ret;
	int ret = 0;

	if (!hw_pp || !hw_pp->ops.get_vsync_info ||
			!hw_pp->ops.poll_timeout_wr_ptr)
	if (!hw_pp || !hw_intf)
		return 0;

	if (phys_enc->has_intf_te) {
		if (!hw_intf->ops.get_vsync_info ||
				!hw_intf->ops.poll_timeout_wr_ptr)
			goto end;
	} else {
		if (!hw_pp->ops.get_vsync_info ||
				!hw_pp->ops.poll_timeout_wr_ptr)
			goto end;
	}

	if (phys_enc->has_intf_te)
		ret = hw_intf->ops.get_vsync_info(hw_intf, &info);
	else
		ret = hw_pp->ops.get_vsync_info(hw_pp, &info);

	if (ret)
		return ret;

	SDE_DEBUG_CMDENC(cmd_enc,
			"pp:%d rd_ptr %d wr_ptr %d\n",
			"pp:%d intf:%d rd_ptr %d wr_ptr %d\n",
			phys_enc->hw_pp->idx - PINGPONG_0,
			phys_enc->hw_intf->idx - INTF_0,
			info.rd_ptr_line_count,
			info.wr_ptr_line_count);
	SDE_EVT32_VERBOSE(DRMID(phys_enc->parent),
			phys_enc->hw_pp->idx - PINGPONG_0,
			phys_enc->hw_intf->idx - INTF_0,
			info.wr_ptr_line_count);

	if (phys_enc->has_intf_te)
		ret = hw_intf->ops.poll_timeout_wr_ptr(hw_intf, timeout_us);
	else
		ret = hw_pp->ops.poll_timeout_wr_ptr(hw_pp, timeout_us);

	if (ret) {
		SDE_EVT32(DRMID(phys_enc->parent),
				phys_enc->hw_pp->idx - PINGPONG_0,
				phys_enc->hw_intf->idx - INTF_0,
				timeout_us,
				ret);
		SDE_DBG_DUMP("all", "dbg_bus", "vbif_dbg_bus", "panic");
	}

end:
	return ret;
}

@@ -573,18 +610,28 @@ static bool _sde_encoder_phys_cmd_is_ongoing_pptx(
{
	struct sde_hw_pingpong *hw_pp;
	struct sde_hw_pp_vsync_info info;
	struct sde_hw_intf *hw_intf;

	if (!phys_enc)
		return false;

	if (phys_enc->has_intf_te) {
		hw_intf = phys_enc->hw_intf;
		if (!hw_intf || !hw_intf->ops.get_vsync_info)
			return false;

		hw_intf->ops.get_vsync_info(hw_intf, &info);
	} else {
		hw_pp = phys_enc->hw_pp;
		if (!hw_pp || !hw_pp->ops.get_vsync_info)
			return false;

		hw_pp->ops.get_vsync_info(hw_pp, &info);
	}

	SDE_EVT32(DRMID(phys_enc->parent),
			phys_enc->hw_pp->idx - PINGPONG_0,
			phys_enc->hw_intf->idx - INTF_0,
			atomic_read(&phys_enc->pending_kickoff_cnt),
			info.wr_ptr_line_count,
			phys_enc->cached_mode.vdisplay);
@@ -772,19 +819,29 @@ static void sde_encoder_phys_cmd_tearcheck_config(
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;

	if (!phys_enc || !phys_enc->hw_pp) {
	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf) {
		SDE_ERROR("invalid encoder\n");
		return;
	}
	mode = &phys_enc->cached_mode;

	SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
	SDE_DEBUG_CMDENC(cmd_enc, "pp %d, intf %d\n",
			phys_enc->hw_pp->idx - PINGPONG_0,
			phys_enc->hw_intf->idx - INTF_0);

	if (phys_enc->has_intf_te) {
		if (!phys_enc->hw_intf->ops.setup_tearcheck ||
			!phys_enc->hw_intf->ops.enable_tearcheck) {
			SDE_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n");
			return;
		}
	} else {
		if (!phys_enc->hw_pp->ops.setup_tearcheck ||
			!phys_enc->hw_pp->ops.enable_tearcheck) {
			SDE_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n");
			return;
		}
	}

	sde_kms = phys_enc->sde_kms;
	if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev_private) {
@@ -828,24 +885,38 @@ static void sde_encoder_phys_cmd_tearcheck_config(
	tc_cfg.rd_ptr_irq = mode->vdisplay + 1;

	SDE_DEBUG_CMDENC(cmd_enc,
		"tc %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n",
		phys_enc->hw_pp->idx - PINGPONG_0, vsync_hz,
		mode->vtotal, mode->vrefresh);
		"tc %d intf %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n",
		phys_enc->hw_pp->idx - PINGPONG_0,
		phys_enc->hw_intf->idx - INTF_0,
		vsync_hz, mode->vtotal, mode->vrefresh);
	SDE_DEBUG_CMDENC(cmd_enc,
		"tc %d enable %u start_pos %u rd_ptr_irq %u\n",
		phys_enc->hw_pp->idx - PINGPONG_0, tc_enable, tc_cfg.start_pos,
		tc_cfg.rd_ptr_irq);
		"tc %d intf %d enable %u start_pos %u rd_ptr_irq %u\n",
		phys_enc->hw_pp->idx - PINGPONG_0,
		phys_enc->hw_intf->idx - INTF_0,
		tc_enable, tc_cfg.start_pos, tc_cfg.rd_ptr_irq);
	SDE_DEBUG_CMDENC(cmd_enc,
		"tc %d hw_vsync_mode %u vsync_count %u vsync_init_val %u\n",
		phys_enc->hw_pp->idx - PINGPONG_0, tc_cfg.hw_vsync_mode,
		tc_cfg.vsync_count, tc_cfg.vsync_init_val);
		"tc %d intf %d hw_vsync_mode %u vsync_count %u vsync_init_val %u\n",
		phys_enc->hw_pp->idx - PINGPONG_0,
		phys_enc->hw_intf->idx - INTF_0,
		tc_cfg.hw_vsync_mode, tc_cfg.vsync_count,
		tc_cfg.vsync_init_val);
	SDE_DEBUG_CMDENC(cmd_enc,
		"tc %d cfgheight %u thresh_start %u thresh_cont %u\n",
		phys_enc->hw_pp->idx - PINGPONG_0, tc_cfg.sync_cfg_height,
		"tc %d intf %d cfgheight %u thresh_start %u thresh_cont %u\n",
		phys_enc->hw_pp->idx - PINGPONG_0,
		phys_enc->hw_intf->idx - INTF_0,
		tc_cfg.sync_cfg_height,
		tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue);

	if (phys_enc->has_intf_te) {
		phys_enc->hw_intf->ops.setup_tearcheck(phys_enc->hw_intf,
				&tc_cfg);
		phys_enc->hw_intf->ops.enable_tearcheck(phys_enc->hw_intf,
				tc_enable);
	} else {
		phys_enc->hw_pp->ops.setup_tearcheck(phys_enc->hw_pp, &tc_cfg);
	phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, tc_enable);
		phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp,
				tc_enable);
	}
}

static void _sde_encoder_phys_cmd_pingpong_config(
@@ -920,20 +991,30 @@ static bool sde_encoder_phys_cmd_is_autorefresh_enabled(
		struct sde_encoder_phys *phys_enc)
{
	struct sde_hw_pingpong *hw_pp;
	struct sde_hw_intf *hw_intf;
	struct sde_hw_autorefresh cfg;
	int ret;

	if (!phys_enc || !phys_enc->hw_pp)
	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf)
		return 0;

	if (!sde_encoder_phys_cmd_is_master(phys_enc))
		return 0;

	if (phys_enc->has_intf_te) {
		hw_intf = phys_enc->hw_intf;
		if (!hw_intf->ops.get_autorefresh)
			return 0;

		ret = hw_intf->ops.get_autorefresh(hw_intf, &cfg);
	} else {
		hw_pp = phys_enc->hw_pp;
		if (!hw_pp->ops.get_autorefresh)
			return 0;

		ret = hw_pp->ops.get_autorefresh(hw_pp, &cfg);
	}

	if (ret)
		return 0;

@@ -943,50 +1024,78 @@ static bool sde_encoder_phys_cmd_is_autorefresh_enabled(
static void sde_encoder_phys_cmd_connect_te(
		struct sde_encoder_phys *phys_enc, bool enable)
{
	if (!phys_enc || !phys_enc->hw_pp ||
	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf ||
			!phys_enc->hw_pp->ops.connect_external_te)
		return;

	SDE_EVT32(DRMID(phys_enc->parent), enable);
	phys_enc->hw_pp->ops.connect_external_te(phys_enc->hw_pp, enable);

	if (phys_enc->has_intf_te)
		phys_enc->hw_intf->ops.connect_external_te(phys_enc->hw_intf,
				enable);
	else
		phys_enc->hw_pp->ops.connect_external_te(phys_enc->hw_pp,
				enable);
}

static int sde_encoder_phys_cmd_get_line_count(
static int sde_encoder_phys_cmd_te_get_line_count(
		struct sde_encoder_phys *phys_enc)
{
	struct sde_hw_pingpong *hw_pp;
	struct sde_hw_intf *hw_intf;
	u32 line_count;

	if (!phys_enc || !phys_enc->hw_pp)
	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf)
		return -EINVAL;

	if (!sde_encoder_phys_cmd_is_master(phys_enc))
		return -EINVAL;

	if (phys_enc->has_intf_te) {
		hw_intf = phys_enc->hw_intf;
		if (!hw_intf->ops.get_line_count)
			return -EINVAL;

		line_count = hw_intf->ops.get_line_count(hw_intf);
	} else {
		hw_pp = phys_enc->hw_pp;
		if (!hw_pp->ops.get_line_count)
			return -EINVAL;

	return hw_pp->ops.get_line_count(hw_pp);
		line_count = hw_pp->ops.get_line_count(hw_pp);
	}

	return line_count;
}

static int sde_encoder_phys_cmd_get_write_line_count(
		struct sde_encoder_phys *phys_enc)
{
	struct sde_hw_pingpong *hw_pp;
	struct sde_hw_intf *hw_intf;
	struct sde_hw_pp_vsync_info info;

	if (!phys_enc || !phys_enc->hw_pp)
	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf)
		return -EINVAL;

	if (!sde_encoder_phys_cmd_is_master(phys_enc))
		return -EINVAL;

	if (phys_enc->has_intf_te) {
		hw_intf = phys_enc->hw_intf;
		if (!hw_intf->ops.get_vsync_info)
			return -EINVAL;

		if (hw_intf->ops.get_vsync_info(hw_intf, &info))
			return -EINVAL;
	} else {
		hw_pp = phys_enc->hw_pp;
		if (!hw_pp->ops.get_vsync_info)
			return -EINVAL;

		if (hw_pp->ops.get_vsync_info(hw_pp, &info))
			return -EINVAL;
	}

	return (int)info.wr_ptr_line_count;
}
@@ -996,14 +1105,16 @@ static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc)
	struct sde_encoder_phys_cmd *cmd_enc =
		to_sde_encoder_phys_cmd(phys_enc);

	if (!phys_enc || !phys_enc->hw_pp) {
	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf) {
		SDE_ERROR("invalid encoder\n");
		return;
	}
	SDE_DEBUG_CMDENC(cmd_enc, "pp %d state %d\n",
	SDE_DEBUG_CMDENC(cmd_enc, "pp %d intf %d state %d\n",
			phys_enc->hw_pp->idx - PINGPONG_0,
			phys_enc->hw_intf->idx - INTF_0,
			phys_enc->enable_state);
	SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
			phys_enc->hw_intf->idx - INTF_0,
			phys_enc->enable_state);

	if (phys_enc->enable_state == SDE_ENC_DISABLED) {
@@ -1011,8 +1122,14 @@ static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc)
		return;
	}

	if (phys_enc->hw_pp->ops.enable_tearcheck)
		phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, false);
	if (phys_enc->has_intf_te && phys_enc->hw_intf->ops.enable_tearcheck)
		phys_enc->hw_intf->ops.enable_tearcheck(
				phys_enc->hw_intf,
				false);
	else if (phys_enc->hw_pp->ops.enable_tearcheck)
		phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp,
				false);

	phys_enc->enable_state = SDE_ENC_DISABLED;
}

@@ -1307,8 +1424,21 @@ static void sde_encoder_phys_cmd_trigger_start(
	}
}

static void sde_encoder_phys_cmd_init_ops(
		struct sde_encoder_phys_ops *ops)
static void sde_encoder_phys_cmd_setup_vsync_source(
		struct sde_encoder_phys *phys_enc,
		u32 vsync_source, bool is_dummy)
{
	if (!phys_enc || !phys_enc->hw_intf)
		return;

	sde_encoder_helper_vsync_config(phys_enc, vsync_source, is_dummy);

	if (phys_enc->has_intf_te && phys_enc->hw_intf->ops.vsync_sel)
		phys_enc->hw_intf->ops.vsync_sel(phys_enc->hw_intf,
				vsync_source);
}

static void sde_encoder_phys_cmd_init_ops(struct sde_encoder_phys_ops *ops)
{
	ops->prepare_commit = sde_encoder_phys_cmd_prepare_commit;
	ops->is_master = sde_encoder_phys_cmd_is_master;
@@ -1334,9 +1464,10 @@ static void sde_encoder_phys_cmd_init_ops(
	ops->control_te = sde_encoder_phys_cmd_connect_te;
	ops->is_autorefresh_enabled =
			sde_encoder_phys_cmd_is_autorefresh_enabled;
	ops->get_line_count = sde_encoder_phys_cmd_get_line_count;
	ops->get_line_count = sde_encoder_phys_cmd_te_get_line_count;
	ops->get_wr_line_count = sde_encoder_phys_cmd_get_write_line_count;
	ops->wait_for_active = NULL;
	ops->setup_vsync_source = sde_encoder_phys_cmd_setup_vsync_source;
}

struct sde_encoder_phys *sde_encoder_phys_cmd_init(
@@ -1367,7 +1498,6 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
	phys_enc->hw_mdptop = hw_mdp;
	phys_enc->intf_idx = p->intf_idx;

	sde_encoder_phys_cmd_init_ops(&phys_enc->ops);
	phys_enc->parent = p->parent;
	phys_enc->parent_ops = p->parent_ops;
	phys_enc->sde_kms = p->sde_kms;
@@ -1376,7 +1506,14 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
	phys_enc->enc_spinlock = p->enc_spinlock;
	cmd_enc->stream_sel = 0;
	phys_enc->enable_state = SDE_ENC_DISABLED;
	sde_encoder_phys_cmd_init_ops(&phys_enc->ops);
	phys_enc->comp_type = p->comp_type;

	if (sde_hw_intf_te_supported(phys_enc->sde_kms->catalog))
		phys_enc->has_intf_te = true;
	else
		phys_enc->has_intf_te = false;

	for (i = 0; i < INTR_IDX_MAX; i++) {
		irq = &phys_enc->irq[i];
		INIT_LIST_HEAD(&irq->cb.list);
@@ -1398,10 +1535,15 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
	irq->cb.func = sde_encoder_phys_cmd_pp_tx_done_irq;

	irq = &phys_enc->irq[INTR_IDX_RDPTR];
	irq->name = "pp_rd_ptr";
	irq->intr_type = SDE_IRQ_TYPE_PING_PONG_RD_PTR;
	irq->intr_idx = INTR_IDX_RDPTR;
	irq->cb.func = sde_encoder_phys_cmd_pp_rd_ptr_irq;
	irq->name = "te_rd_ptr";

	if (phys_enc->has_intf_te)
		irq->intr_type = SDE_IRQ_TYPE_INTF_TEAR_RD_PTR;
	else
		irq->intr_type = SDE_IRQ_TYPE_PING_PONG_RD_PTR;

	irq->cb.func = sde_encoder_phys_cmd_te_rd_ptr_irq;

	irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
	irq->name = "underrun";
@@ -1411,7 +1553,12 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(

	irq = &phys_enc->irq[INTR_IDX_AUTOREFRESH_DONE];
	irq->name = "autorefresh_done";

	if (phys_enc->has_intf_te)
		irq->intr_type = SDE_IRQ_TYPE_INTF_TEAR_AUTO_REF;
	else
		irq->intr_type = SDE_IRQ_TYPE_PING_PONG_AUTO_REF;

	irq->intr_idx = INTR_IDX_AUTOREFRESH_DONE;
	irq->cb.func = sde_encoder_phys_cmd_autorefresh_done_irq;

+5 −1
Original line number Diff line number Diff line
@@ -1718,6 +1718,10 @@ static int sde_intf_parse_dt(struct device_node *np,
			set_bit(SDE_INTF_ROT_START, &intf->features);
		if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev))
			set_bit(SDE_INTF_INPUT_CTRL, &intf->features);

		if (IS_SDE_MAJOR_MINOR_SAME((sde_cfg->hwversion),
				SDE_HW_VER_500))
			set_bit(SDE_INTF_TE, &intf->features);
	}

end:
@@ -2894,7 +2898,7 @@ static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
	cfg->mdp[0].smart_panel_align_mode =
		PROP_VALUE_ACCESS(prop_value, SMART_PANEL_ALIGN_MODE, 0);

	major_version = SDE_HW_MAJOR(sde_cfg->hwversion);
	major_version = SDE_HW_MAJOR(cfg->hwversion);
	if (major_version < SDE_HW_MAJOR(SDE_HW_VER_500))
		set_bit(SDE_MDP_VSYNC_SEL, &cfg->mdp[0].features);

+5 −0
Original line number Diff line number Diff line
@@ -1130,4 +1130,9 @@ static inline bool sde_hw_sspp_multirect_enabled(const struct sde_sspp_cfg *cfg)
	return test_bit(SDE_SSPP_SMART_DMA_V1, &cfg->features) ||
			 test_bit(SDE_SSPP_SMART_DMA_V2, &cfg->features);
}

static inline sde_hw_intf_te_supported(const struct sde_mdss_cfg *sde_cfg)
{
	return test_bit(SDE_INTF_TE, &(sde_cfg->intf[0].features));
}
#endif /* _SDE_HW_CATALOG_H */