Commit ef042776 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-next-fixes-2023-02-16' of...

Merge tag 'drm-misc-next-fixes-2023-02-16' of git://anongit.freedesktop.org/drm/drm-misc

 into drm-next

Short summary of fixes pull:

Contains fixes for DP MST and the panel orientation on an Lenovo
IdeaPad model.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/Y+4H4C4E6cZcM9+J@linux-uq9g
parents 8573df34 38b2d8ef
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
	if (enable)
		drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
	else
		drm_dp_remove_payload(mst_mgr, mst_state, payload);
		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);

	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
	 * AUX message. The sequence is slot 1-63 allocated sequence for each
+43 −16
Original line number Diff line number Diff line
@@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
 * drm_dp_remove_payload() - Remove an MST payload
 * @mgr: Manager to use.
 * @mst_state: The MST atomic state
 * @payload: The payload to write
 * @old_payload: The payload with its old state
 * @new_payload: The payload to write
 *
 * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates
 * the starting time slots of all other payloads which would have been shifted towards the start of
@@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
 */
void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
			   struct drm_dp_mst_topology_state *mst_state,
			   struct drm_dp_mst_atomic_payload *payload)
			   const struct drm_dp_mst_atomic_payload *old_payload,
			   struct drm_dp_mst_atomic_payload *new_payload)
{
	struct drm_dp_mst_atomic_payload *pos;
	bool send_remove = false;

	/* We failed to make the payload, so nothing to do */
	if (payload->vc_start_slot == -1)
	if (new_payload->vc_start_slot == -1)
		return;

	mutex_lock(&mgr->lock);
	send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary);
	send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary);
	mutex_unlock(&mgr->lock);

	if (send_remove)
		drm_dp_destroy_payload_step1(mgr, mst_state, payload);
		drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
	else
		drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n",
			    payload->vcpi);
			    new_payload->vcpi);

	list_for_each_entry(pos, &mst_state->payloads, next) {
		if (pos != payload && pos->vc_start_slot > payload->vc_start_slot)
			pos->vc_start_slot -= payload->time_slots;
		if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
			pos->vc_start_slot -= old_payload->time_slots;
	}
	payload->vc_start_slot = -1;
	new_payload->vc_start_slot = -1;

	mgr->payload_count--;
	mgr->next_start_slot -= payload->time_slots;
	mgr->next_start_slot -= old_payload->time_slots;

	if (payload->delete)
		drm_dp_mst_put_port_malloc(payload->port);
	if (new_payload->delete)
		drm_dp_mst_put_port_malloc(new_payload->port);
}
EXPORT_SYMBOL(drm_dp_remove_payload);

@@ -5362,28 +5364,53 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a
}
EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);

/**
 * drm_atomic_get_old_mst_topology_state: get old MST topology state in atomic state, if any
 * @state: global atomic state
 * @mgr: MST topology manager, also the private object in this case
 *
 * This function wraps drm_atomic_get_old_private_obj_state() passing in the MST atomic
 * state vtable so that the private object state returned is that of a MST
 * topology object.
 *
 * Returns:
 *
 * The old MST topology state, or NULL if there's no topology state for this MST mgr
 * in the global atomic state
 */
struct drm_dp_mst_topology_state *
drm_atomic_get_old_mst_topology_state(struct drm_atomic_state *state,
				      struct drm_dp_mst_topology_mgr *mgr)
{
	struct drm_private_state *old_priv_state =
		drm_atomic_get_old_private_obj_state(state, &mgr->base);

	return old_priv_state ? to_dp_mst_topology_state(old_priv_state) : NULL;
}
EXPORT_SYMBOL(drm_atomic_get_old_mst_topology_state);

/**
 * drm_atomic_get_new_mst_topology_state: get new MST topology state in atomic state, if any
 * @state: global atomic state
 * @mgr: MST topology manager, also the private object in this case
 *
 * This function wraps drm_atomic_get_priv_obj_state() passing in the MST atomic
 * This function wraps drm_atomic_get_new_private_obj_state() passing in the MST atomic
 * state vtable so that the private object state returned is that of a MST
 * topology object.
 *
 * Returns:
 *
 * The MST topology state, or NULL if there's no topology state for this MST mgr
 * The new MST topology state, or NULL if there's no topology state for this MST mgr
 * in the global atomic state
 */
struct drm_dp_mst_topology_state *
drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
				      struct drm_dp_mst_topology_mgr *mgr)
{
	struct drm_private_state *priv_state =
	struct drm_private_state *new_priv_state =
		drm_atomic_get_new_private_obj_state(state, &mgr->base);

	return priv_state ? to_dp_mst_topology_state(priv_state) : NULL;
	return new_priv_state ? to_dp_mst_topology_state(new_priv_state) : NULL;
}
EXPORT_SYMBOL(drm_atomic_get_new_mst_topology_state);

+6 −0
Original line number Diff line number Diff line
@@ -322,6 +322,12 @@ static const struct dmi_system_id orientation_data[] = {
		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGL"),
		},
		.driver_data = (void *)&lcd800x1280_rightside_up,
	}, {	/* Lenovo IdeaPad Duet 3 10IGL5 */
		.matches = {
		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Duet 3 10IGL5"),
		},
		.driver_data = (void *)&lcd1200x1920_rightside_up,
	}, {	/* Lenovo Yoga Book X90F / X91F / X91L */
		.matches = {
		  /* Non exact match to match all versions */
+4 −0
Original line number Diff line number Diff line
@@ -5934,6 +5934,10 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
		if (ret)
			return ret;

		ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
		if (ret)
			return ret;

		ret = intel_atomic_add_affected_planes(state, crtc);
		if (ret)
			return ret;
+71 −4
Original line number Diff line number Diff line
@@ -524,8 +524,14 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
	struct intel_dp *intel_dp = &dig_port->dp;
	struct intel_connector *connector =
		to_intel_connector(old_conn_state->connector);
	struct drm_dp_mst_topology_state *mst_state =
		drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr);
	struct drm_dp_mst_topology_state *old_mst_state =
		drm_atomic_get_old_mst_topology_state(&state->base, &intel_dp->mst_mgr);
	struct drm_dp_mst_topology_state *new_mst_state =
		drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr);
	const struct drm_dp_mst_atomic_payload *old_payload =
		drm_atomic_get_mst_payload_state(old_mst_state, connector->port);
	struct drm_dp_mst_atomic_payload *new_payload =
		drm_atomic_get_mst_payload_state(new_mst_state, connector->port);
	struct drm_i915_private *i915 = to_i915(connector->base.dev);

	drm_dbg_kms(&i915->drm, "active links %d\n",
@@ -533,8 +539,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,

	intel_hdcp_disable(intel_mst->connector);

	drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state,
			      drm_atomic_get_mst_payload_state(mst_state, connector->port));
	drm_dp_remove_payload(&intel_dp->mst_mgr, new_mst_state,
			      old_payload, new_payload);

	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
}
@@ -1223,3 +1229,64 @@ bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state)
	return crtc_state->mst_master_transcoder != INVALID_TRANSCODER &&
	       crtc_state->mst_master_transcoder != crtc_state->cpu_transcoder;
}

/**
 * intel_dp_mst_add_topology_state_for_connector - add MST topology state for a connector
 * @state: atomic state
 * @connector: connector to add the state for
 * @crtc: the CRTC @connector is attached to
 *
 * Add the MST topology state for @connector to @state.
 *
 * Returns 0 on success, negative error code on failure.
 */
static int
intel_dp_mst_add_topology_state_for_connector(struct intel_atomic_state *state,
					      struct intel_connector *connector,
					      struct intel_crtc *crtc)
{
	struct drm_dp_mst_topology_state *mst_state;

	if (!connector->mst_port)
		return 0;

	mst_state = drm_atomic_get_mst_topology_state(&state->base,
						      &connector->mst_port->mst_mgr);
	if (IS_ERR(mst_state))
		return PTR_ERR(mst_state);

	mst_state->pending_crtc_mask |= drm_crtc_mask(&crtc->base);

	return 0;
}

/**
 * intel_dp_mst_add_topology_state_for_crtc - add MST topology state for a CRTC
 * @state: atomic state
 * @crtc: CRTC to add the state for
 *
 * Add the MST topology state for @crtc to @state.
 *
 * Returns 0 on success, negative error code on failure.
 */
int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
					     struct intel_crtc *crtc)
{
	struct drm_connector *_connector;
	struct drm_connector_state *conn_state;
	int i;

	for_each_new_connector_in_state(&state->base, _connector, conn_state, i) {
		struct intel_connector *connector = to_intel_connector(_connector);
		int ret;

		if (conn_state->crtc != &crtc->base)
			continue;

		ret = intel_dp_mst_add_topology_state_for_connector(state, connector, crtc);
		if (ret)
			return ret;
	}

	return 0;
}
Loading