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

Commit 2e655031 authored by Jeykumar Sankaran's avatar Jeykumar Sankaran Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm/sde: add support for smart DMA 2.0



SmartDMA allows fetching multiple surfaces in a single source pipe.
SmartDMA version 2.0 can fetch up to 2 surfaces in a single pipe for
2 destination rectangles. This change adds support for this feature
in SDE DRM. Each destination rectangle path of a smartDMA pipe is
enumerated as a separate DRM plane with necessary property to
indicate the pair. Clients need to identify the pair and program the
source surfaces as per the HW limitations of the version supported.
SmartDMA will be enabled only on requesting SDE customization by
kernel-clients.

Change-Id: Ic0a0496cb785d6212e375cc7e0fc55407f7d8a0b
Signed-off-by: default avatarJeykumar Sankaran <jsanka@codeaurora.org>
parent b5d980c0
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -147,12 +147,17 @@ Optional properties:
				indicating the danger luts on sspp.
- qcom,sde-sspp-safe-lut:	A 3 cell property, with a format of <linear, tile, nrt>,
				indicating the safe luts on sspp.
- qcom,sde-sspp-max-rects:	Array of u32 values indicating maximum rectangles supported
				on each sspp. This property is for multirect feature support.
				Number of offsets defined should match the number of
				offsets defined in property: qcom,sde-sspp-off.
- qcom,sde-sspp-excl-rect:	Array of u32 values indicating exclusion rectangle
				support on each sspp.
- qcom,sde-sspp-smart-dma-priority:	Array of u32 values indicating hw pipe
					priority of secondary rectangles when smart dma
					is supported. Number of priority values should
					match the number of offsets defined in
					qcom,sde-sspp-off node. Zero indicates no support
					for smart dma for the sspp.
- qcom,sde-smart-dma-rev:	A string entry indicating the smart dma version
				supported on the device. Supported entries are
				"smart_dma_v1" and "smart_dma_v2".
- qcom,sde-intf-type:		Array of string provides the interface type information.
				Possible string values
					"dsi" - dsi display interface
@@ -385,6 +390,11 @@ Example:
				1 1 1 1
				1 1
				1 1>;
    qcom,sde-sspp-smart-dma-priority = <0 0 0 0
					0 0 0 0
					0 0
					1 2>;
    qcom,sde-smart-dma-rev = "smart_dma_v2";
    qcom,sde-te-off = <0x100>;
    qcom,sde-te2-off = <0x100>;
    qcom,sde-te-size = <0xffff>;
+1 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ struct msm_fence_cb;

#define NUM_DOMAINS    4    /* one for KMS, then one per gpu core (?) */
#define MAX_CRTCS      8
#define MAX_PLANES     12
#define MAX_PLANES     20
#define MAX_ENCODERS   8
#define MAX_BRIDGES    8
#define MAX_CONNECTORS 8
+58 −4
Original line number Diff line number Diff line
@@ -270,6 +270,9 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,

		stage_cfg->stage[lm_idx][pstate->stage][idx] =
							sde_plane_pipe(plane);
		stage_cfg->multirect_index
				[lm_idx][pstate->stage][idx] =
				pstate->multirect_index;
		mixer[lm_idx].flush_mask |= flush_mask;

		SDE_DEBUG("crtc %d stage:%d - plane %d sspp %d fb %d\n",
@@ -300,6 +303,9 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
			idx = right_crtc_zpos_cnt[pstate->stage]++;
			stage_cfg->stage[RIGHT_MIXER][pstate->stage][idx] =
							sde_plane_pipe(plane);
			stage_cfg->multirect_index
				[RIGHT_MIXER][pstate->stage][idx] =
				pstate->multirect_index;
			mixer[RIGHT_MIXER].flush_mask |= flush_mask;

			/* blend config update */
@@ -1156,8 +1162,8 @@ static void sde_crtc_enable(struct drm_crtc *crtc)
struct plane_state {
	struct sde_plane_state *sde_pstate;
	const struct drm_plane_state *drm_pstate;

	int stage;
	u32 pipe_id;
};

static int pstate_cmp(const void *a, const void *b)
@@ -1182,7 +1188,7 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
		struct drm_crtc_state *state)
{
	struct sde_crtc *sde_crtc;
	struct plane_state pstates[SDE_STAGE_MAX * 2];
	struct plane_state pstates[SDE_STAGE_MAX * 4];
	struct sde_crtc_state *cstate;

	const struct drm_plane_state *pstate;
@@ -1190,8 +1196,12 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
	struct drm_display_mode *mode;

	int cnt = 0, rc = 0, mixer_width, i, z_pos;

	int left_crtc_zpos_cnt[SDE_STAGE_MAX] = {0};
	int right_crtc_zpos_cnt[SDE_STAGE_MAX] = {0};
	struct sde_multirect_plane_states multirect_plane[SDE_STAGE_MAX * 2];
	int multirect_count = 0;
	const struct drm_plane_state *pipe_staged[SSPP_MAX];

	if (!crtc) {
		SDE_ERROR("invalid crtc\n");
@@ -1209,6 +1219,8 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
	mode = &state->adjusted_mode;
	SDE_DEBUG("%s: check", sde_crtc->name);

	memset(pipe_staged, 0, sizeof(pipe_staged));

	mixer_width = sde_crtc_mixer_width(sde_crtc, mode);

	 /* get plane state for all drm planes associated with crtc state */
@@ -1226,6 +1238,7 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
		pstates[cnt].drm_pstate = pstate;
		pstates[cnt].stage = sde_plane_get_property(
				pstates[cnt].sde_pstate, PLANE_PROP_ZPOS);
		pstates[cnt].pipe_id = sde_plane_pipe(plane);

		/* check dim layer stage with every plane */
		for (i = 0; i < cstate->num_dim_layers; i++) {
@@ -1238,6 +1251,17 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
			}
		}

		if (pipe_staged[pstates[cnt].pipe_id]) {
			multirect_plane[multirect_count].r0 =
				pipe_staged[pstates[cnt].pipe_id];
			multirect_plane[multirect_count].r1 = pstate;
			multirect_count++;

			pipe_staged[pstates[cnt].pipe_id] = NULL;
		} else {
			pipe_staged[pstates[cnt].pipe_id] = pstate;
		}

		cnt++;

		if (CHECK_LAYER_BOUNDS(pstate->crtc_y, pstate->crtc_h,
@@ -1253,6 +1277,15 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
		}
	}

	for (i = 1; i < SSPP_MAX; i++) {
		if (pipe_staged[i] &&
			is_sde_plane_virtual(pipe_staged[i]->plane)) {
			SDE_ERROR("invalid use of virtual plane: %d\n",
					pipe_staged[i]->plane->base.id);
			goto end;
		}
	}

	/* Check dim layer rect bounds and stage */
	for (i = 0; i < cstate->num_dim_layers; i++) {
		if ((CHECK_LAYER_BOUNDS(cstate->dim_layer[i].rect.y,
@@ -1300,7 +1333,7 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
			goto end;
		} else if (pstates[i].drm_pstate->crtc_x < mixer_width) {
			if (left_crtc_zpos_cnt[z_pos] == 2) {
				SDE_ERROR("> 2 plane @ stage%d on left\n",
				SDE_ERROR("> 2 planes @ stage %d on left\n",
					z_pos);
				rc = -EINVAL;
				goto end;
@@ -1308,7 +1341,7 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
			left_crtc_zpos_cnt[z_pos]++;
		} else {
			if (right_crtc_zpos_cnt[z_pos] == 2) {
				SDE_ERROR("> 2 plane @ stage%d on right\n",
				SDE_ERROR("> 2 planes @ stage %d on right\n",
					z_pos);
				rc = -EINVAL;
				goto end;
@@ -1319,6 +1352,17 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
		SDE_DEBUG("%s: zpos %d", sde_crtc->name, z_pos);
	}

	for (i = 0; i < multirect_count; i++) {
		if (sde_plane_validate_multirect_v2(&multirect_plane[i])) {
			SDE_ERROR(
			"multirect validation failed for planes (%d - %d)\n",
					multirect_plane[i].r0->plane->base.id,
					multirect_plane[i].r1->plane->base.id);
			rc = -EINVAL;
			break;
		}
	}

end:
	return rc;
}
@@ -1427,6 +1471,16 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
		sde_kms_info_add_keystr(info, "qseed_type", "qseed2");
	if (catalog->qseed_type == SDE_SSPP_SCALER_QSEED3)
		sde_kms_info_add_keystr(info, "qseed_type", "qseed3");

	if (sde_is_custom_client()) {
		if (catalog->smart_dma_rev == SDE_SSPP_SMART_DMA_V1)
			sde_kms_info_add_keystr(info,
					"smart_dma_rev", "smart_dma_v1");
		if (catalog->smart_dma_rev == SDE_SSPP_SMART_DMA_V2)
			sde_kms_info_add_keystr(info,
					"smart_dma_rev", "smart_dma_v2");
	}

	sde_kms_info_add_keyint(info, "has_src_split", catalog->has_src_split);
	msm_property_set_blob(&sde_crtc->property_info, &sde_crtc->blob_info,
			info->data, info->len, CRTC_PROP_INFO);
+27 −6
Original line number Diff line number Diff line
@@ -46,9 +46,6 @@
/* default hardware block size if dtsi entry is not present */
#define DEFAULT_SDE_HW_BLOCK_LEN 0x100

/* default rects for multi rect case */
#define DEFAULT_SDE_SSPP_MAX_RECTS 1

/* total number of intf - dp, dsi, hdmi */
#define INTF_COUNT			3

@@ -106,6 +103,7 @@ enum sde_prop {
	CDP,
	SRC_SPLIT,
	DIM_LAYER,
	SMART_DMA_REV,
	SDE_PROP_MAX,
};

@@ -118,11 +116,11 @@ enum {
	SSPP_CLK_STATUS,
	SSPP_DANGER,
	SSPP_SAFE,
	SSPP_MAX_RECTS,
	SSPP_SCALE_SIZE,
	SSPP_VIG_BLOCKS,
	SSPP_RGB_BLOCKS,
	SSPP_EXCL_RECT,
	SSPP_SMART_DMA,
	SSPP_PROP_MAX,
};

@@ -283,6 +281,7 @@ static struct sde_prop_type sde_prop[] = {
	{CDP, "qcom,sde-has-cdp", false, PROP_TYPE_BOOL},
	{SRC_SPLIT, "qcom,sde-has-src-split", false, PROP_TYPE_BOOL},
	{DIM_LAYER, "qcom,sde-has-dim-layer", false, PROP_TYPE_BOOL},
	{SMART_DMA_REV, "qcom,sde-smart-dma-rev", false, PROP_TYPE_STRING},
};

static struct sde_prop_type sspp_prop[] = {
@@ -296,11 +295,12 @@ static struct sde_prop_type sspp_prop[] = {
		PROP_TYPE_BIT_OFFSET_ARRAY},
	{SSPP_DANGER, "qcom,sde-sspp-danger-lut", false, PROP_TYPE_U32_ARRAY},
	{SSPP_SAFE, "qcom,sde-sspp-safe-lut", false, PROP_TYPE_U32_ARRAY},
	{SSPP_MAX_RECTS, "qcom,sde-sspp-max-rects", false, PROP_TYPE_U32_ARRAY},
	{SSPP_SCALE_SIZE, "qcom,sde-sspp-scale-size", false, PROP_TYPE_U32},
	{SSPP_VIG_BLOCKS, "qcom,sde-sspp-vig-blocks", false, PROP_TYPE_NODE},
	{SSPP_RGB_BLOCKS, "qcom,sde-sspp-rgb-blocks", false, PROP_TYPE_NODE},
	{SSPP_EXCL_RECT, "qcom,sde-sspp-excl-rect", false, PROP_TYPE_U32_ARRAY},
	{SSPP_SMART_DMA, "qcom,sde-sspp-smart-dma-priority", false,
		PROP_TYPE_U32_ARRAY},
};

static struct sde_prop_type vig_prop[] = {
@@ -900,6 +900,13 @@ static int sde_sspp_parse_dt(struct device_node *np,
		sblk->maxlinewidth = sde_cfg->max_sspp_linewidth;

		set_bit(SDE_SSPP_SRC, &sspp->features);

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

		if (sblk->smart_dma_priority && sde_cfg->smart_dma_rev)
			set_bit(sde_cfg->smart_dma_rev, &sspp->features);

		sblk->src_blk.id = SDE_SSPP_SRC;

		of_property_read_string_index(np,
@@ -1815,7 +1822,7 @@ static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg)

static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
{
	int rc, len, prop_count[SDE_PROP_MAX];
	int rc, dma_rc, len, prop_count[SDE_PROP_MAX];
	struct sde_prop_value *prop_value = NULL;
	bool prop_exists[SDE_PROP_MAX];
	const char *type;
@@ -1890,6 +1897,20 @@ static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
	else if (!rc && !strcmp(type, "csc-10bit"))
		cfg->csc_type = SDE_SSPP_CSC_10BIT;

	/*
	 * Current SDE support only Smart DMA 2.0.
	 * No support for Smart DMA 1.0 yet.
	 */
	cfg->smart_dma_rev = 0;
	dma_rc = of_property_read_string(np, sde_prop[SMART_DMA_REV].prop_name,
			&type);
	if (!dma_rc && !strcmp(type, "smart_dma_v2")) {
		cfg->smart_dma_rev = SDE_SSPP_SMART_DMA_V2;
	} else if (!dma_rc && !strcmp(type, "smart_dma_v1")) {
		SDE_ERROR("smart dma 1.0 is not supported in SDE\n");
		cfg->smart_dma_rev = 0;
	}

	cfg->has_src_split = PROP_VALUE_ACCESS(prop_value, SRC_SPLIT, 0);
	cfg->has_dim_layer = PROP_VALUE_ACCESS(prop_value, DIM_LAYER, 0);
end:
+17 −0
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ enum {
 * @SDE_SSPP_CURSOR,         SSPP can be used as a cursor layer
 * @SDE_SSPP_QOS,            SSPP support QoS control, danger/safe/creq
 * @SDE_SSPP_EXCL_RECT,      SSPP supports exclusion rect
 * @SDE_SSPP_SMART_DMA_V1,   SmartDMA 1.0 support
 * @SDE_SSPP_SMART_DMA_V2,   SmartDMA 2.0 support
 * @SDE_SSPP_MAX             maximum value
 */
enum {
@@ -109,6 +111,8 @@ enum {
	SDE_SSPP_CURSOR,
	SDE_SSPP_QOS,
	SDE_SSPP_EXCL_RECT,
	SDE_SSPP_SMART_DMA_V1,
	SDE_SSPP_SMART_DMA_V2,
	SDE_SSPP_MAX
};

@@ -317,6 +321,7 @@ struct sde_format_extended {
 * @creq_vblank: creq priority during vertical blanking
 * @danger_vblank: danger priority during vertical blanking
 * @pixel_ram_size: size of latency hiding and de-tiling buffer in bytes
 * @smart_dma_priority: hw priority of rect1 of multirect pipe
 * @src_blk:
 * @scaler_blk:
 * @csc_blk:
@@ -342,6 +347,7 @@ struct sde_sspp_sub_blks {
	u32 maxupscale;
	u32 maxhdeciexp; /* max decimation is 2^value */
	u32 maxvdeciexp; /* max decimation is 2^value */
	u32 smart_dma_priority;
	struct sde_src_blk src_blk;
	struct sde_scaler_blk scaler_blk;
	struct sde_pp_blk csc_blk;
@@ -627,6 +633,7 @@ struct sde_reg_dma_cfg {
 * @highest_bank_bit   highest memory bit setting for tile buffers.
 * @qseed_type         qseed2 or qseed3 support.
 * @csc_type           csc or csc_10bit support.
 * @smart_dma_rev      Supported version of SmartDMA feature.
 * @has_src_split      source split feature status
 * @has_cdp            Client driver prefetch feature status
 */
@@ -640,6 +647,7 @@ struct sde_mdss_cfg {
	u32 highest_bank_bit;
	u32 qseed_type;
	u32 csc_type;
	u32 smart_dma_rev;
	bool has_src_split;
	bool has_cdp;
	bool has_dim_layer;
@@ -721,4 +729,13 @@ struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 hw_rev);
 */
void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg);

/**
 * sde_hw_sspp_multirect_enabled - check multirect enabled for the sspp
 * @cfg:          pointer to sspp cfg
 */
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);
}
#endif /* _SDE_HW_CATALOG_H */
Loading