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

Commit 76913944 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: support release/retire fence through set prop"

parents dee4adf2 b24b2d61
Loading
Loading
Loading
Loading
+23 −6
Original line number Diff line number Diff line
@@ -955,6 +955,7 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
	struct sde_connector *c_conn;
	struct sde_connector_state *c_state;
	int idx, rc;
	uint64_t fence_fd;

	if (!connector || !state || !property) {
		SDE_ERROR("invalid argument(s), conn %pK, state %pK, prp %pK\n",
@@ -993,14 +994,30 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
					c_conn->fb_kmap);
		}
		break;
	default:
		break;
	case CONNECTOR_PROP_RETIRE_FENCE:
		rc = sde_fence_create(&c_conn->retire_fence, &fence_fd, 0);
		if (rc) {
			SDE_ERROR("fence create failed rc:%d\n", rc);
			goto end;
		}

	if (idx == CONNECTOR_PROP_ROI_V1) {
		rc = copy_to_user((uint64_t __user *)val, &fence_fd,
			sizeof(uint64_t));
		if (rc) {
			SDE_ERROR("copy to user failed rc:%d\n", rc);
			/* fence will be released with timeline update */
			put_unused_fd(fence_fd);
			rc = -EFAULT;
			goto end;
		}
		break;
	case CONNECTOR_PROP_ROI_V1:
		rc = _sde_connector_set_roi_v1(c_conn, c_state, (void *)val);
		if (rc)
			SDE_ERROR_CONN(c_conn, "invalid roi_v1, rc: %d\n", rc);
		break;
	default:
		break;
	}

	if (idx == CONNECTOR_PROP_HDR_METADATA) {
@@ -1701,8 +1718,8 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
	msm_property_install_volatile_range(&c_conn->property_info,
		"hdr_metadata", 0x0, 0, ~0, 0, CONNECTOR_PROP_HDR_METADATA);

	msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
			0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
	msm_property_install_volatile_range(&c_conn->property_info,
		"RETIRE_FENCE", 0x0, 0, ~0, 0, CONNECTOR_PROP_RETIRE_FENCE);

	msm_property_install_range(&c_conn->property_info, "autorefresh",
			0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0,
+76 −51
Original line number Diff line number Diff line
@@ -4803,8 +4803,8 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
		"input_fence_timeout", 0x0, 0, SDE_CRTC_MAX_INPUT_FENCE_TIMEOUT,
		SDE_CRTC_INPUT_FENCE_TIMEOUT, CRTC_PROP_INPUT_FENCE_TIMEOUT);

	msm_property_install_range(&sde_crtc->property_info, "output_fence",
			0x0, 0, INR_OPEN_MAX, 0, CRTC_PROP_OUTPUT_FENCE);
	msm_property_install_volatile_range(&sde_crtc->property_info,
		"output_fence", 0x0, 0, ~0, 0, CRTC_PROP_OUTPUT_FENCE);

	msm_property_install_range(&sde_crtc->property_info,
			"output_fence_offset", 0x0, 0, 1, 0,
@@ -4976,6 +4976,47 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
	kfree(info);
}

static int _sde_crtc_get_output_fence(struct drm_crtc *crtc,
	const struct drm_crtc_state *state, uint64_t *val)
{
	struct drm_encoder *encoder;
	struct sde_crtc *sde_crtc;
	struct sde_crtc_state *cstate;
	uint32_t offset, i;
	bool conn_offset = 0, is_cmd = true;

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

	for (i = 0; i < cstate->num_connectors; ++i) {
		conn_offset = sde_connector_needs_offset(cstate->connectors[i]);
		if (conn_offset)
			break;
	}

	/**
	 * set the cmd flag only when all the encoders attached
	 * to the crtc are in cmd mode. Consider all other cases
	 * as video mode.
	 */
	drm_for_each_encoder(encoder, crtc->dev) {
		if (encoder->crtc == crtc)
			is_cmd = sde_encoder_check_mode(encoder,
					MSM_DISPLAY_CAP_CMD_MODE);
	}

	offset = sde_crtc_get_property(cstate, CRTC_PROP_OUTPUT_FENCE_OFFSET);

	/**
	 * set the offset to 0 only for cmd mode panels, so
	 * the release fence for the current frame can be
	 * triggered right after PP_DONE interrupt.
	 */
	offset = is_cmd ? 0 : (offset + conn_offset);

	return sde_fence_create(&sde_crtc->output_fence, val, offset);
}

/**
 * sde_crtc_atomic_set_property - atomically set a crtc drm property
 * @crtc: Pointer to drm crtc structure
@@ -4992,6 +5033,7 @@ static int sde_crtc_atomic_set_property(struct drm_crtc *crtc,
	struct sde_crtc *sde_crtc;
	struct sde_crtc_state *cstate;
	int idx, ret;
	uint64_t fence_fd;

	if (!crtc || !state || !property) {
		SDE_ERROR("invalid argument(s)\n");
@@ -5044,6 +5086,22 @@ static int sde_crtc_atomic_set_property(struct drm_crtc *crtc,
		cstate->bw_control = true;
		cstate->bw_split_vote = true;
		break;
	case CRTC_PROP_OUTPUT_FENCE:
		ret = _sde_crtc_get_output_fence(crtc, state, &fence_fd);
		if (ret) {
			SDE_ERROR("fence create failed rc:%d\n", ret);
			goto exit;
		}

		ret = copy_to_user((uint64_t __user *)val, &fence_fd,
				sizeof(uint64_t));
		if (ret) {
			SDE_ERROR("copy to user failed rc:%d\n", ret);
			put_unused_fd(fence_fd);
			ret = -EFAULT;
			goto exit;
		}
		break;
	default:
		/* nothing to do */
		break;
@@ -5090,62 +5148,29 @@ static int sde_crtc_atomic_get_property(struct drm_crtc *crtc,
{
	struct sde_crtc *sde_crtc;
	struct sde_crtc_state *cstate;
	struct drm_encoder *encoder;
	int i, ret = -EINVAL;
	bool conn_offset = 0;
	bool is_cmd = true;
	int ret = -EINVAL, i;

	if (!crtc || !state) {
		SDE_ERROR("invalid argument(s)\n");
	} else {
		sde_crtc = to_sde_crtc(crtc);
		cstate = to_sde_crtc_state(state);

		for (i = 0; i < cstate->num_connectors; ++i) {
			conn_offset = sde_connector_needs_offset(
						cstate->connectors[i]);
			if (conn_offset)
				break;
		goto end;
	}

		/**
		 * set the cmd flag only when all the encoders attached
		 * to the crtc are in cmd mode. Consider all other cases
		 * as video mode.
		 */
		drm_for_each_encoder(encoder, crtc->dev) {
			if (encoder->crtc == crtc)
				is_cmd = sde_encoder_check_mode(encoder,
						MSM_DISPLAY_CAP_CMD_MODE);
		}
	sde_crtc = to_sde_crtc(crtc);
	cstate = to_sde_crtc_state(state);

	i = msm_property_index(&sde_crtc->property_info, property);
	if (i == CRTC_PROP_OUTPUT_FENCE) {
			uint32_t offset = sde_crtc_get_property(cstate,
					CRTC_PROP_OUTPUT_FENCE_OFFSET);

			/**
			 * set the offset to 0 only for cmd mode panels, so
			 * the release fence for the current frame can be
			 * triggered right after PP_DONE interrupt.
			 */
			offset = is_cmd ? 0 : (offset + conn_offset);

			ret = sde_fence_create(&sde_crtc->output_fence, val,
								offset);
			if (ret)
				SDE_ERROR("fence create failed\n");
		ret = _sde_crtc_get_output_fence(crtc, state, val);
	} else {
		ret = msm_property_atomic_get(&sde_crtc->property_info,
					&cstate->property_state,
					property, val);
			&cstate->property_state, property, val);
		if (ret)
				ret = sde_cp_crtc_get_property(crtc,
					property, val);
			ret = sde_cp_crtc_get_property(crtc, property, val);
	}
	if (ret)
		DRM_ERROR("get property failed\n");
	}

end:
	return ret;
}