Commit ef042776 authored by Dave Airlie's avatar Dave Airlie

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
...@@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( ...@@ -208,7 +208,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
if (enable) if (enable)
drm_dp_add_payload_part1(mst_mgr, mst_state, payload); drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
else 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 /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
* AUX message. The sequence is slot 1-63 allocated sequence for each * AUX message. The sequence is slot 1-63 allocated sequence for each
......
...@@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1); ...@@ -3342,7 +3342,8 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
* drm_dp_remove_payload() - Remove an MST payload * drm_dp_remove_payload() - Remove an MST payload
* @mgr: Manager to use. * @mgr: Manager to use.
* @mst_state: The MST atomic state * @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 * 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 * 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); ...@@ -3350,36 +3351,37 @@ EXPORT_SYMBOL(drm_dp_add_payload_part1);
*/ */
void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr, void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_topology_state *mst_state, 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; struct drm_dp_mst_atomic_payload *pos;
bool send_remove = false; bool send_remove = false;
/* We failed to make the payload, so nothing to do */ /* We failed to make the payload, so nothing to do */
if (payload->vc_start_slot == -1) if (new_payload->vc_start_slot == -1)
return; return;
mutex_lock(&mgr->lock); 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); mutex_unlock(&mgr->lock);
if (send_remove) if (send_remove)
drm_dp_destroy_payload_step1(mgr, mst_state, payload); drm_dp_destroy_payload_step1(mgr, mst_state, new_payload);
else else
drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n", 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) { list_for_each_entry(pos, &mst_state->payloads, next) {
if (pos != payload && pos->vc_start_slot > payload->vc_start_slot) if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot)
pos->vc_start_slot -= payload->time_slots; pos->vc_start_slot -= old_payload->time_slots;
} }
payload->vc_start_slot = -1; new_payload->vc_start_slot = -1;
mgr->payload_count--; mgr->payload_count--;
mgr->next_start_slot -= payload->time_slots; mgr->next_start_slot -= old_payload->time_slots;
if (payload->delete) if (new_payload->delete)
drm_dp_mst_put_port_malloc(payload->port); drm_dp_mst_put_port_malloc(new_payload->port);
} }
EXPORT_SYMBOL(drm_dp_remove_payload); 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 ...@@ -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); 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 * drm_atomic_get_new_mst_topology_state: get new MST topology state in atomic state, if any
* @state: global atomic state * @state: global atomic state
* @mgr: MST topology manager, also the private object in this case * @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 * state vtable so that the private object state returned is that of a MST
* topology object. * topology object.
* *
* Returns: * 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 * in the global atomic state
*/ */
struct drm_dp_mst_topology_state * struct drm_dp_mst_topology_state *
drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state, drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
struct drm_dp_mst_topology_mgr *mgr) 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); 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); EXPORT_SYMBOL(drm_atomic_get_new_mst_topology_state);
......
...@@ -322,6 +322,12 @@ static const struct dmi_system_id orientation_data[] = { ...@@ -322,6 +322,12 @@ static const struct dmi_system_id orientation_data[] = {
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGL"), DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGL"),
}, },
.driver_data = (void *)&lcd800x1280_rightside_up, .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 */ }, { /* Lenovo Yoga Book X90F / X91F / X91L */
.matches = { .matches = {
/* Non exact match to match all versions */ /* Non exact match to match all versions */
......
...@@ -5934,6 +5934,10 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state, ...@@ -5934,6 +5934,10 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
if (ret) if (ret)
return 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); ret = intel_atomic_add_affected_planes(state, crtc);
if (ret) if (ret)
return ret; return ret;
......
...@@ -524,8 +524,14 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state, ...@@ -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_dp *intel_dp = &dig_port->dp;
struct intel_connector *connector = struct intel_connector *connector =
to_intel_connector(old_conn_state->connector); to_intel_connector(old_conn_state->connector);
struct drm_dp_mst_topology_state *mst_state = struct drm_dp_mst_topology_state *old_mst_state =
drm_atomic_get_mst_topology_state(&state->base, &intel_dp->mst_mgr); 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); struct drm_i915_private *i915 = to_i915(connector->base.dev);
drm_dbg_kms(&i915->drm, "active links %d\n", drm_dbg_kms(&i915->drm, "active links %d\n",
...@@ -533,8 +539,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state, ...@@ -533,8 +539,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
intel_hdcp_disable(intel_mst->connector); intel_hdcp_disable(intel_mst->connector);
drm_dp_remove_payload(&intel_dp->mst_mgr, mst_state, drm_dp_remove_payload(&intel_dp->mst_mgr, new_mst_state,
drm_atomic_get_mst_payload_state(mst_state, connector->port)); old_payload, new_payload);
intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); 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) ...@@ -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 && return crtc_state->mst_master_transcoder != INVALID_TRANSCODER &&
crtc_state->mst_master_transcoder != crtc_state->cpu_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;
}
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <linux/types.h> #include <linux/types.h>
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state; struct intel_crtc_state;
struct intel_digital_port; struct intel_digital_port;
struct intel_dp; struct intel_dp;
...@@ -18,5 +20,7 @@ int intel_dp_mst_encoder_active_links(struct intel_digital_port *dig_port); ...@@ -18,5 +20,7 @@ int intel_dp_mst_encoder_active_links(struct intel_digital_port *dig_port);
bool intel_dp_mst_is_master_trans(const struct intel_crtc_state *crtc_state); bool intel_dp_mst_is_master_trans(const struct intel_crtc_state *crtc_state);
bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state); bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state);
bool intel_dp_mst_source_support(struct intel_dp *intel_dp); bool intel_dp_mst_source_support(struct intel_dp *intel_dp);
int intel_dp_mst_add_topology_state_for_crtc(struct intel_atomic_state *state,
struct intel_crtc *crtc);
#endif /* __INTEL_DP_MST_H__ */ #endif /* __INTEL_DP_MST_H__ */
...@@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state, ...@@ -885,7 +885,7 @@ nv50_msto_prepare(struct drm_atomic_state *state,
// TODO: Figure out if we want to do a better job of handling VCPI allocation failures here? // TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
if (msto->disabled) { if (msto->disabled) {
drm_dp_remove_payload(mgr, mst_state, payload); drm_dp_remove_payload(mgr, mst_state, payload, payload);
nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0); nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
} else { } else {
......
...@@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr, ...@@ -841,7 +841,8 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_atomic_payload *payload); struct drm_dp_mst_atomic_payload *payload);
void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr, void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_topology_state *mst_state, 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);
int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr); int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr);
...@@ -867,6 +868,9 @@ struct drm_dp_mst_topology_state * ...@@ -867,6 +868,9 @@ struct drm_dp_mst_topology_state *
drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
struct drm_dp_mst_topology_mgr *mgr); struct drm_dp_mst_topology_mgr *mgr);
struct drm_dp_mst_topology_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_dp_mst_topology_state *
drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state, drm_atomic_get_new_mst_topology_state(struct drm_atomic_state *state,
struct drm_dp_mst_topology_mgr *mgr); struct drm_dp_mst_topology_mgr *mgr);
struct drm_dp_mst_atomic_payload * struct drm_dp_mst_atomic_payload *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment