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

Commit 1bb94fa3 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: add drm property for multirect mode"

parents 50907504 13924778
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ enum msm_mdp_plane_property {
	PLANE_PROP_BLEND_OP,
	PLANE_PROP_SRC_CONFIG,
	PLANE_PROP_FB_TRANSLATION_MODE,
	PLANE_PROP_MULTIRECT_MODE,

	/* total # of properties */
	PLANE_PROP_COUNT
+108 −41
Original line number Diff line number Diff line
@@ -58,6 +58,9 @@

#define SDE_PLANE_COLOR_FILL_FLAG	BIT(31)

#define TIME_MULTIPLEX_RECT(r0, r1, buffer_lines) \
	 ((r0).y >= ((r1).y + (r1).h + buffer_lines))

/* multirect rect index */
enum {
	R0,
@@ -2787,6 +2790,12 @@ void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
	pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
}

/**
 * multi_rect validate API allows to validate only R0 and R1 RECT
 * passing for each plane. Client of this API must not pass multiple
 * plane which are not sharing same XIN client. Such calls will fail
 * even though kernel client is passing valid multirect configuration.
 */
int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
{
	struct sde_plane_state *pstate[R_MAX];
@@ -2794,37 +2803,44 @@ int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
	struct sde_rect src[R_MAX], dst[R_MAX];
	struct sde_plane *sde_plane[R_MAX];
	const struct sde_format *fmt[R_MAX];
	int xin_id[R_MAX];
	bool q16_data = true;
	int i, buffer_lines;
	int i, j, buffer_lines, width_threshold[R_MAX];
	unsigned int max_tile_height = 1;
	bool parallel_fetch_qualified = true;
	bool has_tiled_rect = false;

	for (i = 0; i < R_MAX; i++) {
	enum sde_sspp_multirect_mode mode = SDE_SSPP_MULTIRECT_NONE;
	const struct msm_format *msm_fmt;

	for (i = 0; i < R_MAX; i++) {
		drm_state[i] = i ? plane->r1 : plane->r0;
		msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
		fmt[i] = to_sde_format(msm_fmt);

		if (SDE_FORMAT_IS_UBWC(fmt[i])) {
			has_tiled_rect = true;
			if (fmt[i]->tile_height > max_tile_height)
				max_tile_height = fmt[i]->tile_height;
		}
		if (!drm_state[i]) {
			SDE_ERROR("drm plane state is NULL\n");
			return -EINVAL;
		}

	for (i = 0; i < R_MAX; i++) {
		int width_threshold;

		pstate[i] = to_sde_plane_state(drm_state[i]);
		sde_plane[i] = to_sde_plane(drm_state[i]->plane);
		xin_id[i] = sde_plane[i]->pipe_hw->cap->xin_id;

		if (pstate[i] == NULL) {
			SDE_ERROR("SDE plane state of plane id %d is NULL\n",
				drm_state[i]->plane->base.id);
		for (j = 0; j < i; j++) {
			if (xin_id[i] != xin_id[j]) {
				SDE_ERROR_PLANE(sde_plane[i],
					"invalid multirect validate call base:%d xin_id:%d curr:%d xin:%d\n",
					j, xin_id[j], i, xin_id[i]);
				return -EINVAL;
			}
		}

		msm_fmt = msm_framebuffer_format(drm_state[i]->fb);
		if (!msm_fmt) {
			SDE_ERROR_PLANE(sde_plane[i], "null fb\n");
			return -EINVAL;
		}
		fmt[i] = to_sde_format(msm_fmt);

		if (SDE_FORMAT_IS_UBWC(fmt[i]) &&
		    (fmt[i]->tile_height > max_tile_height))
			max_tile_height = fmt[i]->tile_height;

		POPULATE_RECT(&src[i], drm_state[i]->src_x, drm_state[i]->src_y,
			drm_state[i]->src_w, drm_state[i]->src_h, q16_data);
@@ -2851,41 +2867,81 @@ int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
		 * So we cannot support more than half of the supported SSPP
		 * width for tiled formats.
		 */
		width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
		if (has_tiled_rect)
			width_threshold /= 2;
		width_threshold[i] = sde_plane[i]->pipe_sblk->maxlinewidth;
		if (SDE_FORMAT_IS_UBWC(fmt[i]))
			width_threshold[i] /= 2;

		if (parallel_fetch_qualified && src[i].w > width_threshold)
		if (parallel_fetch_qualified && src[i].w > width_threshold[i])
			parallel_fetch_qualified = false;

		if (sde_plane[i]->is_virtual)
			mode = sde_plane_get_property(pstate[i],
					PLANE_PROP_MULTIRECT_MODE);
	}

	/* Validate RECT's and set the mode */

	/* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
	if (parallel_fetch_qualified) {
		pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;
		pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_PARALLEL;

		goto done;
	}

	/* TIME_MX Mode */
	buffer_lines = 2 * max_tile_height;

	if ((dst[R1].y >= dst[R0].y + dst[R0].h + buffer_lines) ||
		(dst[R0].y >= dst[R1].y + dst[R1].h + buffer_lines)) {
		pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
		pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
	} else {
	/**
	 * fallback to driver mode selection logic if client is using
	 * multirect plane without setting property.
	 *
	 * validate multirect mode configuration based on rectangle
	 */
	switch (mode) {
	case SDE_SSPP_MULTIRECT_NONE:
		if (parallel_fetch_qualified)
			mode = SDE_SSPP_MULTIRECT_PARALLEL;
		else if (TIME_MULTIPLEX_RECT(dst[R1], dst[R0], buffer_lines) ||
			 TIME_MULTIPLEX_RECT(dst[R0], dst[R1], buffer_lines))
			mode = SDE_SSPP_MULTIRECT_TIME_MX;
		else
			SDE_ERROR(
			"No multirect mode possible for the planes (%d - %d)\n",
				"planes(%d - %d) multirect mode selection fail\n",
				drm_state[R0]->plane->base.id,
				drm_state[R1]->plane->base.id);
		return -EINVAL;
		break;

	case SDE_SSPP_MULTIRECT_PARALLEL:
		if (!parallel_fetch_qualified) {
			SDE_ERROR("R0 plane:%d width_threshold:%d src_w:%d\n",
				drm_state[R0]->plane->base.id,
				width_threshold[R0],  src[R0].w);
			SDE_ERROR("R1 plane:%d width_threshold:%d src_w:%d\n",
				drm_state[R1]->plane->base.id,
				width_threshold[R1],  src[R1].w);
			SDE_ERROR("parallel fetch not qualified\n");
			mode = SDE_SSPP_MULTIRECT_NONE;
		}
		break;

	case SDE_SSPP_MULTIRECT_TIME_MX:
		if (!TIME_MULTIPLEX_RECT(dst[R1], dst[R0], buffer_lines) &&
		    !TIME_MULTIPLEX_RECT(dst[R0], dst[R1], buffer_lines)) {
			SDE_ERROR(
				"buffer_lines:%d R0 plane:%d dst_y:%d dst_h:%d\n",
				buffer_lines, drm_state[R0]->plane->base.id,
				dst[R0].y, dst[R0].h);
			SDE_ERROR(
				"buffer_lines:%d R1 plane:%d dst_y:%d dst_h:%d\n",
				buffer_lines, drm_state[R1]->plane->base.id,
				dst[R1].y, dst[R1].h);
			SDE_ERROR("time multiplexed fetch not qualified\n");
			mode = SDE_SSPP_MULTIRECT_NONE;
		}
		break;

	default:
		SDE_ERROR("bad mode:%d selection\n", mode);
		mode = SDE_SSPP_MULTIRECT_NONE;
		break;
	}

	for (i = 0; i < R_MAX; i++)
		pstate[i]->multirect_mode = mode;

	if (mode == SDE_SSPP_MULTIRECT_NONE)
		return -EINVAL;

done:
	if (sde_plane[R0]->is_virtual) {
		pstate[R0]->multirect_index = SDE_SSPP_RECT_1;
		pstate[R1]->multirect_index = SDE_SSPP_RECT_0;
@@ -2898,6 +2954,7 @@ int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
		pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
	SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
		pstate[R1]->multirect_mode, pstate[R1]->multirect_index);

	return 0;
}

@@ -3609,6 +3666,7 @@ static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
		case PLANE_PROP_CSC_V1:
			pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
			break;
		case PLANE_PROP_MULTIRECT_MODE:
		case PLANE_PROP_COLOR_FILL:
			/* potentially need to refresh everything */
			pstate->dirty = SDE_PLANE_DIRTY_ALL;
@@ -4029,6 +4087,11 @@ static void _sde_plane_install_properties(struct drm_plane *plane,
		{SDE_DRM_FB_NON_SEC_DIR_TRANS, "non_sec_direct_translation"},
		{SDE_DRM_FB_SEC_DIR_TRANS, "sec_direct_translation"},
	};
	static const struct drm_prop_enum_list e_multirect_mode[] = {
		{SDE_SSPP_MULTIRECT_NONE, "none"},
		{SDE_SSPP_MULTIRECT_PARALLEL, "parallel"},
		{SDE_SSPP_MULTIRECT_TIME_MX,  "serial"},
	};
	const struct sde_format_extended *format_list;
	struct sde_kms_info *info;
	struct sde_plane *psde = to_sde_plane(plane);
@@ -4178,6 +4241,10 @@ static void _sde_plane_install_properties(struct drm_plane *plane,
		format_list = psde->pipe_sblk->virt_format_list;
		sde_kms_info_add_keyint(info, "primary_smart_plane_id",
						master_plane_id);
		msm_property_install_enum(&psde->property_info,
			"multirect_mode", 0x0, 0, e_multirect_mode,
			ARRAY_SIZE(e_multirect_mode),
			PLANE_PROP_MULTIRECT_MODE);
	}

	if (format_list) {