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

Commit 5d8a9b37 authored by Xiaowen Wu's avatar Xiaowen Wu
Browse files

drm/msm/sde: add line insertion support for sspp



Add line insertion support for sspp, this is used to support
display with external splitter. Also extend sspp feature bits
from 32 to 64 as line insertion feature index is 32.

Change-Id: Ifa4f2b2914f391ced42383282731a62cf1ad82ee
Signed-off-by: default avatarXiaowen Wu <wxiaowen@codeaurora.org>
parent 1ee5220d
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
 * Copyright (C) 2013 Red Hat
 * Author: Rob Clark <robdclark@gmail.com>
 *
@@ -445,6 +445,7 @@ struct msm_display_topology {
 * @wide_bus_en:	wide-bus mode cfg for interface module
 * @mdp_transfer_time_us   Specifies the mdp transfer time for command mode
 *                         panels in microseconds.
 * @vpadding:        panel stacking height
 */
struct msm_mode_info {
	uint32_t frame_rate;
@@ -458,6 +459,7 @@ struct msm_mode_info {
	struct msm_roi_caps roi_caps;
	bool wide_bus_en;
	u32 mdp_transfer_time_us;
	u32 vpadding;
};

/**
+143 −0
Original line number Diff line number Diff line
@@ -91,6 +91,9 @@ static struct sde_crtc_custom_events custom_events[] = {
#define MAX_FRAME_COUNT			1000
#define MILI_TO_MICRO			1000

/* Line padding ratio limit */
#define MAX_VPADDING_RATIO		3

static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc)
{
	struct msm_drm_private *priv;
@@ -1058,6 +1061,18 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc,
						cstate->lm_roi[i].y;
		}

		/* update dim layer rect for panel stacking crtc */
		if (cstate->padding_height) {
			uint32_t padding_y, padding_start, padding_height;

			sde_crtc_calc_vpadding_param(crtc->state,
				split_dim_layer.rect.y, split_dim_layer.rect.h,
				&padding_y, &padding_start, &padding_height);

			split_dim_layer.rect.y = padding_y;
			split_dim_layer.rect.h = padding_height;
		}

		SDE_EVT32_VERBOSE(DRMID(crtc),
				cstate->lm_roi[i].x,
				cstate->lm_roi[i].y,
@@ -1601,6 +1616,84 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc,
	return 0;
}

static u32 _sde_crtc_calc_gcd(u32 a, u32 b)
{
	if (b == 0)
		return a;

	return _sde_crtc_calc_gcd(b, a % b);
}

static int _sde_crtc_check_panel_stacking(struct drm_crtc *crtc,
		struct drm_crtc_state *state)
{
	struct sde_kms *kms;
	struct sde_crtc *sde_crtc;
	struct sde_crtc_state *sde_crtc_state;
	struct drm_connector *conn;
	struct msm_mode_info mode_info;
	u32 gcd, m, n;
	int rc;

	kms = _sde_crtc_get_kms(crtc);
	if (!kms || !kms->catalog) {
		SDE_ERROR("invalid kms\n");
		return -EINVAL;
	}

	if (!kms->catalog->has_line_insertion)
		return 0;

	sde_crtc = to_sde_crtc(crtc);
	sde_crtc_state = to_sde_crtc_state(state);

	/* panel stacking only support single connector */
	if (sde_crtc_state->num_connectors != 1)
		return 0;

	conn = sde_crtc_state->connectors[0];
	rc = sde_connector_get_mode_info(conn->state, &mode_info);
	if (rc) {
		SDE_ERROR("failed to get mode info\n");
		return -EINVAL;
	}

	if (!mode_info.vpadding)
		goto done;

	if (mode_info.vpadding < state->mode.vdisplay) {
		SDE_ERROR("padding height %d is less than vdisplay %d\n",
			mode_info.vpadding, state->mode.vdisplay);
		return -EINVAL;
	}

	/* skip calculation if already cached */
	if (mode_info.vpadding == sde_crtc_state->padding_height)
		return 0;

	gcd = _sde_crtc_calc_gcd(mode_info.vpadding, state->mode.vdisplay);
	if (!gcd) {
		SDE_ERROR("zero gcd found for padding height %d %d\n",
			mode_info.vpadding, state->mode.vdisplay);
		return -EINVAL;
	}

	m = state->mode.vdisplay / gcd;
	n = mode_info.vpadding / gcd - m;

	if (m > MAX_VPADDING_RATIO || n > MAX_VPADDING_RATIO) {
		SDE_ERROR("unsupported panel stacking pattern %d:%d", m, n);
		return -EINVAL;
	}

	sde_crtc_state->padding_active = m;
	sde_crtc_state->padding_dummy = n;

done:
	sde_crtc_state->padding_height = mode_info.vpadding;
	return 0;
}

static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc)
{
	struct sde_crtc *sde_crtc;
@@ -5340,6 +5433,13 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
		goto end;
	}

	rc = _sde_crtc_check_panel_stacking(crtc, state);
	if (rc) {
		SDE_ERROR("crtc%d failed panel stacking check %d\n",
				crtc->base.id, rc);
		goto end;
	}

end:
	kfree(pstates);
	kfree(multirect_plane);
@@ -6872,3 +6972,46 @@ void sde_crtc_update_cont_splash_settings(struct drm_crtc *crtc)
	sde_crtc = to_sde_crtc(crtc);
	sde_crtc->cur_perf.core_clk_rate = kms->perf.max_core_clk_rate;
}

int sde_crtc_calc_vpadding_param(struct drm_crtc_state *state,
		uint32_t crtc_y, uint32_t crtc_h, uint32_t *padding_y,
		uint32_t *padding_start, uint32_t *padding_height)
{
	struct sde_kms *kms;
	struct sde_crtc_state *cstate = to_sde_crtc_state(state);
	u32 y_blocks, y_remain, y_start;
	u32 h_start, h_blocks, h_end, h_total;
	u32 m, n;

	kms = _sde_crtc_get_kms(state->crtc);
	if (!kms || !kms->catalog) {
		SDE_ERROR("invalid kms\n");
		return -EINVAL;
	}

	if (!kms->catalog->has_line_insertion)
		return 0;

	if (!cstate->padding_active) {
		SDE_ERROR("zero padding active value\n");
		return -EINVAL;
	}

	m = cstate->padding_active;
	n = m + cstate->padding_dummy;
	y_blocks = crtc_y / m;
	y_remain = crtc_y - y_blocks * m;
	y_start = y_remain + y_blocks * n;
	h_start = m - y_remain;
	h_blocks = (crtc_h - h_start) / m;
	h_end = (crtc_h - h_start) - h_blocks * m;
	if (h_end)
		h_end += cstate->padding_dummy;
	h_total = h_start + h_end + h_blocks * n;

	*padding_y = y_start;
	*padding_start = h_start;
	*padding_height = h_total;

	return 0;
}
+21 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
 * Copyright (C) 2013 Red Hat
 * Author: Rob Clark <robdclark@gmail.com>
 *
@@ -393,6 +393,9 @@ struct sde_crtc_respool {
 * @sbuf_clk_rate : previous and current user specified inline rotator clock
 * @sbuf_clk_shifted : whether or not sbuf_clk_rate has been shifted as part
 *	of crtc atomic check
 * @padding_height: panel height after line padding
 * @padding_active: active lines in panel stacking pattern
 * @padding_dummy: dummy lines in panel stacking pattern
 */
struct sde_crtc_state {
	struct drm_crtc_state base;
@@ -427,6 +430,10 @@ struct sde_crtc_state {
	u64 sbuf_clk_rate[2];
	bool sbuf_clk_shifted;

	u32 padding_height;
	u32 padding_active;
	u32 padding_dummy;

	struct sde_crtc_respool rp;
};

@@ -828,4 +835,17 @@ uint64_t sde_crtc_get_sbuf_clk(struct drm_crtc_state *state);
 */
void sde_crtc_misr_setup(struct drm_crtc *crtc, bool enable, u32 frame_count);

/**
 * sde_crtc_calc_vpadding_param - calculate vpadding parameters
 * @state: Pointer to DRM crtc state object
 * @crtc_y: Plane's CRTC_Y offset
 * @crtc_h: Plane's CRTC_H size
 * @padding_y: Padding Y offset
 * @padding_start: Padding start offset
 * @padding_height: Padding height in total
 */
int sde_crtc_calc_vpadding_param(struct drm_crtc_state *state,
		uint32_t crtc_y, uint32_t crtc_h, uint32_t *padding_y,
		uint32_t *padding_start, uint32_t *padding_height);

#endif /* _SDE_CRTC_H_ */
+7 −0
Original line number Diff line number Diff line
@@ -168,6 +168,7 @@ enum sde_prop {
	UBWC_BW_CALC_VERSION,
	PIPE_ORDER_VERSION,
	SEC_SID_MASK,
	LINE_INSERTION,
	SDE_PROP_MAX,
};

@@ -447,6 +448,7 @@ static struct sde_prop_type sde_prop[] = {
	{PIPE_ORDER_VERSION, "qcom,sde-pipe-order-version", false,
			PROP_TYPE_U32},
	{SEC_SID_MASK, "qcom,sde-secure-sid-mask", false, PROP_TYPE_U32_ARRAY},
	{LINE_INSERTION, "qcom,sde-has-line-insertion", false, PROP_TYPE_BOOL},
};

static struct sde_prop_type sde_perf_prop[] = {
@@ -1397,6 +1399,9 @@ static int sde_sspp_parse_dt(struct device_node *np,
			set_bit(SDE_SSPP_TS_PREFILL_REC1, &sspp->features);
		}

		if (sde_cfg->has_line_insertion)
			set_bit(SDE_SSPP_LINE_INSERTION, &sspp->features);

		sblk->smart_dma_priority =
			PROP_VALUE_ACCESS(prop_value, SSPP_SMART_DMA, i);

@@ -3054,6 +3059,8 @@ static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
	cfg->has_idle_pc = PROP_VALUE_ACCESS(prop_value, IDLE_PC, 0);
	cfg->pipe_order_type = PROP_VALUE_ACCESS(prop_value,
		PIPE_ORDER_VERSION, 0);
	cfg->has_line_insertion = PROP_VALUE_ACCESS(prop_value,
		LINE_INSERTION, 0);
end:
	kfree(prop_value);
	return rc;
+3 −0
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ enum {
 * @SDE_SSPP_BLOCK_SEC_UI    Blocks secure-ui layers
 * @SDE_SSPP_QOS_FL_NOCALC   Avoid fill level calculation for QoS/danger/safe
 * @SDE_SSPP_SCALER_QSEED3LITE Qseed3lite algorithm support
 * @SDE_SSPP_LINE_INSERTION  Line insertion support
 * @SDE_SSPP_MAX             maximum value
 */
enum {
@@ -199,6 +200,7 @@ enum {
	SDE_SSPP_BLOCK_SEC_UI,
	SDE_SSPP_QOS_FL_NOCALC,
	SDE_SSPP_SCALER_QSEED3LITE,
	SDE_SSPP_LINE_INSERTION,
	SDE_SSPP_MAX
};

@@ -1109,6 +1111,7 @@ struct sde_mdss_cfg {
	bool delay_prg_fetch_start;
	bool has_qsync;
	bool has_3d_merge_reset;
	bool has_line_insertion;

	bool sui_misr_supported;
	u32 sui_block_xin_mask;
Loading