diff mbox

drm: Pass crtc to .best_encoder()

Message ID 20180615195221.18119-1-ville.syrjala@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ville Syrjälä June 15, 2018, 7:52 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

To pick the correct MST encoder i915 wants to know which crtc is going
to be feeding us. To that end let's pass the crtc to the .best_encoder()
hook. The atomic variant already knows the crtc via the connector state,
but the non-atomic hooks is still being used by the fb_helper even on
atomic drivers.

This allows us to fix up the possible_crtcs bitmask for the i915 MST
encoders. We have one encoder for each crtc+port combination, and thus
we have to know both the connector and the crtc to pick the right one.
This has only worked so far because every MST encoder lied in its
possible_crtcs bitmask that they can be driven by any crtc.

I took the easy way out and passed NULL as the crtc for all the driver
internal uses of .best_encoder() in the amdgpu/radeon drivers. None of
the other drivers have such internal uses. The other callers
(crtc_helper, atomic_helper, fb_helper) will pass in the proper crtc.
but no one besides i915 will currently look at it.

Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: "Christian König" <christian.koenig@amd.com>
Cc: "David (ChunMing) Zhou" <David1.Zhou@amd.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: amd-gfx@lists.freedesktop.org
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c     | 33 +++++++++--------
 drivers/gpu/drm/amd/amdgpu/dce_virtual.c           |  3 +-
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |  7 ++--
 .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c    |  5 +--
 drivers/gpu/drm/ast/ast_mode.c                     |  3 +-
 drivers/gpu/drm/bochs/bochs_kms.c                  |  3 +-
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  3 +-
 drivers/gpu/drm/bridge/tc358767.c                  |  3 +-
 drivers/gpu/drm/cirrus/cirrus_mode.c               |  5 +--
 drivers/gpu/drm/drm_atomic_helper.c                | 16 ++++++---
 drivers/gpu/drm/drm_crtc_helper.c                  |  3 +-
 drivers/gpu/drm/drm_fb_helper.c                    | 41 ++++++++++++----------
 drivers/gpu/drm/gma500/gma_display.c               |  3 +-
 drivers/gpu/drm/gma500/mdfld_dsi_output.c          |  5 +--
 drivers/gpu/drm/gma500/psb_intel_drv.h             |  3 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c   |  3 +-
 drivers/gpu/drm/i2c/tda998x_drv.c                  |  3 +-
 drivers/gpu/drm/i915/intel_dp_mst.c                |  9 +++--
 drivers/gpu/drm/imx/imx-ldb.c                      |  5 +--
 drivers/gpu/drm/imx/imx-tve.c                      |  5 +--
 drivers/gpu/drm/imx/parallel-display.c             |  5 +--
 drivers/gpu/drm/mediatek/mtk_hdmi.c                |  3 +-
 drivers/gpu/drm/mgag200/mgag200_mode.c             |  5 +--
 drivers/gpu/drm/msm/dsi/dsi_manager.c              |  3 +-
 drivers/gpu/drm/nouveau/dispnv50/disp.c            |  3 +-
 drivers/gpu/drm/nouveau/nouveau_connector.c        |  3 +-
 drivers/gpu/drm/qxl/qxl_display.c                  |  3 +-
 drivers/gpu/drm/radeon/radeon_connectors.c         | 40 +++++++++++----------
 drivers/gpu/drm/radeon/radeon_dp_mst.c             |  5 +--
 drivers/gpu/drm/shmobile/shmob_drm_crtc.c          |  3 +-
 drivers/gpu/drm/tilcdc/tilcdc_panel.c              |  5 +--
 drivers/gpu/drm/tilcdc/tilcdc_tfp410.c             |  5 +--
 drivers/gpu/drm/udl/udl_connector.c                |  3 +-
 drivers/staging/vboxvideo/vbox_mode.c              |  5 +--
 include/drm/drm_atomic_helper.h                    |  3 +-
 include/drm/drm_modeset_helper_vtables.h           |  6 ++--
 36 files changed, 155 insertions(+), 106 deletions(-)

Comments

Harry Wentland June 26, 2018, 3:01 p.m. UTC | #1
On 2018-06-15 03:52 PM, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> To pick the correct MST encoder i915 wants to know which crtc is going
> to be feeding us. To that end let's pass the crtc to the .best_encoder()
> hook. The atomic variant already knows the crtc via the connector state,
> but the non-atomic hooks is still being used by the fb_helper even on
> atomic drivers.
> 
> This allows us to fix up the possible_crtcs bitmask for the i915 MST
> encoders. We have one encoder for each crtc+port combination, and thus
> we have to know both the connector and the crtc to pick the right one.
> This has only worked so far because every MST encoder lied in its
> possible_crtcs bitmask that they can be driven by any crtc.
> 
> I took the easy way out and passed NULL as the crtc for all the driver
> internal uses of .best_encoder() in the amdgpu/radeon drivers. None of
> the other drivers have such internal uses. The other callers
> (crtc_helper, atomic_helper, fb_helper) will pass in the proper crtc.
> but no one besides i915 will currently look at it.
> 
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: "Christian König" <christian.koenig@amd.com>
> Cc: "David (ChunMing) Zhou" <David1.Zhou@amd.com>
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

amdgpu parts are
Acked-by: Harry Wentland <harry.wentland@amd.com>

Harry

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c     | 33 +++++++++--------
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.c           |  3 +-
>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |  7 ++--
>  .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c    |  5 +--
>  drivers/gpu/drm/ast/ast_mode.c                     |  3 +-
>  drivers/gpu/drm/bochs/bochs_kms.c                  |  3 +-
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  3 +-
>  drivers/gpu/drm/bridge/tc358767.c                  |  3 +-
>  drivers/gpu/drm/cirrus/cirrus_mode.c               |  5 +--
>  drivers/gpu/drm/drm_atomic_helper.c                | 16 ++++++---
>  drivers/gpu/drm/drm_crtc_helper.c                  |  3 +-
>  drivers/gpu/drm/drm_fb_helper.c                    | 41 ++++++++++++----------
>  drivers/gpu/drm/gma500/gma_display.c               |  3 +-
>  drivers/gpu/drm/gma500/mdfld_dsi_output.c          |  5 +--
>  drivers/gpu/drm/gma500/psb_intel_drv.h             |  3 +-
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c   |  3 +-
>  drivers/gpu/drm/i2c/tda998x_drv.c                  |  3 +-
>  drivers/gpu/drm/i915/intel_dp_mst.c                |  9 +++--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  5 +--
>  drivers/gpu/drm/imx/imx-tve.c                      |  5 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  5 +--
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                |  3 +-
>  drivers/gpu/drm/mgag200/mgag200_mode.c             |  5 +--
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              |  3 +-
>  drivers/gpu/drm/nouveau/dispnv50/disp.c            |  3 +-
>  drivers/gpu/drm/nouveau/nouveau_connector.c        |  3 +-
>  drivers/gpu/drm/qxl/qxl_display.c                  |  3 +-
>  drivers/gpu/drm/radeon/radeon_connectors.c         | 40 +++++++++++----------
>  drivers/gpu/drm/radeon/radeon_dp_mst.c             |  5 +--
>  drivers/gpu/drm/shmobile/shmob_drm_crtc.c          |  3 +-
>  drivers/gpu/drm/tilcdc/tilcdc_panel.c              |  5 +--
>  drivers/gpu/drm/tilcdc/tilcdc_tfp410.c             |  5 +--
>  drivers/gpu/drm/udl/udl_connector.c                |  3 +-
>  drivers/staging/vboxvideo/vbox_mode.c              |  5 +--
>  include/drm/drm_atomic_helper.h                    |  3 +-
>  include/drm/drm_modeset_helper_vtables.h           |  6 ++--
>  36 files changed, 155 insertions(+), 106 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
> index 8e66851eb427..3dfa50ec2589 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
> @@ -135,7 +135,8 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
>  		else {
>  			const struct drm_connector_helper_funcs *connector_funcs =
>  				connector->helper_private;
> -			struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
> +			struct drm_encoder *encoder = connector_funcs->best_encoder(connector,
> +										    NULL);
>  			struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
>  			struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
>  
> @@ -218,7 +219,7 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector,
>  	bool connected;
>  	int i;
>  
> -	best_encoder = connector_funcs->best_encoder(connector);
> +	best_encoder = connector_funcs->best_encoder(connector, NULL);
>  
>  	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
>  		if (connector->encoder_ids[i] == 0)
> @@ -358,7 +359,8 @@ static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
>  }
>  
>  static struct drm_encoder *
> -amdgpu_connector_best_single_encoder(struct drm_connector *connector)
> +amdgpu_connector_best_single_encoder(struct drm_connector *connector,
> +				     struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  
> @@ -370,7 +372,7 @@ amdgpu_connector_best_single_encoder(struct drm_connector *connector)
>  
>  static void amdgpu_get_native_mode(struct drm_connector *connector)
>  {
> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	struct amdgpu_encoder *amdgpu_encoder;
>  
>  	if (encoder == NULL)
> @@ -593,7 +595,7 @@ static int amdgpu_connector_set_property(struct drm_connector *connector,
>  			amdgpu_encoder = to_amdgpu_encoder(connector->encoder);
>  		} else {
>  			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
> -			amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector));
> +			amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector, NULL));
>  		}
>  
>  		switch (val) {
> @@ -663,7 +665,7 @@ static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
>  	amdgpu_connector_get_edid(connector);
>  	ret = amdgpu_connector_ddc_get_modes(connector);
>  	if (ret > 0) {
> -		encoder = amdgpu_connector_best_single_encoder(connector);
> +		encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  		if (encoder) {
>  			amdgpu_connector_fixup_lcd_native_mode(encoder, connector);
>  			/* add scaled modes */
> @@ -672,7 +674,7 @@ static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
>  		return ret;
>  	}
>  
> -	encoder = amdgpu_connector_best_single_encoder(connector);
> +	encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		return 0;
>  
> @@ -694,7 +696,7 @@ static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
>  static enum drm_mode_status amdgpu_connector_lvds_mode_valid(struct drm_connector *connector,
>  					     struct drm_display_mode *mode)
>  {
> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  
>  	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>  		return MODE_PANEL;
> @@ -725,7 +727,7 @@ static enum drm_connector_status
>  amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)
>  {
>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	enum drm_connector_status ret = connector_status_disconnected;
>  	int r;
>  
> @@ -798,7 +800,7 @@ static int amdgpu_connector_set_lcd_property(struct drm_connector *connector,
>  		amdgpu_encoder = to_amdgpu_encoder(connector->encoder);
>  	else {
>  		const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
> -		amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector));
> +		amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector, NULL));
>  	}
>  
>  	switch (value) {
> @@ -873,7 +875,7 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
>  			return connector_status_disconnected;
>  	}
>  
> -	encoder = amdgpu_connector_best_single_encoder(connector);
> +	encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		ret = connector_status_disconnected;
>  
> @@ -1130,7 +1132,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
>  
>  /* okay need to be smart in here about which encoder to pick */
>  static struct drm_encoder *
> -amdgpu_connector_dvi_encoder(struct drm_connector *connector)
> +amdgpu_connector_dvi_encoder(struct drm_connector *connector,
> +			     struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
> @@ -1224,7 +1227,7 @@ static int amdgpu_connector_dp_get_modes(struct drm_connector *connector)
>  {
>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
>  	struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv;
> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	int ret;
>  
>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
> @@ -1363,7 +1366,7 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
>  	enum drm_connector_status ret = connector_status_disconnected;
>  	struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv;
> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	int r;
>  
>  	if (!drm_kms_helper_is_poll_worker()) {
> @@ -1458,7 +1461,7 @@ static enum drm_mode_status amdgpu_connector_dp_mode_valid(struct drm_connector
>  
>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
>  	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
> -		struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +		struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  
>  		if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>  			return MODE_PANEL;
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> index dbf2ccd0c744..b02ce39e65b7 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> @@ -267,7 +267,8 @@ static int dce_virtual_early_init(void *handle)
>  }
>  
>  static struct drm_encoder *
> -dce_virtual_encoder(struct drm_connector *connector)
> +dce_virtual_encoder(struct drm_connector *connector,
> +		    struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	struct drm_encoder *encoder;
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 3e1c2a04d669..e56ed4e5818f 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -2758,7 +2758,8 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
>  	.atomic_get_property = amdgpu_dm_connector_atomic_get_property
>  };
>  
> -static struct drm_encoder *best_encoder(struct drm_connector *connector)
> +static struct drm_encoder *best_encoder(struct drm_connector *connector,
> +					struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	struct drm_mode_object *obj;
> @@ -3304,7 +3305,7 @@ static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
>  	struct drm_encoder *encoder;
>  	struct amdgpu_encoder *amdgpu_encoder;
>  
> -	encoder = helper->best_encoder(connector);
> +	encoder = helper->best_encoder(connector, NULL);
>  
>  	if (encoder == NULL)
>  		return;
> @@ -3438,7 +3439,7 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
>  	struct drm_encoder *encoder;
>  	struct edid *edid = amdgpu_dm_connector->edid;
>  
> -	encoder = helper->best_encoder(connector);
> +	encoder = helper->best_encoder(connector, NULL);
>  	amdgpu_dm_connector_ddc_get_modes(connector, edid);
>  	amdgpu_dm_connector_add_common_modes(encoder, connector);
>  
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> index 4304d9e408b8..4544a1401caf 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> @@ -269,7 +269,8 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
>  	return ret;
>  }
>  
> -static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector)
> +static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector,
> +					       struct drm_crtc *crtc)
>  {
>  	struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
>  
> @@ -302,7 +303,7 @@ dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector)
>  	const struct drm_connector_helper_funcs *connector_funcs =
>  		connector->base.helper_private;
>  	struct drm_encoder *enc_master =
> -		connector_funcs->best_encoder(&connector->base);
> +		connector_funcs->best_encoder(&connector->base, NULL);
>  
>  	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
>  	amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
> diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
> index 036dff8a1f33..d5899aa41d37 100644
> --- a/drivers/gpu/drm/ast/ast_mode.c
> +++ b/drivers/gpu/drm/ast/ast_mode.c
> @@ -709,7 +709,8 @@ static void ast_encoder_destroy(struct drm_encoder *encoder)
>  }
>  
>  
> -static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector)
> +static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector,
> +						   struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	/* pick the encoder ids */
> diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
> index 233980a78591..dc80a238feef 100644
> --- a/drivers/gpu/drm/bochs/bochs_kms.c
> +++ b/drivers/gpu/drm/bochs/bochs_kms.c
> @@ -208,7 +208,8 @@ static enum drm_mode_status bochs_connector_mode_valid(struct drm_connector *con
>  }
>  
>  static struct drm_encoder *
> -bochs_connector_best_encoder(struct drm_connector *connector)
> +bochs_connector_best_encoder(struct drm_connector *connector,
> +			     struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	/* pick the encoder ids */
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 2bcbfadb6ac5..0706471c8c63 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1137,7 +1137,8 @@ static int analogix_dp_get_modes(struct drm_connector *connector)
>  }
>  
>  static struct drm_encoder *
> -analogix_dp_best_encoder(struct drm_connector *connector)
> +analogix_dp_best_encoder(struct drm_connector *connector,
> +			 struct drm_crtc *crtc)
>  {
>  	struct analogix_dp_device *dp = to_dp(connector);
>  
> diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
> index 0fd9cf27542c..7cd954226fe3 100644
> --- a/drivers/gpu/drm/bridge/tc358767.c
> +++ b/drivers/gpu/drm/bridge/tc358767.c
> @@ -1155,7 +1155,8 @@ static void tc_connector_set_polling(struct tc_data *tc,
>  }
>  
>  static struct drm_encoder *
> -tc_connector_best_encoder(struct drm_connector *connector)
> +tc_connector_best_encoder(struct drm_connector *connector,
> +			  struct drm_crtc *crtc)
>  {
>  	struct tc_data *tc = connector_to_tc(connector);
>  
> diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
> index b529f8c8e2a6..378ebc3f25e8 100644
> --- a/drivers/gpu/drm/cirrus/cirrus_mode.c
> +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
> @@ -451,8 +451,9 @@ static int cirrus_vga_get_modes(struct drm_connector *connector)
>  	return count;
>  }
>  
> -static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
> -						  *connector)
> +static struct drm_encoder *
> +cirrus_connector_best_encoder(struct drm_connector *connector,
> +			      struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	/* pick the encoder ids */
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index 232fa11a5e31..bd3aebbfd5b4 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -115,9 +115,11 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
>  		if (funcs->atomic_best_encoder)
>  			new_encoder = funcs->atomic_best_encoder(connector, new_conn_state);
>  		else if (funcs->best_encoder)
> -			new_encoder = funcs->best_encoder(connector);
> +			new_encoder = funcs->best_encoder(connector,
> +							  new_conn_state->crtc);
>  		else
> -			new_encoder = drm_atomic_helper_best_encoder(connector);
> +			new_encoder = drm_atomic_helper_best_encoder(connector,
> +								     new_conn_state->crtc);
>  
>  		if (new_encoder) {
>  			if (encoder_mask & (1 << drm_encoder_index(new_encoder))) {
> @@ -312,9 +314,11 @@ update_connector_routing(struct drm_atomic_state *state,
>  		new_encoder = funcs->atomic_best_encoder(connector,
>  							 new_connector_state);
>  	else if (funcs->best_encoder)
> -		new_encoder = funcs->best_encoder(connector);
> +		new_encoder = funcs->best_encoder(connector,
> +						  new_connector_state->crtc);
>  	else
> -		new_encoder = drm_atomic_helper_best_encoder(connector);
> +		new_encoder = drm_atomic_helper_best_encoder(connector,
> +							     new_connector_state->crtc);
>  
>  	if (!new_encoder) {
>  		DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n",
> @@ -3318,13 +3322,15 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
>   * drm_atomic_helper_best_encoder - Helper for
>   * 	&drm_connector_helper_funcs.best_encoder callback
>   * @connector: Connector control structure
> + * @crtc: DRM crtc
>   *
>   * This is a &drm_connector_helper_funcs.best_encoder callback helper for
>   * connectors that support exactly 1 encoder, statically determined at driver
>   * init time.
>   */
>  struct drm_encoder *
> -drm_atomic_helper_best_encoder(struct drm_connector *connector)
> +drm_atomic_helper_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	WARN_ON(connector->encoder_ids[1]);
>  	return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index 5a84c3bc915d..f9318fc11fb1 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -637,7 +637,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set,
>  		new_encoder = connector->encoder;
>  		for (ro = 0; ro < set->num_connectors; ro++) {
>  			if (set->connectors[ro] == connector) {
> -				new_encoder = connector_funcs->best_encoder(connector);
> +				new_encoder = connector_funcs->best_encoder(connector,
> +									    set->crtc);
>  				/* if we can't get an encoder for a connector
>  				   we are setting now - then fail */
>  				if (new_encoder == NULL)
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index cab14f253384..ce91ae12cccb 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -2331,9 +2331,8 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
>  	int c, o;
>  	struct drm_connector *connector;
>  	const struct drm_connector_helper_funcs *connector_funcs;
> -	struct drm_encoder *encoder;
>  	int my_score, best_score, score;
> -	struct drm_fb_helper_crtc **crtcs, *crtc;
> +	struct drm_fb_helper_crtc **crtcs;
>  	struct drm_fb_helper_connector *fb_helper_conn;
>  
>  	if (n == fb_helper->connector_count)
> @@ -2362,28 +2361,32 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
>  
>  	connector_funcs = connector->helper_private;
>  
> -	/*
> -	 * If the DRM device implements atomic hooks and ->best_encoder() is
> -	 * NULL we fallback to the default drm_atomic_helper_best_encoder()
> -	 * helper.
> -	 */
> -	if (drm_drv_uses_atomic_modeset(fb_helper->dev) &&
> -	    !connector_funcs->best_encoder)
> -		encoder = drm_atomic_helper_best_encoder(connector);
> -	else
> -		encoder = connector_funcs->best_encoder(connector);
> -
> -	if (!encoder)
> -		goto out;
> -
>  	/*
>  	 * select a crtc for this connector and then attempt to configure
>  	 * remaining connectors
>  	 */
>  	for (c = 0; c < fb_helper->crtc_count; c++) {
> -		crtc = &fb_helper->crtc_info[c];
> +		struct drm_encoder *encoder;
> +		struct drm_fb_helper_crtc *crtc = &fb_helper->crtc_info[c];
>  
> -		if ((encoder->possible_crtcs & (1 << c)) == 0)
> +		/*
> +		 * If the DRM device implements atomic hooks and ->best_encoder() is
> +		 * NULL we fallback to the default drm_atomic_helper_best_encoder()
> +		 * helper.
> +		 */
> +		if (drm_drv_uses_atomic_modeset(fb_helper->dev) &&
> +		    !connector_funcs->best_encoder)
> +			encoder = drm_atomic_helper_best_encoder(connector,
> +								 crtc->mode_set.crtc);
> +		else
> +			encoder = connector_funcs->best_encoder(connector,
> +								crtc->mode_set.crtc);
> +
> +		if (!encoder)
> +			continue;
> +
> +		if ((encoder->possible_crtcs &
> +		     drm_crtc_mask(crtc->mode_set.crtc)) == 0)
>  			continue;
>  
>  		for (o = 0; o < n; o++)
> @@ -2410,7 +2413,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
>  			       sizeof(struct drm_fb_helper_crtc *));
>  		}
>  	}
> -out:
> +
>  	kfree(crtcs);
>  	return best_score;
>  }
> diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
> index c8f071c47daf..251b64653dc8 100644
> --- a/drivers/gpu/drm/gma500/gma_display.c
> +++ b/drivers/gpu/drm/gma500/gma_display.c
> @@ -652,7 +652,8 @@ void gma_encoder_destroy(struct drm_encoder *encoder)
>  }
>  
>  /* Currently there is only a 1:1 mapping of encoders and connectors */
> -struct drm_encoder *gma_best_encoder(struct drm_connector *connector)
> +struct drm_encoder *gma_best_encoder(struct drm_connector *connector,
> +				     struct drm_crtc *crtc)
>  {
>  	struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
>  
> diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> index fe020926ea4f..9e5b059a9e5b 100644
> --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> @@ -377,8 +377,9 @@ static enum drm_mode_status mdfld_dsi_connector_mode_valid(struct drm_connector
>  	return MODE_OK;
>  }
>  
> -static struct drm_encoder *mdfld_dsi_connector_best_encoder(
> -				struct drm_connector *connector)
> +static struct drm_encoder *
> +mdfld_dsi_connector_best_encoder(struct drm_connector *connector,
> +				 struct drm_crtc *crtc)
>  {
>  	struct mdfld_dsi_connector *dsi_connector =
>  				mdfld_dsi_connector(connector);
> diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
> index e05e5399af2d..e903525b9d30 100644
> --- a/drivers/gpu/drm/gma500/psb_intel_drv.h
> +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
> @@ -230,7 +230,8 @@ extern void oaktrail_lvds_i2c_init(struct drm_encoder *encoder);
>  extern void mid_dsi_init(struct drm_device *dev,
>  		    struct psb_intel_mode_device *mode_dev, int dsi_num);
>  
> -extern struct drm_encoder *gma_best_encoder(struct drm_connector *connector);
> +extern struct drm_encoder *gma_best_encoder(struct drm_connector *connector,
> +					    struct drm_crtc *crtc);
>  extern void gma_connector_attach_encoder(struct gma_connector *connector,
>  					 struct gma_encoder *encoder);
>  
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
> index d2f4749ebf8d..89a0104f9855 100644
> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
> @@ -34,7 +34,8 @@ static enum drm_mode_status hibmc_connector_mode_valid(struct drm_connector *con
>  }
>  
>  static struct drm_encoder *
> -hibmc_connector_best_encoder(struct drm_connector *connector)
> +hibmc_connector_best_encoder(struct drm_connector *connector,
> +			     struct drm_crtc *crtc)
>  {
>  	return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
>  }
> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
> index 0038c976536a..422347d977b4 100644
> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
> @@ -1267,7 +1267,8 @@ static enum drm_mode_status tda998x_connector_mode_valid(struct drm_connector *c
>  }
>  
>  static struct drm_encoder *
> -tda998x_connector_best_encoder(struct drm_connector *connector)
> +tda998x_connector_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> index 5890500a3a8b..d9119d516579 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> @@ -403,20 +403,23 @@ static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *c
>  	return &intel_dp->mst_encoders[crtc->pipe]->base.base;
>  }
>  
> -static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector)
> +static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector,
> +						  struct drm_crtc *_crtc)
>  {
>  	struct intel_connector *intel_connector = to_intel_connector(connector);
>  	struct intel_dp *intel_dp = intel_connector->mst_port;
> +	struct intel_crtc *crtc = to_intel_crtc(_crtc);
> +
>  	if (!intel_dp)
>  		return NULL;
> -	return &intel_dp->mst_encoders[0]->base.base;
> +	return &intel_dp->mst_encoders[crtc->pipe]->base.base;
>  }
>  
>  static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = {
>  	.get_modes = intel_dp_mst_get_modes,
>  	.mode_valid = intel_dp_mst_mode_valid,
>  	.atomic_best_encoder = intel_mst_atomic_best_encoder,
> -	.best_encoder = intel_mst_best_encoder,
> +	.best_encoder = intel_mst_best_encoder, /* only for fb_helper */
>  	.atomic_check = intel_dp_mst_atomic_check,
>  };
>  
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index 56dd7a9a8e25..f1523cccc090 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -163,8 +163,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
>  	return num_modes;
>  }
>  
> -static struct drm_encoder *imx_ldb_connector_best_encoder(
> -		struct drm_connector *connector)
> +static struct drm_encoder *
> +imx_ldb_connector_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
>  
> diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
> index bc27c2699464..71f49ac835ec 100644
> --- a/drivers/gpu/drm/imx/imx-tve.c
> +++ b/drivers/gpu/drm/imx/imx-tve.c
> @@ -265,8 +265,9 @@ static int imx_tve_connector_mode_valid(struct drm_connector *connector,
>  	return MODE_BAD;
>  }
>  
> -static struct drm_encoder *imx_tve_connector_best_encoder(
> -		struct drm_connector *connector)
> +static struct drm_encoder *
> +imx_tve_connector_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	struct imx_tve *tve = con_to_tve(connector);
>  
> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> index aedecda9728a..438f95dee73e 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -89,8 +89,9 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
>  	return num_modes;
>  }
>  
> -static struct drm_encoder *imx_pd_connector_best_encoder(
> -		struct drm_connector *connector)
> +static struct drm_encoder *
> +imx_pd_connector_best_encoder(struct drm_connector *connector,
> +			      struct drm_crtc *crtc)
>  {
>  	struct imx_parallel_display *imxpd = con_to_imxpd(connector);
>  
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 59a11026dceb..c0578779fb19 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1253,7 +1253,8 @@ static int mtk_hdmi_conn_mode_valid(struct drm_connector *conn,
>  	return drm_mode_validate_size(mode, 0x1fff, 0x1fff);
>  }
>  
> -static struct drm_encoder *mtk_hdmi_conn_best_enc(struct drm_connector *conn)
> +static struct drm_encoder *mtk_hdmi_conn_best_enc(struct drm_connector *conn,
> +						  struct drm_crtc *crtc)
>  {
>  	struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
>  
> diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
> index 8918539a19aa..4059f04030ee 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_mode.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
> @@ -1664,8 +1664,9 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector,
>  	return MODE_OK;
>  }
>  
> -static struct drm_encoder *mga_connector_best_encoder(struct drm_connector
> -						  *connector)
> +static struct drm_encoder *
> +mga_connector_best_encoder(struct drm_connector *connector,
> +			   struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	/* pick the encoder ids */
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index 4cb1cb68878b..8cbede64819e 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -426,7 +426,8 @@ static int dsi_mgr_connector_mode_valid(struct drm_connector *connector,
>  }
>  
>  static struct drm_encoder *
> -dsi_mgr_connector_best_encoder(struct drm_connector *connector)
> +dsi_mgr_connector_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	int id = dsi_mgr_connector_get_id(connector);
>  	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
> diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> index b83465ae7c1b..a9bacb0a1e16 100644
> --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> @@ -826,7 +826,8 @@ nv50_mstc_atomic_best_encoder(struct drm_connector *connector,
>  }
>  
>  static struct drm_encoder *
> -nv50_mstc_best_encoder(struct drm_connector *connector)
> +nv50_mstc_best_encoder(struct drm_connector *connector,
> +		       struct drm_crtc *crtc)
>  {
>  	struct nv50_mstc *mstc = nv50_mstc(connector);
>  	if (mstc->port) {
> diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
> index 7b557c354307..ee4bf532b932 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_connector.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
> @@ -1063,7 +1063,8 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
>  }
>  
>  static struct drm_encoder *
> -nouveau_connector_best_encoder(struct drm_connector *connector)
> +nouveau_connector_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	struct nouveau_connector *nv_connector = nouveau_connector(connector);
>  
> diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> index 768207fbbae3..fa5c84f35531 100644
> --- a/drivers/gpu/drm/qxl/qxl_display.c
> +++ b/drivers/gpu/drm/qxl/qxl_display.c
> @@ -978,7 +978,8 @@ static enum drm_mode_status qxl_conn_mode_valid(struct drm_connector *connector,
>  	return MODE_BAD;
>  }
>  
> -static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector)
> +static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector,
> +					    struct drm_crtc *crtc)
>  {
>  	struct qxl_output *qxl_output =
>  		drm_connector_to_qxl_output(connector);
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index 2aea2bdff99b..8bf7298dccb3 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -158,7 +158,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
>  		else if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
>  			const struct drm_connector_helper_funcs *connector_funcs =
>  				connector->helper_private;
> -			struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
> +			struct drm_encoder *encoder = connector_funcs->best_encoder(connector, NULL);
>  			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
>  			struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
>  
> @@ -250,7 +250,7 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
>  	bool connected;
>  	int i;
>  
> -	best_encoder = connector_funcs->best_encoder(connector);
> +	best_encoder = connector_funcs->best_encoder(connector, NULL);
>  
>  	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
>  		if (connector->encoder_ids[i] == 0)
> @@ -391,7 +391,8 @@ static int radeon_ddc_get_modes(struct drm_connector *connector)
>  	return 0;
>  }
>  
> -static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
> +static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector,
> +						      struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	/* pick the encoder ids */
> @@ -402,7 +403,7 @@ static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *conn
>  
>  static void radeon_get_native_mode(struct drm_connector *connector)
>  {
> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  	struct radeon_encoder *radeon_encoder;
>  
>  	if (encoder == NULL)
> @@ -728,7 +729,7 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct
>  			radeon_encoder = to_radeon_encoder(connector->encoder);
>  		else {
>  			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
> -			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
> +			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
>  		}
>  
>  		switch (val) {
> @@ -755,7 +756,7 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct
>  			radeon_encoder = to_radeon_encoder(connector->encoder);
>  		else {
>  			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
> -			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
> +			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
>  		}
>  
>  		if (radeon_encoder->output_csc == val)
> @@ -824,7 +825,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
>  	radeon_connector_get_edid(connector);
>  	ret = radeon_ddc_get_modes(connector);
>  	if (ret > 0) {
> -		encoder = radeon_best_single_encoder(connector);
> +		encoder = radeon_best_single_encoder(connector, NULL);
>  		if (encoder) {
>  			radeon_fixup_lvds_native_mode(encoder, connector);
>  			/* add scaled modes */
> @@ -833,7 +834,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
>  		return ret;
>  	}
>  
> -	encoder = radeon_best_single_encoder(connector);
> +	encoder = radeon_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		return 0;
>  
> @@ -855,7 +856,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
>  static enum drm_mode_status radeon_lvds_mode_valid(struct drm_connector *connector,
>  				  struct drm_display_mode *mode)
>  {
> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  
>  	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>  		return MODE_PANEL;
> @@ -888,7 +889,7 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
>  	struct drm_device *dev = connector->dev;
>  	struct radeon_device *rdev = dev->dev_private;
>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  	enum drm_connector_status ret = connector_status_disconnected;
>  	int r;
>  
> @@ -965,7 +966,7 @@ static int radeon_lvds_set_property(struct drm_connector *connector,
>  		radeon_encoder = to_radeon_encoder(connector->encoder);
>  	else {
>  		const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
> -		radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
> +		radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
>  	}
>  
>  	switch (value) {
> @@ -1044,7 +1045,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
>  			return connector_status_disconnected;
>  	}
>  
> -	encoder = radeon_best_single_encoder(connector);
> +	encoder = radeon_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		ret = connector_status_disconnected;
>  
> @@ -1139,7 +1140,7 @@ static int radeon_tv_get_modes(struct drm_connector *connector)
>  	struct drm_display_mode *tv_mode;
>  	struct drm_encoder *encoder;
>  
> -	encoder = radeon_best_single_encoder(connector);
> +	encoder = radeon_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		return 0;
>  
> @@ -1182,7 +1183,7 @@ radeon_tv_detect(struct drm_connector *connector, bool force)
>  			return connector_status_disconnected;
>  	}
>  
> -	encoder = radeon_best_single_encoder(connector);
> +	encoder = radeon_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		ret = connector_status_disconnected;
>  	else {
> @@ -1439,7 +1440,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>  		const struct drm_connector_helper_funcs *connector_funcs =
>  			connector->helper_private;
>  
> -		encoder = connector_funcs->best_encoder(connector);
> +		encoder = connector_funcs->best_encoder(connector, NULL);
>  		if (encoder && (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)) {
>  			radeon_connector_get_edid(connector);
>  			radeon_audio_detect(connector, encoder, ret);
> @@ -1456,7 +1457,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>  }
>  
>  /* okay need to be smart in here about which encoder to pick */
> -static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
> +static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector,
> +					      struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
> @@ -1556,7 +1558,7 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
>  {
>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>  	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  	int ret;
>  
>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
> @@ -1695,7 +1697,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>  	enum drm_connector_status ret = connector_status_disconnected;
>  	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  	int r;
>  
>  	if (radeon_dig_connector->is_mst)
> @@ -1812,7 +1814,7 @@ static enum drm_mode_status radeon_dp_mode_valid(struct drm_connector *connector
>  
>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
>  	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
> -		struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +		struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  
>  		if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>  			return MODE_PANEL;
> diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
> index cd8a3ee16649..fd5a0dae0e1f 100644
> --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
> +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
> @@ -224,7 +224,8 @@ radeon_dp_mst_mode_valid(struct drm_connector *connector,
>  }
>  
>  static struct
> -drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector)
> +drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector,
> +				     struct drm_crtc *crtc)
>  {
>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>  
> @@ -613,7 +614,7 @@ radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector)
>  	struct radeon_encoder_mst *mst_enc;
>  	struct drm_encoder *encoder;
>  	const struct drm_connector_helper_funcs *connector_funcs = connector->base.helper_private;
> -	struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base);
> +	struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base, NULL);
>  
>  	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
>  	radeon_encoder = kzalloc(sizeof(*radeon_encoder), GFP_KERNEL);
> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
> index e7738939a86d..cdc991d5c28e 100644
> --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
> +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
> @@ -668,7 +668,8 @@ static int shmob_drm_connector_get_modes(struct drm_connector *connector)
>  }
>  
>  static struct drm_encoder *
> -shmob_drm_connector_best_encoder(struct drm_connector *connector)
> +shmob_drm_connector_best_encoder(struct drm_connector *connector,
> +				 struct drm_crtc *crtc)
>  {
>  	struct shmob_drm_connector *scon = to_shmob_connector(connector);
>  
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
> index d616d64a6725..197962eca1af 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
> @@ -178,8 +178,9 @@ static int panel_connector_mode_valid(struct drm_connector *connector,
>  	return tilcdc_crtc_mode_valid(priv->crtc, mode);
>  }
>  
> -static struct drm_encoder *panel_connector_best_encoder(
> -		struct drm_connector *connector)
> +static struct drm_encoder *
> +panel_connector_best_encoder(struct drm_connector *connector,
> +			     struct drm_crtc *crtc)
>  {
>  	struct panel_connector *panel_connector = to_panel_connector(connector);
>  	return panel_connector->encoder;
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
> index c45cabb38db0..0ef8221c5334 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
> @@ -191,8 +191,9 @@ static int tfp410_connector_mode_valid(struct drm_connector *connector,
>  	return tilcdc_crtc_mode_valid(priv->crtc, mode);
>  }
>  
> -static struct drm_encoder *tfp410_connector_best_encoder(
> -		struct drm_connector *connector)
> +static struct drm_encoder *
> +tfp410_connector_best_encoder(struct drm_connector *connector,
> +			      struct drm_crtc *crtc)
>  {
>  	struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
>  	return tfp410_connector->encoder;
> diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
> index 09dc585aa46f..803ae6515892 100644
> --- a/drivers/gpu/drm/udl/udl_connector.c
> +++ b/drivers/gpu/drm/udl/udl_connector.c
> @@ -145,7 +145,8 @@ udl_detect(struct drm_connector *connector, bool force)
>  }
>  
>  static struct drm_encoder*
> -udl_best_single_encoder(struct drm_connector *connector)
> +udl_best_single_encoder(struct drm_connector *connector,
> +			struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	return drm_encoder_find(connector->dev, NULL, enc_id);
> diff --git a/drivers/staging/vboxvideo/vbox_mode.c b/drivers/staging/vboxvideo/vbox_mode.c
> index b265fe924556..bf0e93705e1c 100644
> --- a/drivers/staging/vboxvideo/vbox_mode.c
> +++ b/drivers/staging/vboxvideo/vbox_mode.c
> @@ -370,8 +370,9 @@ static void vbox_encoder_destroy(struct drm_encoder *encoder)
>  	kfree(encoder);
>  }
>  
> -static struct drm_encoder *vbox_best_single_encoder(struct drm_connector
> -						    *connector)
> +static struct drm_encoder *
> +vbox_best_single_encoder(struct drm_connector *connector,
> +			 struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  
> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
> index 26aaba58d6ce..e0f00d43ed63 100644
> --- a/include/drm/drm_atomic_helper.h
> +++ b/include/drm/drm_atomic_helper.h
> @@ -143,7 +143,8 @@ int drm_atomic_helper_page_flip_target(
>  				uint32_t target,
>  				struct drm_modeset_acquire_ctx *ctx);
>  struct drm_encoder *
> -drm_atomic_helper_best_encoder(struct drm_connector *connector);
> +drm_atomic_helper_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc);
>  
>  /* default implementations for state handling */
>  void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index 35e2a3a79fc5..a9b3a2c50877 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -885,7 +885,8 @@ struct drm_connector_helper_funcs {
>  	/**
>  	 * @best_encoder:
>  	 *
> -	 * This function should select the best encoder for the given connector.
> +	 * This function should select the best encoder for the given connector
> +	 * and crtc. For some driver internal use crtc may be NULL.
>  	 *
>  	 * This function is used by both the atomic helpers (in the
>  	 * drm_atomic_helper_check_modeset() function) and in the legacy CRTC
> @@ -911,7 +912,8 @@ struct drm_connector_helper_funcs {
>  	 * will ensure that encoders aren't used twice, drivers should not check
>  	 * for this.
>  	 */
> -	struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
> +	struct drm_encoder *(*best_encoder)(struct drm_connector *connector,
> +					    struct drm_crtc *crtc);
>  
>  	/**
>  	 * @atomic_best_encoder:
>
Daniel Vetter June 26, 2018, 3:23 p.m. UTC | #2
On Fri, Jun 15, 2018 at 10:52:21PM +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> To pick the correct MST encoder i915 wants to know which crtc is going
> to be feeding us. To that end let's pass the crtc to the .best_encoder()
> hook. The atomic variant already knows the crtc via the connector state,
> but the non-atomic hooks is still being used by the fb_helper even on
> atomic drivers.

Can't we instead fix the fb helpers to use atomic_best_encoder? Or just
drop that code, userspace doesn't really know any better either and just
needs to figure this out without the help of ->best_encoder, so it should
be possible.
-Daniel

> 
> This allows us to fix up the possible_crtcs bitmask for the i915 MST
> encoders. We have one encoder for each crtc+port combination, and thus
> we have to know both the connector and the crtc to pick the right one.
> This has only worked so far because every MST encoder lied in its
> possible_crtcs bitmask that they can be driven by any crtc.
> 
> I took the easy way out and passed NULL as the crtc for all the driver
> internal uses of .best_encoder() in the amdgpu/radeon drivers. None of
> the other drivers have such internal uses. The other callers
> (crtc_helper, atomic_helper, fb_helper) will pass in the proper crtc.
> but no one besides i915 will currently look at it.
> 
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: "Christian König" <christian.koenig@amd.com>
> Cc: "David (ChunMing) Zhou" <David1.Zhou@amd.com>
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: amd-gfx@lists.freedesktop.org
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c     | 33 +++++++++--------
>  drivers/gpu/drm/amd/amdgpu/dce_virtual.c           |  3 +-
>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |  7 ++--
>  .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c    |  5 +--
>  drivers/gpu/drm/ast/ast_mode.c                     |  3 +-
>  drivers/gpu/drm/bochs/bochs_kms.c                  |  3 +-
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  3 +-
>  drivers/gpu/drm/bridge/tc358767.c                  |  3 +-
>  drivers/gpu/drm/cirrus/cirrus_mode.c               |  5 +--
>  drivers/gpu/drm/drm_atomic_helper.c                | 16 ++++++---
>  drivers/gpu/drm/drm_crtc_helper.c                  |  3 +-
>  drivers/gpu/drm/drm_fb_helper.c                    | 41 ++++++++++++----------
>  drivers/gpu/drm/gma500/gma_display.c               |  3 +-
>  drivers/gpu/drm/gma500/mdfld_dsi_output.c          |  5 +--
>  drivers/gpu/drm/gma500/psb_intel_drv.h             |  3 +-
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c   |  3 +-
>  drivers/gpu/drm/i2c/tda998x_drv.c                  |  3 +-
>  drivers/gpu/drm/i915/intel_dp_mst.c                |  9 +++--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  5 +--
>  drivers/gpu/drm/imx/imx-tve.c                      |  5 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  5 +--
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                |  3 +-
>  drivers/gpu/drm/mgag200/mgag200_mode.c             |  5 +--
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              |  3 +-
>  drivers/gpu/drm/nouveau/dispnv50/disp.c            |  3 +-
>  drivers/gpu/drm/nouveau/nouveau_connector.c        |  3 +-
>  drivers/gpu/drm/qxl/qxl_display.c                  |  3 +-
>  drivers/gpu/drm/radeon/radeon_connectors.c         | 40 +++++++++++----------
>  drivers/gpu/drm/radeon/radeon_dp_mst.c             |  5 +--
>  drivers/gpu/drm/shmobile/shmob_drm_crtc.c          |  3 +-
>  drivers/gpu/drm/tilcdc/tilcdc_panel.c              |  5 +--
>  drivers/gpu/drm/tilcdc/tilcdc_tfp410.c             |  5 +--
>  drivers/gpu/drm/udl/udl_connector.c                |  3 +-
>  drivers/staging/vboxvideo/vbox_mode.c              |  5 +--
>  include/drm/drm_atomic_helper.h                    |  3 +-
>  include/drm/drm_modeset_helper_vtables.h           |  6 ++--
>  36 files changed, 155 insertions(+), 106 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
> index 8e66851eb427..3dfa50ec2589 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
> @@ -135,7 +135,8 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
>  		else {
>  			const struct drm_connector_helper_funcs *connector_funcs =
>  				connector->helper_private;
> -			struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
> +			struct drm_encoder *encoder = connector_funcs->best_encoder(connector,
> +										    NULL);
>  			struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
>  			struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
>  
> @@ -218,7 +219,7 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector,
>  	bool connected;
>  	int i;
>  
> -	best_encoder = connector_funcs->best_encoder(connector);
> +	best_encoder = connector_funcs->best_encoder(connector, NULL);
>  
>  	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
>  		if (connector->encoder_ids[i] == 0)
> @@ -358,7 +359,8 @@ static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
>  }
>  
>  static struct drm_encoder *
> -amdgpu_connector_best_single_encoder(struct drm_connector *connector)
> +amdgpu_connector_best_single_encoder(struct drm_connector *connector,
> +				     struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  
> @@ -370,7 +372,7 @@ amdgpu_connector_best_single_encoder(struct drm_connector *connector)
>  
>  static void amdgpu_get_native_mode(struct drm_connector *connector)
>  {
> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	struct amdgpu_encoder *amdgpu_encoder;
>  
>  	if (encoder == NULL)
> @@ -593,7 +595,7 @@ static int amdgpu_connector_set_property(struct drm_connector *connector,
>  			amdgpu_encoder = to_amdgpu_encoder(connector->encoder);
>  		} else {
>  			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
> -			amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector));
> +			amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector, NULL));
>  		}
>  
>  		switch (val) {
> @@ -663,7 +665,7 @@ static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
>  	amdgpu_connector_get_edid(connector);
>  	ret = amdgpu_connector_ddc_get_modes(connector);
>  	if (ret > 0) {
> -		encoder = amdgpu_connector_best_single_encoder(connector);
> +		encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  		if (encoder) {
>  			amdgpu_connector_fixup_lcd_native_mode(encoder, connector);
>  			/* add scaled modes */
> @@ -672,7 +674,7 @@ static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
>  		return ret;
>  	}
>  
> -	encoder = amdgpu_connector_best_single_encoder(connector);
> +	encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		return 0;
>  
> @@ -694,7 +696,7 @@ static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
>  static enum drm_mode_status amdgpu_connector_lvds_mode_valid(struct drm_connector *connector,
>  					     struct drm_display_mode *mode)
>  {
> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  
>  	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>  		return MODE_PANEL;
> @@ -725,7 +727,7 @@ static enum drm_connector_status
>  amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)
>  {
>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	enum drm_connector_status ret = connector_status_disconnected;
>  	int r;
>  
> @@ -798,7 +800,7 @@ static int amdgpu_connector_set_lcd_property(struct drm_connector *connector,
>  		amdgpu_encoder = to_amdgpu_encoder(connector->encoder);
>  	else {
>  		const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
> -		amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector));
> +		amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector, NULL));
>  	}
>  
>  	switch (value) {
> @@ -873,7 +875,7 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
>  			return connector_status_disconnected;
>  	}
>  
> -	encoder = amdgpu_connector_best_single_encoder(connector);
> +	encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		ret = connector_status_disconnected;
>  
> @@ -1130,7 +1132,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
>  
>  /* okay need to be smart in here about which encoder to pick */
>  static struct drm_encoder *
> -amdgpu_connector_dvi_encoder(struct drm_connector *connector)
> +amdgpu_connector_dvi_encoder(struct drm_connector *connector,
> +			     struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
> @@ -1224,7 +1227,7 @@ static int amdgpu_connector_dp_get_modes(struct drm_connector *connector)
>  {
>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
>  	struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv;
> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	int ret;
>  
>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
> @@ -1363,7 +1366,7 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
>  	enum drm_connector_status ret = connector_status_disconnected;
>  	struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv;
> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  	int r;
>  
>  	if (!drm_kms_helper_is_poll_worker()) {
> @@ -1458,7 +1461,7 @@ static enum drm_mode_status amdgpu_connector_dp_mode_valid(struct drm_connector
>  
>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
>  	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
> -		struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
> +		struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>  
>  		if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>  			return MODE_PANEL;
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> index dbf2ccd0c744..b02ce39e65b7 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
> @@ -267,7 +267,8 @@ static int dce_virtual_early_init(void *handle)
>  }
>  
>  static struct drm_encoder *
> -dce_virtual_encoder(struct drm_connector *connector)
> +dce_virtual_encoder(struct drm_connector *connector,
> +		    struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	struct drm_encoder *encoder;
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 3e1c2a04d669..e56ed4e5818f 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -2758,7 +2758,8 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
>  	.atomic_get_property = amdgpu_dm_connector_atomic_get_property
>  };
>  
> -static struct drm_encoder *best_encoder(struct drm_connector *connector)
> +static struct drm_encoder *best_encoder(struct drm_connector *connector,
> +					struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	struct drm_mode_object *obj;
> @@ -3304,7 +3305,7 @@ static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
>  	struct drm_encoder *encoder;
>  	struct amdgpu_encoder *amdgpu_encoder;
>  
> -	encoder = helper->best_encoder(connector);
> +	encoder = helper->best_encoder(connector, NULL);
>  
>  	if (encoder == NULL)
>  		return;
> @@ -3438,7 +3439,7 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
>  	struct drm_encoder *encoder;
>  	struct edid *edid = amdgpu_dm_connector->edid;
>  
> -	encoder = helper->best_encoder(connector);
> +	encoder = helper->best_encoder(connector, NULL);
>  	amdgpu_dm_connector_ddc_get_modes(connector, edid);
>  	amdgpu_dm_connector_add_common_modes(encoder, connector);
>  
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> index 4304d9e408b8..4544a1401caf 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> @@ -269,7 +269,8 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
>  	return ret;
>  }
>  
> -static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector)
> +static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector,
> +					       struct drm_crtc *crtc)
>  {
>  	struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
>  
> @@ -302,7 +303,7 @@ dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector)
>  	const struct drm_connector_helper_funcs *connector_funcs =
>  		connector->base.helper_private;
>  	struct drm_encoder *enc_master =
> -		connector_funcs->best_encoder(&connector->base);
> +		connector_funcs->best_encoder(&connector->base, NULL);
>  
>  	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
>  	amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
> diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
> index 036dff8a1f33..d5899aa41d37 100644
> --- a/drivers/gpu/drm/ast/ast_mode.c
> +++ b/drivers/gpu/drm/ast/ast_mode.c
> @@ -709,7 +709,8 @@ static void ast_encoder_destroy(struct drm_encoder *encoder)
>  }
>  
>  
> -static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector)
> +static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector,
> +						   struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	/* pick the encoder ids */
> diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
> index 233980a78591..dc80a238feef 100644
> --- a/drivers/gpu/drm/bochs/bochs_kms.c
> +++ b/drivers/gpu/drm/bochs/bochs_kms.c
> @@ -208,7 +208,8 @@ static enum drm_mode_status bochs_connector_mode_valid(struct drm_connector *con
>  }
>  
>  static struct drm_encoder *
> -bochs_connector_best_encoder(struct drm_connector *connector)
> +bochs_connector_best_encoder(struct drm_connector *connector,
> +			     struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	/* pick the encoder ids */
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 2bcbfadb6ac5..0706471c8c63 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1137,7 +1137,8 @@ static int analogix_dp_get_modes(struct drm_connector *connector)
>  }
>  
>  static struct drm_encoder *
> -analogix_dp_best_encoder(struct drm_connector *connector)
> +analogix_dp_best_encoder(struct drm_connector *connector,
> +			 struct drm_crtc *crtc)
>  {
>  	struct analogix_dp_device *dp = to_dp(connector);
>  
> diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
> index 0fd9cf27542c..7cd954226fe3 100644
> --- a/drivers/gpu/drm/bridge/tc358767.c
> +++ b/drivers/gpu/drm/bridge/tc358767.c
> @@ -1155,7 +1155,8 @@ static void tc_connector_set_polling(struct tc_data *tc,
>  }
>  
>  static struct drm_encoder *
> -tc_connector_best_encoder(struct drm_connector *connector)
> +tc_connector_best_encoder(struct drm_connector *connector,
> +			  struct drm_crtc *crtc)
>  {
>  	struct tc_data *tc = connector_to_tc(connector);
>  
> diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
> index b529f8c8e2a6..378ebc3f25e8 100644
> --- a/drivers/gpu/drm/cirrus/cirrus_mode.c
> +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
> @@ -451,8 +451,9 @@ static int cirrus_vga_get_modes(struct drm_connector *connector)
>  	return count;
>  }
>  
> -static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
> -						  *connector)
> +static struct drm_encoder *
> +cirrus_connector_best_encoder(struct drm_connector *connector,
> +			      struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	/* pick the encoder ids */
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index 232fa11a5e31..bd3aebbfd5b4 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -115,9 +115,11 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
>  		if (funcs->atomic_best_encoder)
>  			new_encoder = funcs->atomic_best_encoder(connector, new_conn_state);
>  		else if (funcs->best_encoder)
> -			new_encoder = funcs->best_encoder(connector);
> +			new_encoder = funcs->best_encoder(connector,
> +							  new_conn_state->crtc);
>  		else
> -			new_encoder = drm_atomic_helper_best_encoder(connector);
> +			new_encoder = drm_atomic_helper_best_encoder(connector,
> +								     new_conn_state->crtc);
>  
>  		if (new_encoder) {
>  			if (encoder_mask & (1 << drm_encoder_index(new_encoder))) {
> @@ -312,9 +314,11 @@ update_connector_routing(struct drm_atomic_state *state,
>  		new_encoder = funcs->atomic_best_encoder(connector,
>  							 new_connector_state);
>  	else if (funcs->best_encoder)
> -		new_encoder = funcs->best_encoder(connector);
> +		new_encoder = funcs->best_encoder(connector,
> +						  new_connector_state->crtc);
>  	else
> -		new_encoder = drm_atomic_helper_best_encoder(connector);
> +		new_encoder = drm_atomic_helper_best_encoder(connector,
> +							     new_connector_state->crtc);
>  
>  	if (!new_encoder) {
>  		DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n",
> @@ -3318,13 +3322,15 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
>   * drm_atomic_helper_best_encoder - Helper for
>   * 	&drm_connector_helper_funcs.best_encoder callback
>   * @connector: Connector control structure
> + * @crtc: DRM crtc
>   *
>   * This is a &drm_connector_helper_funcs.best_encoder callback helper for
>   * connectors that support exactly 1 encoder, statically determined at driver
>   * init time.
>   */
>  struct drm_encoder *
> -drm_atomic_helper_best_encoder(struct drm_connector *connector)
> +drm_atomic_helper_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	WARN_ON(connector->encoder_ids[1]);
>  	return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index 5a84c3bc915d..f9318fc11fb1 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -637,7 +637,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set,
>  		new_encoder = connector->encoder;
>  		for (ro = 0; ro < set->num_connectors; ro++) {
>  			if (set->connectors[ro] == connector) {
> -				new_encoder = connector_funcs->best_encoder(connector);
> +				new_encoder = connector_funcs->best_encoder(connector,
> +									    set->crtc);
>  				/* if we can't get an encoder for a connector
>  				   we are setting now - then fail */
>  				if (new_encoder == NULL)
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index cab14f253384..ce91ae12cccb 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -2331,9 +2331,8 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
>  	int c, o;
>  	struct drm_connector *connector;
>  	const struct drm_connector_helper_funcs *connector_funcs;
> -	struct drm_encoder *encoder;
>  	int my_score, best_score, score;
> -	struct drm_fb_helper_crtc **crtcs, *crtc;
> +	struct drm_fb_helper_crtc **crtcs;
>  	struct drm_fb_helper_connector *fb_helper_conn;
>  
>  	if (n == fb_helper->connector_count)
> @@ -2362,28 +2361,32 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
>  
>  	connector_funcs = connector->helper_private;
>  
> -	/*
> -	 * If the DRM device implements atomic hooks and ->best_encoder() is
> -	 * NULL we fallback to the default drm_atomic_helper_best_encoder()
> -	 * helper.
> -	 */
> -	if (drm_drv_uses_atomic_modeset(fb_helper->dev) &&
> -	    !connector_funcs->best_encoder)
> -		encoder = drm_atomic_helper_best_encoder(connector);
> -	else
> -		encoder = connector_funcs->best_encoder(connector);
> -
> -	if (!encoder)
> -		goto out;
> -
>  	/*
>  	 * select a crtc for this connector and then attempt to configure
>  	 * remaining connectors
>  	 */
>  	for (c = 0; c < fb_helper->crtc_count; c++) {
> -		crtc = &fb_helper->crtc_info[c];
> +		struct drm_encoder *encoder;
> +		struct drm_fb_helper_crtc *crtc = &fb_helper->crtc_info[c];
>  
> -		if ((encoder->possible_crtcs & (1 << c)) == 0)
> +		/*
> +		 * If the DRM device implements atomic hooks and ->best_encoder() is
> +		 * NULL we fallback to the default drm_atomic_helper_best_encoder()
> +		 * helper.
> +		 */
> +		if (drm_drv_uses_atomic_modeset(fb_helper->dev) &&
> +		    !connector_funcs->best_encoder)
> +			encoder = drm_atomic_helper_best_encoder(connector,
> +								 crtc->mode_set.crtc);
> +		else
> +			encoder = connector_funcs->best_encoder(connector,
> +								crtc->mode_set.crtc);
> +
> +		if (!encoder)
> +			continue;
> +
> +		if ((encoder->possible_crtcs &
> +		     drm_crtc_mask(crtc->mode_set.crtc)) == 0)
>  			continue;
>  
>  		for (o = 0; o < n; o++)
> @@ -2410,7 +2413,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
>  			       sizeof(struct drm_fb_helper_crtc *));
>  		}
>  	}
> -out:
> +
>  	kfree(crtcs);
>  	return best_score;
>  }
> diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
> index c8f071c47daf..251b64653dc8 100644
> --- a/drivers/gpu/drm/gma500/gma_display.c
> +++ b/drivers/gpu/drm/gma500/gma_display.c
> @@ -652,7 +652,8 @@ void gma_encoder_destroy(struct drm_encoder *encoder)
>  }
>  
>  /* Currently there is only a 1:1 mapping of encoders and connectors */
> -struct drm_encoder *gma_best_encoder(struct drm_connector *connector)
> +struct drm_encoder *gma_best_encoder(struct drm_connector *connector,
> +				     struct drm_crtc *crtc)
>  {
>  	struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
>  
> diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> index fe020926ea4f..9e5b059a9e5b 100644
> --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
> @@ -377,8 +377,9 @@ static enum drm_mode_status mdfld_dsi_connector_mode_valid(struct drm_connector
>  	return MODE_OK;
>  }
>  
> -static struct drm_encoder *mdfld_dsi_connector_best_encoder(
> -				struct drm_connector *connector)
> +static struct drm_encoder *
> +mdfld_dsi_connector_best_encoder(struct drm_connector *connector,
> +				 struct drm_crtc *crtc)
>  {
>  	struct mdfld_dsi_connector *dsi_connector =
>  				mdfld_dsi_connector(connector);
> diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
> index e05e5399af2d..e903525b9d30 100644
> --- a/drivers/gpu/drm/gma500/psb_intel_drv.h
> +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
> @@ -230,7 +230,8 @@ extern void oaktrail_lvds_i2c_init(struct drm_encoder *encoder);
>  extern void mid_dsi_init(struct drm_device *dev,
>  		    struct psb_intel_mode_device *mode_dev, int dsi_num);
>  
> -extern struct drm_encoder *gma_best_encoder(struct drm_connector *connector);
> +extern struct drm_encoder *gma_best_encoder(struct drm_connector *connector,
> +					    struct drm_crtc *crtc);
>  extern void gma_connector_attach_encoder(struct gma_connector *connector,
>  					 struct gma_encoder *encoder);
>  
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
> index d2f4749ebf8d..89a0104f9855 100644
> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
> @@ -34,7 +34,8 @@ static enum drm_mode_status hibmc_connector_mode_valid(struct drm_connector *con
>  }
>  
>  static struct drm_encoder *
> -hibmc_connector_best_encoder(struct drm_connector *connector)
> +hibmc_connector_best_encoder(struct drm_connector *connector,
> +			     struct drm_crtc *crtc)
>  {
>  	return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
>  }
> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
> index 0038c976536a..422347d977b4 100644
> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
> @@ -1267,7 +1267,8 @@ static enum drm_mode_status tda998x_connector_mode_valid(struct drm_connector *c
>  }
>  
>  static struct drm_encoder *
> -tda998x_connector_best_encoder(struct drm_connector *connector)
> +tda998x_connector_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> index 5890500a3a8b..d9119d516579 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> @@ -403,20 +403,23 @@ static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *c
>  	return &intel_dp->mst_encoders[crtc->pipe]->base.base;
>  }
>  
> -static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector)
> +static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector,
> +						  struct drm_crtc *_crtc)
>  {
>  	struct intel_connector *intel_connector = to_intel_connector(connector);
>  	struct intel_dp *intel_dp = intel_connector->mst_port;
> +	struct intel_crtc *crtc = to_intel_crtc(_crtc);
> +
>  	if (!intel_dp)
>  		return NULL;
> -	return &intel_dp->mst_encoders[0]->base.base;
> +	return &intel_dp->mst_encoders[crtc->pipe]->base.base;
>  }
>  
>  static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = {
>  	.get_modes = intel_dp_mst_get_modes,
>  	.mode_valid = intel_dp_mst_mode_valid,
>  	.atomic_best_encoder = intel_mst_atomic_best_encoder,
> -	.best_encoder = intel_mst_best_encoder,
> +	.best_encoder = intel_mst_best_encoder, /* only for fb_helper */
>  	.atomic_check = intel_dp_mst_atomic_check,
>  };
>  
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index 56dd7a9a8e25..f1523cccc090 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -163,8 +163,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
>  	return num_modes;
>  }
>  
> -static struct drm_encoder *imx_ldb_connector_best_encoder(
> -		struct drm_connector *connector)
> +static struct drm_encoder *
> +imx_ldb_connector_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
>  
> diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
> index bc27c2699464..71f49ac835ec 100644
> --- a/drivers/gpu/drm/imx/imx-tve.c
> +++ b/drivers/gpu/drm/imx/imx-tve.c
> @@ -265,8 +265,9 @@ static int imx_tve_connector_mode_valid(struct drm_connector *connector,
>  	return MODE_BAD;
>  }
>  
> -static struct drm_encoder *imx_tve_connector_best_encoder(
> -		struct drm_connector *connector)
> +static struct drm_encoder *
> +imx_tve_connector_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	struct imx_tve *tve = con_to_tve(connector);
>  
> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> index aedecda9728a..438f95dee73e 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -89,8 +89,9 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
>  	return num_modes;
>  }
>  
> -static struct drm_encoder *imx_pd_connector_best_encoder(
> -		struct drm_connector *connector)
> +static struct drm_encoder *
> +imx_pd_connector_best_encoder(struct drm_connector *connector,
> +			      struct drm_crtc *crtc)
>  {
>  	struct imx_parallel_display *imxpd = con_to_imxpd(connector);
>  
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 59a11026dceb..c0578779fb19 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1253,7 +1253,8 @@ static int mtk_hdmi_conn_mode_valid(struct drm_connector *conn,
>  	return drm_mode_validate_size(mode, 0x1fff, 0x1fff);
>  }
>  
> -static struct drm_encoder *mtk_hdmi_conn_best_enc(struct drm_connector *conn)
> +static struct drm_encoder *mtk_hdmi_conn_best_enc(struct drm_connector *conn,
> +						  struct drm_crtc *crtc)
>  {
>  	struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
>  
> diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
> index 8918539a19aa..4059f04030ee 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_mode.c
> +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
> @@ -1664,8 +1664,9 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector,
>  	return MODE_OK;
>  }
>  
> -static struct drm_encoder *mga_connector_best_encoder(struct drm_connector
> -						  *connector)
> +static struct drm_encoder *
> +mga_connector_best_encoder(struct drm_connector *connector,
> +			   struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	/* pick the encoder ids */
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index 4cb1cb68878b..8cbede64819e 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -426,7 +426,8 @@ static int dsi_mgr_connector_mode_valid(struct drm_connector *connector,
>  }
>  
>  static struct drm_encoder *
> -dsi_mgr_connector_best_encoder(struct drm_connector *connector)
> +dsi_mgr_connector_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	int id = dsi_mgr_connector_get_id(connector);
>  	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
> diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> index b83465ae7c1b..a9bacb0a1e16 100644
> --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
> +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
> @@ -826,7 +826,8 @@ nv50_mstc_atomic_best_encoder(struct drm_connector *connector,
>  }
>  
>  static struct drm_encoder *
> -nv50_mstc_best_encoder(struct drm_connector *connector)
> +nv50_mstc_best_encoder(struct drm_connector *connector,
> +		       struct drm_crtc *crtc)
>  {
>  	struct nv50_mstc *mstc = nv50_mstc(connector);
>  	if (mstc->port) {
> diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
> index 7b557c354307..ee4bf532b932 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_connector.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
> @@ -1063,7 +1063,8 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
>  }
>  
>  static struct drm_encoder *
> -nouveau_connector_best_encoder(struct drm_connector *connector)
> +nouveau_connector_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc)
>  {
>  	struct nouveau_connector *nv_connector = nouveau_connector(connector);
>  
> diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
> index 768207fbbae3..fa5c84f35531 100644
> --- a/drivers/gpu/drm/qxl/qxl_display.c
> +++ b/drivers/gpu/drm/qxl/qxl_display.c
> @@ -978,7 +978,8 @@ static enum drm_mode_status qxl_conn_mode_valid(struct drm_connector *connector,
>  	return MODE_BAD;
>  }
>  
> -static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector)
> +static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector,
> +					    struct drm_crtc *crtc)
>  {
>  	struct qxl_output *qxl_output =
>  		drm_connector_to_qxl_output(connector);
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index 2aea2bdff99b..8bf7298dccb3 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -158,7 +158,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
>  		else if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
>  			const struct drm_connector_helper_funcs *connector_funcs =
>  				connector->helper_private;
> -			struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
> +			struct drm_encoder *encoder = connector_funcs->best_encoder(connector, NULL);
>  			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
>  			struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
>  
> @@ -250,7 +250,7 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
>  	bool connected;
>  	int i;
>  
> -	best_encoder = connector_funcs->best_encoder(connector);
> +	best_encoder = connector_funcs->best_encoder(connector, NULL);
>  
>  	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
>  		if (connector->encoder_ids[i] == 0)
> @@ -391,7 +391,8 @@ static int radeon_ddc_get_modes(struct drm_connector *connector)
>  	return 0;
>  }
>  
> -static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
> +static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector,
> +						      struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	/* pick the encoder ids */
> @@ -402,7 +403,7 @@ static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *conn
>  
>  static void radeon_get_native_mode(struct drm_connector *connector)
>  {
> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  	struct radeon_encoder *radeon_encoder;
>  
>  	if (encoder == NULL)
> @@ -728,7 +729,7 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct
>  			radeon_encoder = to_radeon_encoder(connector->encoder);
>  		else {
>  			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
> -			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
> +			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
>  		}
>  
>  		switch (val) {
> @@ -755,7 +756,7 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct
>  			radeon_encoder = to_radeon_encoder(connector->encoder);
>  		else {
>  			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
> -			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
> +			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
>  		}
>  
>  		if (radeon_encoder->output_csc == val)
> @@ -824,7 +825,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
>  	radeon_connector_get_edid(connector);
>  	ret = radeon_ddc_get_modes(connector);
>  	if (ret > 0) {
> -		encoder = radeon_best_single_encoder(connector);
> +		encoder = radeon_best_single_encoder(connector, NULL);
>  		if (encoder) {
>  			radeon_fixup_lvds_native_mode(encoder, connector);
>  			/* add scaled modes */
> @@ -833,7 +834,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
>  		return ret;
>  	}
>  
> -	encoder = radeon_best_single_encoder(connector);
> +	encoder = radeon_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		return 0;
>  
> @@ -855,7 +856,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
>  static enum drm_mode_status radeon_lvds_mode_valid(struct drm_connector *connector,
>  				  struct drm_display_mode *mode)
>  {
> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  
>  	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>  		return MODE_PANEL;
> @@ -888,7 +889,7 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
>  	struct drm_device *dev = connector->dev;
>  	struct radeon_device *rdev = dev->dev_private;
>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  	enum drm_connector_status ret = connector_status_disconnected;
>  	int r;
>  
> @@ -965,7 +966,7 @@ static int radeon_lvds_set_property(struct drm_connector *connector,
>  		radeon_encoder = to_radeon_encoder(connector->encoder);
>  	else {
>  		const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
> -		radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
> +		radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
>  	}
>  
>  	switch (value) {
> @@ -1044,7 +1045,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
>  			return connector_status_disconnected;
>  	}
>  
> -	encoder = radeon_best_single_encoder(connector);
> +	encoder = radeon_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		ret = connector_status_disconnected;
>  
> @@ -1139,7 +1140,7 @@ static int radeon_tv_get_modes(struct drm_connector *connector)
>  	struct drm_display_mode *tv_mode;
>  	struct drm_encoder *encoder;
>  
> -	encoder = radeon_best_single_encoder(connector);
> +	encoder = radeon_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		return 0;
>  
> @@ -1182,7 +1183,7 @@ radeon_tv_detect(struct drm_connector *connector, bool force)
>  			return connector_status_disconnected;
>  	}
>  
> -	encoder = radeon_best_single_encoder(connector);
> +	encoder = radeon_best_single_encoder(connector, NULL);
>  	if (!encoder)
>  		ret = connector_status_disconnected;
>  	else {
> @@ -1439,7 +1440,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>  		const struct drm_connector_helper_funcs *connector_funcs =
>  			connector->helper_private;
>  
> -		encoder = connector_funcs->best_encoder(connector);
> +		encoder = connector_funcs->best_encoder(connector, NULL);
>  		if (encoder && (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)) {
>  			radeon_connector_get_edid(connector);
>  			radeon_audio_detect(connector, encoder, ret);
> @@ -1456,7 +1457,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>  }
>  
>  /* okay need to be smart in here about which encoder to pick */
> -static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
> +static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector,
> +					      struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
> @@ -1556,7 +1558,7 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
>  {
>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>  	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  	int ret;
>  
>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
> @@ -1695,7 +1697,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>  	enum drm_connector_status ret = connector_status_disconnected;
>  	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  	int r;
>  
>  	if (radeon_dig_connector->is_mst)
> @@ -1812,7 +1814,7 @@ static enum drm_mode_status radeon_dp_mode_valid(struct drm_connector *connector
>  
>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
>  	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
> -		struct drm_encoder *encoder = radeon_best_single_encoder(connector);
> +		struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>  
>  		if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>  			return MODE_PANEL;
> diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
> index cd8a3ee16649..fd5a0dae0e1f 100644
> --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
> +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
> @@ -224,7 +224,8 @@ radeon_dp_mst_mode_valid(struct drm_connector *connector,
>  }
>  
>  static struct
> -drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector)
> +drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector,
> +				     struct drm_crtc *crtc)
>  {
>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>  
> @@ -613,7 +614,7 @@ radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector)
>  	struct radeon_encoder_mst *mst_enc;
>  	struct drm_encoder *encoder;
>  	const struct drm_connector_helper_funcs *connector_funcs = connector->base.helper_private;
> -	struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base);
> +	struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base, NULL);
>  
>  	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
>  	radeon_encoder = kzalloc(sizeof(*radeon_encoder), GFP_KERNEL);
> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
> index e7738939a86d..cdc991d5c28e 100644
> --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
> +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
> @@ -668,7 +668,8 @@ static int shmob_drm_connector_get_modes(struct drm_connector *connector)
>  }
>  
>  static struct drm_encoder *
> -shmob_drm_connector_best_encoder(struct drm_connector *connector)
> +shmob_drm_connector_best_encoder(struct drm_connector *connector,
> +				 struct drm_crtc *crtc)
>  {
>  	struct shmob_drm_connector *scon = to_shmob_connector(connector);
>  
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
> index d616d64a6725..197962eca1af 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
> @@ -178,8 +178,9 @@ static int panel_connector_mode_valid(struct drm_connector *connector,
>  	return tilcdc_crtc_mode_valid(priv->crtc, mode);
>  }
>  
> -static struct drm_encoder *panel_connector_best_encoder(
> -		struct drm_connector *connector)
> +static struct drm_encoder *
> +panel_connector_best_encoder(struct drm_connector *connector,
> +			     struct drm_crtc *crtc)
>  {
>  	struct panel_connector *panel_connector = to_panel_connector(connector);
>  	return panel_connector->encoder;
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
> index c45cabb38db0..0ef8221c5334 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
> @@ -191,8 +191,9 @@ static int tfp410_connector_mode_valid(struct drm_connector *connector,
>  	return tilcdc_crtc_mode_valid(priv->crtc, mode);
>  }
>  
> -static struct drm_encoder *tfp410_connector_best_encoder(
> -		struct drm_connector *connector)
> +static struct drm_encoder *
> +tfp410_connector_best_encoder(struct drm_connector *connector,
> +			      struct drm_crtc *crtc)
>  {
>  	struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
>  	return tfp410_connector->encoder;
> diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
> index 09dc585aa46f..803ae6515892 100644
> --- a/drivers/gpu/drm/udl/udl_connector.c
> +++ b/drivers/gpu/drm/udl/udl_connector.c
> @@ -145,7 +145,8 @@ udl_detect(struct drm_connector *connector, bool force)
>  }
>  
>  static struct drm_encoder*
> -udl_best_single_encoder(struct drm_connector *connector)
> +udl_best_single_encoder(struct drm_connector *connector,
> +			struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  	return drm_encoder_find(connector->dev, NULL, enc_id);
> diff --git a/drivers/staging/vboxvideo/vbox_mode.c b/drivers/staging/vboxvideo/vbox_mode.c
> index b265fe924556..bf0e93705e1c 100644
> --- a/drivers/staging/vboxvideo/vbox_mode.c
> +++ b/drivers/staging/vboxvideo/vbox_mode.c
> @@ -370,8 +370,9 @@ static void vbox_encoder_destroy(struct drm_encoder *encoder)
>  	kfree(encoder);
>  }
>  
> -static struct drm_encoder *vbox_best_single_encoder(struct drm_connector
> -						    *connector)
> +static struct drm_encoder *
> +vbox_best_single_encoder(struct drm_connector *connector,
> +			 struct drm_crtc *crtc)
>  {
>  	int enc_id = connector->encoder_ids[0];
>  
> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
> index 26aaba58d6ce..e0f00d43ed63 100644
> --- a/include/drm/drm_atomic_helper.h
> +++ b/include/drm/drm_atomic_helper.h
> @@ -143,7 +143,8 @@ int drm_atomic_helper_page_flip_target(
>  				uint32_t target,
>  				struct drm_modeset_acquire_ctx *ctx);
>  struct drm_encoder *
> -drm_atomic_helper_best_encoder(struct drm_connector *connector);
> +drm_atomic_helper_best_encoder(struct drm_connector *connector,
> +			       struct drm_crtc *crtc);
>  
>  /* default implementations for state handling */
>  void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index 35e2a3a79fc5..a9b3a2c50877 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -885,7 +885,8 @@ struct drm_connector_helper_funcs {
>  	/**
>  	 * @best_encoder:
>  	 *
> -	 * This function should select the best encoder for the given connector.
> +	 * This function should select the best encoder for the given connector
> +	 * and crtc. For some driver internal use crtc may be NULL.
>  	 *
>  	 * This function is used by both the atomic helpers (in the
>  	 * drm_atomic_helper_check_modeset() function) and in the legacy CRTC
> @@ -911,7 +912,8 @@ struct drm_connector_helper_funcs {
>  	 * will ensure that encoders aren't used twice, drivers should not check
>  	 * for this.
>  	 */
> -	struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
> +	struct drm_encoder *(*best_encoder)(struct drm_connector *connector,
> +					    struct drm_crtc *crtc);
>  
>  	/**
>  	 * @atomic_best_encoder:
> -- 
> 2.16.4
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ville Syrjälä June 26, 2018, 3:38 p.m. UTC | #3
On Tue, Jun 26, 2018 at 05:23:25PM +0200, Daniel Vetter wrote:
> On Fri, Jun 15, 2018 at 10:52:21PM +0300, Ville Syrjala wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > To pick the correct MST encoder i915 wants to know which crtc is going
> > to be feeding us. To that end let's pass the crtc to the .best_encoder()
> > hook. The atomic variant already knows the crtc via the connector state,
> > but the non-atomic hooks is still being used by the fb_helper even on
> > atomic drivers.
> 
> Can't we instead fix the fb helpers to use atomic_best_encoder?

We'd need a connector state for that. Not sure we want to construct a
fake one on demand or something.

> Or just
> drop that code, userspace doesn't really know any better either and just
> needs to figure this out without the help of ->best_encoder, so it should
> be possible.

I have to admit I don't even remmber how userspace does this. OK, yeah
so each connector has a list of encoders and each encoder has the
possible_crtcs bitmask. So we should be able to just iterate through
all the encoders for the connector. Not sure there couldn't be some
some false positives if best_encoder() doesn't quite agree with the
answer for some reason.

But yeah, this does seem like a nicer option because we can then nuke
the extra .best_encoder() hook for i915 mst.

Now the question becomes whether I get to review the
connecor->encoder_ids[] assignments in every driver. I suppose they
should be mostly OK if userspace manages to work.
Harry Wentland June 26, 2018, 3:45 p.m. UTC | #4
On 2018-06-26 11:01 AM, Harry Wentland wrote:
> On 2018-06-15 03:52 PM, Ville Syrjala wrote:
>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>
>> To pick the correct MST encoder i915 wants to know which crtc is going
>> to be feeding us. To that end let's pass the crtc to the .best_encoder()
>> hook. The atomic variant already knows the crtc via the connector state,
>> but the non-atomic hooks is still being used by the fb_helper even on
>> atomic drivers.
>>
>> This allows us to fix up the possible_crtcs bitmask for the i915 MST
>> encoders. We have one encoder for each crtc+port combination, and thus
>> we have to know both the connector and the crtc to pick the right one.
>> This has only worked so far because every MST encoder lied in its
>> possible_crtcs bitmask that they can be driven by any crtc.
>>
>> I took the easy way out and passed NULL as the crtc for all the driver
>> internal uses of .best_encoder() in the amdgpu/radeon drivers. None of
>> the other drivers have such internal uses. The other callers
>> (crtc_helper, atomic_helper, fb_helper) will pass in the proper crtc.
>> but no one besides i915 will currently look at it.
>>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: "Christian König" <christian.koenig@amd.com>
>> Cc: "David (ChunMing) Zhou" <David1.Zhou@amd.com>
>> Cc: Harry Wentland <harry.wentland@amd.com>
>> Cc: amd-gfx@lists.freedesktop.org
>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> amdgpu parts are
> Acked-by: Harry Wentland <harry.wentland@amd.com>
> 

Upgrading after proper review of the entire patch

Reviewed-by: Harry Wentland <harry.wentland@amd.com>

Harry

> Harry
> 
>> ---
>>  drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c     | 33 +++++++++--------
>>  drivers/gpu/drm/amd/amdgpu/dce_virtual.c           |  3 +-
>>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |  7 ++--
>>  .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c    |  5 +--
>>  drivers/gpu/drm/ast/ast_mode.c                     |  3 +-
>>  drivers/gpu/drm/bochs/bochs_kms.c                  |  3 +-
>>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  3 +-
>>  drivers/gpu/drm/bridge/tc358767.c                  |  3 +-
>>  drivers/gpu/drm/cirrus/cirrus_mode.c               |  5 +--
>>  drivers/gpu/drm/drm_atomic_helper.c                | 16 ++++++---
>>  drivers/gpu/drm/drm_crtc_helper.c                  |  3 +-
>>  drivers/gpu/drm/drm_fb_helper.c                    | 41 ++++++++++++----------
>>  drivers/gpu/drm/gma500/gma_display.c               |  3 +-
>>  drivers/gpu/drm/gma500/mdfld_dsi_output.c          |  5 +--
>>  drivers/gpu/drm/gma500/psb_intel_drv.h             |  3 +-
>>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c   |  3 +-
>>  drivers/gpu/drm/i2c/tda998x_drv.c                  |  3 +-
>>  drivers/gpu/drm/i915/intel_dp_mst.c                |  9 +++--
>>  drivers/gpu/drm/imx/imx-ldb.c                      |  5 +--
>>  drivers/gpu/drm/imx/imx-tve.c                      |  5 +--
>>  drivers/gpu/drm/imx/parallel-display.c             |  5 +--
>>  drivers/gpu/drm/mediatek/mtk_hdmi.c                |  3 +-
>>  drivers/gpu/drm/mgag200/mgag200_mode.c             |  5 +--
>>  drivers/gpu/drm/msm/dsi/dsi_manager.c              |  3 +-
>>  drivers/gpu/drm/nouveau/dispnv50/disp.c            |  3 +-
>>  drivers/gpu/drm/nouveau/nouveau_connector.c        |  3 +-
>>  drivers/gpu/drm/qxl/qxl_display.c                  |  3 +-
>>  drivers/gpu/drm/radeon/radeon_connectors.c         | 40 +++++++++++----------
>>  drivers/gpu/drm/radeon/radeon_dp_mst.c             |  5 +--
>>  drivers/gpu/drm/shmobile/shmob_drm_crtc.c          |  3 +-
>>  drivers/gpu/drm/tilcdc/tilcdc_panel.c              |  5 +--
>>  drivers/gpu/drm/tilcdc/tilcdc_tfp410.c             |  5 +--
>>  drivers/gpu/drm/udl/udl_connector.c                |  3 +-
>>  drivers/staging/vboxvideo/vbox_mode.c              |  5 +--
>>  include/drm/drm_atomic_helper.h                    |  3 +-
>>  include/drm/drm_modeset_helper_vtables.h           |  6 ++--
>>  36 files changed, 155 insertions(+), 106 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
>> index 8e66851eb427..3dfa50ec2589 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
>> @@ -135,7 +135,8 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
>>  		else {
>>  			const struct drm_connector_helper_funcs *connector_funcs =
>>  				connector->helper_private;
>> -			struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
>> +			struct drm_encoder *encoder = connector_funcs->best_encoder(connector,
>> +										    NULL);
>>  			struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
>>  			struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
>>  
>> @@ -218,7 +219,7 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector,
>>  	bool connected;
>>  	int i;
>>  
>> -	best_encoder = connector_funcs->best_encoder(connector);
>> +	best_encoder = connector_funcs->best_encoder(connector, NULL);
>>  
>>  	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
>>  		if (connector->encoder_ids[i] == 0)
>> @@ -358,7 +359,8 @@ static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
>>  }
>>  
>>  static struct drm_encoder *
>> -amdgpu_connector_best_single_encoder(struct drm_connector *connector)
>> +amdgpu_connector_best_single_encoder(struct drm_connector *connector,
>> +				     struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  
>> @@ -370,7 +372,7 @@ amdgpu_connector_best_single_encoder(struct drm_connector *connector)
>>  
>>  static void amdgpu_get_native_mode(struct drm_connector *connector)
>>  {
>> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
>> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>>  	struct amdgpu_encoder *amdgpu_encoder;
>>  
>>  	if (encoder == NULL)
>> @@ -593,7 +595,7 @@ static int amdgpu_connector_set_property(struct drm_connector *connector,
>>  			amdgpu_encoder = to_amdgpu_encoder(connector->encoder);
>>  		} else {
>>  			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
>> -			amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector));
>> +			amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector, NULL));
>>  		}
>>  
>>  		switch (val) {
>> @@ -663,7 +665,7 @@ static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
>>  	amdgpu_connector_get_edid(connector);
>>  	ret = amdgpu_connector_ddc_get_modes(connector);
>>  	if (ret > 0) {
>> -		encoder = amdgpu_connector_best_single_encoder(connector);
>> +		encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>>  		if (encoder) {
>>  			amdgpu_connector_fixup_lcd_native_mode(encoder, connector);
>>  			/* add scaled modes */
>> @@ -672,7 +674,7 @@ static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
>>  		return ret;
>>  	}
>>  
>> -	encoder = amdgpu_connector_best_single_encoder(connector);
>> +	encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>>  	if (!encoder)
>>  		return 0;
>>  
>> @@ -694,7 +696,7 @@ static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
>>  static enum drm_mode_status amdgpu_connector_lvds_mode_valid(struct drm_connector *connector,
>>  					     struct drm_display_mode *mode)
>>  {
>> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
>> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>>  
>>  	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>>  		return MODE_PANEL;
>> @@ -725,7 +727,7 @@ static enum drm_connector_status
>>  amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)
>>  {
>>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
>> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
>> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>>  	enum drm_connector_status ret = connector_status_disconnected;
>>  	int r;
>>  
>> @@ -798,7 +800,7 @@ static int amdgpu_connector_set_lcd_property(struct drm_connector *connector,
>>  		amdgpu_encoder = to_amdgpu_encoder(connector->encoder);
>>  	else {
>>  		const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
>> -		amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector));
>> +		amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector, NULL));
>>  	}
>>  
>>  	switch (value) {
>> @@ -873,7 +875,7 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
>>  			return connector_status_disconnected;
>>  	}
>>  
>> -	encoder = amdgpu_connector_best_single_encoder(connector);
>> +	encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>>  	if (!encoder)
>>  		ret = connector_status_disconnected;
>>  
>> @@ -1130,7 +1132,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
>>  
>>  /* okay need to be smart in here about which encoder to pick */
>>  static struct drm_encoder *
>> -amdgpu_connector_dvi_encoder(struct drm_connector *connector)
>> +amdgpu_connector_dvi_encoder(struct drm_connector *connector,
>> +			     struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
>> @@ -1224,7 +1227,7 @@ static int amdgpu_connector_dp_get_modes(struct drm_connector *connector)
>>  {
>>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
>>  	struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv;
>> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
>> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>>  	int ret;
>>  
>>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
>> @@ -1363,7 +1366,7 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
>>  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
>>  	enum drm_connector_status ret = connector_status_disconnected;
>>  	struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv;
>> -	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
>> +	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>>  	int r;
>>  
>>  	if (!drm_kms_helper_is_poll_worker()) {
>> @@ -1458,7 +1461,7 @@ static enum drm_mode_status amdgpu_connector_dp_mode_valid(struct drm_connector
>>  
>>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
>>  	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
>> -		struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
>> +		struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
>>  
>>  		if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>>  			return MODE_PANEL;
>> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
>> index dbf2ccd0c744..b02ce39e65b7 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
>> @@ -267,7 +267,8 @@ static int dce_virtual_early_init(void *handle)
>>  }
>>  
>>  static struct drm_encoder *
>> -dce_virtual_encoder(struct drm_connector *connector)
>> +dce_virtual_encoder(struct drm_connector *connector,
>> +		    struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  	struct drm_encoder *encoder;
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> index 3e1c2a04d669..e56ed4e5818f 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> @@ -2758,7 +2758,8 @@ static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
>>  	.atomic_get_property = amdgpu_dm_connector_atomic_get_property
>>  };
>>  
>> -static struct drm_encoder *best_encoder(struct drm_connector *connector)
>> +static struct drm_encoder *best_encoder(struct drm_connector *connector,
>> +					struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  	struct drm_mode_object *obj;
>> @@ -3304,7 +3305,7 @@ static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
>>  	struct drm_encoder *encoder;
>>  	struct amdgpu_encoder *amdgpu_encoder;
>>  
>> -	encoder = helper->best_encoder(connector);
>> +	encoder = helper->best_encoder(connector, NULL);
>>  
>>  	if (encoder == NULL)
>>  		return;
>> @@ -3438,7 +3439,7 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
>>  	struct drm_encoder *encoder;
>>  	struct edid *edid = amdgpu_dm_connector->edid;
>>  
>> -	encoder = helper->best_encoder(connector);
>> +	encoder = helper->best_encoder(connector, NULL);
>>  	amdgpu_dm_connector_ddc_get_modes(connector, edid);
>>  	amdgpu_dm_connector_add_common_modes(encoder, connector);
>>  
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
>> index 4304d9e408b8..4544a1401caf 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
>> @@ -269,7 +269,8 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
>>  	return ret;
>>  }
>>  
>> -static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector)
>> +static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector,
>> +					       struct drm_crtc *crtc)
>>  {
>>  	struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
>>  
>> @@ -302,7 +303,7 @@ dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector)
>>  	const struct drm_connector_helper_funcs *connector_funcs =
>>  		connector->base.helper_private;
>>  	struct drm_encoder *enc_master =
>> -		connector_funcs->best_encoder(&connector->base);
>> +		connector_funcs->best_encoder(&connector->base, NULL);
>>  
>>  	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
>>  	amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
>> diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
>> index 036dff8a1f33..d5899aa41d37 100644
>> --- a/drivers/gpu/drm/ast/ast_mode.c
>> +++ b/drivers/gpu/drm/ast/ast_mode.c
>> @@ -709,7 +709,8 @@ static void ast_encoder_destroy(struct drm_encoder *encoder)
>>  }
>>  
>>  
>> -static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector)
>> +static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector,
>> +						   struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  	/* pick the encoder ids */
>> diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
>> index 233980a78591..dc80a238feef 100644
>> --- a/drivers/gpu/drm/bochs/bochs_kms.c
>> +++ b/drivers/gpu/drm/bochs/bochs_kms.c
>> @@ -208,7 +208,8 @@ static enum drm_mode_status bochs_connector_mode_valid(struct drm_connector *con
>>  }
>>  
>>  static struct drm_encoder *
>> -bochs_connector_best_encoder(struct drm_connector *connector)
>> +bochs_connector_best_encoder(struct drm_connector *connector,
>> +			     struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  	/* pick the encoder ids */
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index 2bcbfadb6ac5..0706471c8c63 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -1137,7 +1137,8 @@ static int analogix_dp_get_modes(struct drm_connector *connector)
>>  }
>>  
>>  static struct drm_encoder *
>> -analogix_dp_best_encoder(struct drm_connector *connector)
>> +analogix_dp_best_encoder(struct drm_connector *connector,
>> +			 struct drm_crtc *crtc)
>>  {
>>  	struct analogix_dp_device *dp = to_dp(connector);
>>  
>> diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
>> index 0fd9cf27542c..7cd954226fe3 100644
>> --- a/drivers/gpu/drm/bridge/tc358767.c
>> +++ b/drivers/gpu/drm/bridge/tc358767.c
>> @@ -1155,7 +1155,8 @@ static void tc_connector_set_polling(struct tc_data *tc,
>>  }
>>  
>>  static struct drm_encoder *
>> -tc_connector_best_encoder(struct drm_connector *connector)
>> +tc_connector_best_encoder(struct drm_connector *connector,
>> +			  struct drm_crtc *crtc)
>>  {
>>  	struct tc_data *tc = connector_to_tc(connector);
>>  
>> diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
>> index b529f8c8e2a6..378ebc3f25e8 100644
>> --- a/drivers/gpu/drm/cirrus/cirrus_mode.c
>> +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
>> @@ -451,8 +451,9 @@ static int cirrus_vga_get_modes(struct drm_connector *connector)
>>  	return count;
>>  }
>>  
>> -static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
>> -						  *connector)
>> +static struct drm_encoder *
>> +cirrus_connector_best_encoder(struct drm_connector *connector,
>> +			      struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  	/* pick the encoder ids */
>> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
>> index 232fa11a5e31..bd3aebbfd5b4 100644
>> --- a/drivers/gpu/drm/drm_atomic_helper.c
>> +++ b/drivers/gpu/drm/drm_atomic_helper.c
>> @@ -115,9 +115,11 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
>>  		if (funcs->atomic_best_encoder)
>>  			new_encoder = funcs->atomic_best_encoder(connector, new_conn_state);
>>  		else if (funcs->best_encoder)
>> -			new_encoder = funcs->best_encoder(connector);
>> +			new_encoder = funcs->best_encoder(connector,
>> +							  new_conn_state->crtc);
>>  		else
>> -			new_encoder = drm_atomic_helper_best_encoder(connector);
>> +			new_encoder = drm_atomic_helper_best_encoder(connector,
>> +								     new_conn_state->crtc);
>>  
>>  		if (new_encoder) {
>>  			if (encoder_mask & (1 << drm_encoder_index(new_encoder))) {
>> @@ -312,9 +314,11 @@ update_connector_routing(struct drm_atomic_state *state,
>>  		new_encoder = funcs->atomic_best_encoder(connector,
>>  							 new_connector_state);
>>  	else if (funcs->best_encoder)
>> -		new_encoder = funcs->best_encoder(connector);
>> +		new_encoder = funcs->best_encoder(connector,
>> +						  new_connector_state->crtc);
>>  	else
>> -		new_encoder = drm_atomic_helper_best_encoder(connector);
>> +		new_encoder = drm_atomic_helper_best_encoder(connector,
>> +							     new_connector_state->crtc);
>>  
>>  	if (!new_encoder) {
>>  		DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n",
>> @@ -3318,13 +3322,15 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
>>   * drm_atomic_helper_best_encoder - Helper for
>>   * 	&drm_connector_helper_funcs.best_encoder callback
>>   * @connector: Connector control structure
>> + * @crtc: DRM crtc
>>   *
>>   * This is a &drm_connector_helper_funcs.best_encoder callback helper for
>>   * connectors that support exactly 1 encoder, statically determined at driver
>>   * init time.
>>   */
>>  struct drm_encoder *
>> -drm_atomic_helper_best_encoder(struct drm_connector *connector)
>> +drm_atomic_helper_best_encoder(struct drm_connector *connector,
>> +			       struct drm_crtc *crtc)
>>  {
>>  	WARN_ON(connector->encoder_ids[1]);
>>  	return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
>> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
>> index 5a84c3bc915d..f9318fc11fb1 100644
>> --- a/drivers/gpu/drm/drm_crtc_helper.c
>> +++ b/drivers/gpu/drm/drm_crtc_helper.c
>> @@ -637,7 +637,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set,
>>  		new_encoder = connector->encoder;
>>  		for (ro = 0; ro < set->num_connectors; ro++) {
>>  			if (set->connectors[ro] == connector) {
>> -				new_encoder = connector_funcs->best_encoder(connector);
>> +				new_encoder = connector_funcs->best_encoder(connector,
>> +									    set->crtc);
>>  				/* if we can't get an encoder for a connector
>>  				   we are setting now - then fail */
>>  				if (new_encoder == NULL)
>> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
>> index cab14f253384..ce91ae12cccb 100644
>> --- a/drivers/gpu/drm/drm_fb_helper.c
>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>> @@ -2331,9 +2331,8 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
>>  	int c, o;
>>  	struct drm_connector *connector;
>>  	const struct drm_connector_helper_funcs *connector_funcs;
>> -	struct drm_encoder *encoder;
>>  	int my_score, best_score, score;
>> -	struct drm_fb_helper_crtc **crtcs, *crtc;
>> +	struct drm_fb_helper_crtc **crtcs;
>>  	struct drm_fb_helper_connector *fb_helper_conn;
>>  
>>  	if (n == fb_helper->connector_count)
>> @@ -2362,28 +2361,32 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
>>  
>>  	connector_funcs = connector->helper_private;
>>  
>> -	/*
>> -	 * If the DRM device implements atomic hooks and ->best_encoder() is
>> -	 * NULL we fallback to the default drm_atomic_helper_best_encoder()
>> -	 * helper.
>> -	 */
>> -	if (drm_drv_uses_atomic_modeset(fb_helper->dev) &&
>> -	    !connector_funcs->best_encoder)
>> -		encoder = drm_atomic_helper_best_encoder(connector);
>> -	else
>> -		encoder = connector_funcs->best_encoder(connector);
>> -
>> -	if (!encoder)
>> -		goto out;
>> -
>>  	/*
>>  	 * select a crtc for this connector and then attempt to configure
>>  	 * remaining connectors
>>  	 */
>>  	for (c = 0; c < fb_helper->crtc_count; c++) {
>> -		crtc = &fb_helper->crtc_info[c];
>> +		struct drm_encoder *encoder;
>> +		struct drm_fb_helper_crtc *crtc = &fb_helper->crtc_info[c];
>>  
>> -		if ((encoder->possible_crtcs & (1 << c)) == 0)
>> +		/*
>> +		 * If the DRM device implements atomic hooks and ->best_encoder() is
>> +		 * NULL we fallback to the default drm_atomic_helper_best_encoder()
>> +		 * helper.
>> +		 */
>> +		if (drm_drv_uses_atomic_modeset(fb_helper->dev) &&
>> +		    !connector_funcs->best_encoder)
>> +			encoder = drm_atomic_helper_best_encoder(connector,
>> +								 crtc->mode_set.crtc);
>> +		else
>> +			encoder = connector_funcs->best_encoder(connector,
>> +								crtc->mode_set.crtc);
>> +
>> +		if (!encoder)
>> +			continue;
>> +
>> +		if ((encoder->possible_crtcs &
>> +		     drm_crtc_mask(crtc->mode_set.crtc)) == 0)
>>  			continue;
>>  
>>  		for (o = 0; o < n; o++)
>> @@ -2410,7 +2413,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
>>  			       sizeof(struct drm_fb_helper_crtc *));
>>  		}
>>  	}
>> -out:
>> +
>>  	kfree(crtcs);
>>  	return best_score;
>>  }
>> diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
>> index c8f071c47daf..251b64653dc8 100644
>> --- a/drivers/gpu/drm/gma500/gma_display.c
>> +++ b/drivers/gpu/drm/gma500/gma_display.c
>> @@ -652,7 +652,8 @@ void gma_encoder_destroy(struct drm_encoder *encoder)
>>  }
>>  
>>  /* Currently there is only a 1:1 mapping of encoders and connectors */
>> -struct drm_encoder *gma_best_encoder(struct drm_connector *connector)
>> +struct drm_encoder *gma_best_encoder(struct drm_connector *connector,
>> +				     struct drm_crtc *crtc)
>>  {
>>  	struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
>>  
>> diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
>> index fe020926ea4f..9e5b059a9e5b 100644
>> --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
>> +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
>> @@ -377,8 +377,9 @@ static enum drm_mode_status mdfld_dsi_connector_mode_valid(struct drm_connector
>>  	return MODE_OK;
>>  }
>>  
>> -static struct drm_encoder *mdfld_dsi_connector_best_encoder(
>> -				struct drm_connector *connector)
>> +static struct drm_encoder *
>> +mdfld_dsi_connector_best_encoder(struct drm_connector *connector,
>> +				 struct drm_crtc *crtc)
>>  {
>>  	struct mdfld_dsi_connector *dsi_connector =
>>  				mdfld_dsi_connector(connector);
>> diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
>> index e05e5399af2d..e903525b9d30 100644
>> --- a/drivers/gpu/drm/gma500/psb_intel_drv.h
>> +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
>> @@ -230,7 +230,8 @@ extern void oaktrail_lvds_i2c_init(struct drm_encoder *encoder);
>>  extern void mid_dsi_init(struct drm_device *dev,
>>  		    struct psb_intel_mode_device *mode_dev, int dsi_num);
>>  
>> -extern struct drm_encoder *gma_best_encoder(struct drm_connector *connector);
>> +extern struct drm_encoder *gma_best_encoder(struct drm_connector *connector,
>> +					    struct drm_crtc *crtc);
>>  extern void gma_connector_attach_encoder(struct gma_connector *connector,
>>  					 struct gma_encoder *encoder);
>>  
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
>> index d2f4749ebf8d..89a0104f9855 100644
>> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
>> @@ -34,7 +34,8 @@ static enum drm_mode_status hibmc_connector_mode_valid(struct drm_connector *con
>>  }
>>  
>>  static struct drm_encoder *
>> -hibmc_connector_best_encoder(struct drm_connector *connector)
>> +hibmc_connector_best_encoder(struct drm_connector *connector,
>> +			     struct drm_crtc *crtc)
>>  {
>>  	return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
>>  }
>> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
>> index 0038c976536a..422347d977b4 100644
>> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
>> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
>> @@ -1267,7 +1267,8 @@ static enum drm_mode_status tda998x_connector_mode_valid(struct drm_connector *c
>>  }
>>  
>>  static struct drm_encoder *
>> -tda998x_connector_best_encoder(struct drm_connector *connector)
>> +tda998x_connector_best_encoder(struct drm_connector *connector,
>> +			       struct drm_crtc *crtc)
>>  {
>>  	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
>>  
>> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
>> index 5890500a3a8b..d9119d516579 100644
>> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
>> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
>> @@ -403,20 +403,23 @@ static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *c
>>  	return &intel_dp->mst_encoders[crtc->pipe]->base.base;
>>  }
>>  
>> -static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector)
>> +static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector,
>> +						  struct drm_crtc *_crtc)
>>  {
>>  	struct intel_connector *intel_connector = to_intel_connector(connector);
>>  	struct intel_dp *intel_dp = intel_connector->mst_port;
>> +	struct intel_crtc *crtc = to_intel_crtc(_crtc);
>> +
>>  	if (!intel_dp)
>>  		return NULL;
>> -	return &intel_dp->mst_encoders[0]->base.base;
>> +	return &intel_dp->mst_encoders[crtc->pipe]->base.base;
>>  }
>>  
>>  static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = {
>>  	.get_modes = intel_dp_mst_get_modes,
>>  	.mode_valid = intel_dp_mst_mode_valid,
>>  	.atomic_best_encoder = intel_mst_atomic_best_encoder,
>> -	.best_encoder = intel_mst_best_encoder,
>> +	.best_encoder = intel_mst_best_encoder, /* only for fb_helper */
>>  	.atomic_check = intel_dp_mst_atomic_check,
>>  };
>>  
>> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
>> index 56dd7a9a8e25..f1523cccc090 100644
>> --- a/drivers/gpu/drm/imx/imx-ldb.c
>> +++ b/drivers/gpu/drm/imx/imx-ldb.c
>> @@ -163,8 +163,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
>>  	return num_modes;
>>  }
>>  
>> -static struct drm_encoder *imx_ldb_connector_best_encoder(
>> -		struct drm_connector *connector)
>> +static struct drm_encoder *
>> +imx_ldb_connector_best_encoder(struct drm_connector *connector,
>> +			       struct drm_crtc *crtc)
>>  {
>>  	struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
>>  
>> diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
>> index bc27c2699464..71f49ac835ec 100644
>> --- a/drivers/gpu/drm/imx/imx-tve.c
>> +++ b/drivers/gpu/drm/imx/imx-tve.c
>> @@ -265,8 +265,9 @@ static int imx_tve_connector_mode_valid(struct drm_connector *connector,
>>  	return MODE_BAD;
>>  }
>>  
>> -static struct drm_encoder *imx_tve_connector_best_encoder(
>> -		struct drm_connector *connector)
>> +static struct drm_encoder *
>> +imx_tve_connector_best_encoder(struct drm_connector *connector,
>> +			       struct drm_crtc *crtc)
>>  {
>>  	struct imx_tve *tve = con_to_tve(connector);
>>  
>> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
>> index aedecda9728a..438f95dee73e 100644
>> --- a/drivers/gpu/drm/imx/parallel-display.c
>> +++ b/drivers/gpu/drm/imx/parallel-display.c
>> @@ -89,8 +89,9 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
>>  	return num_modes;
>>  }
>>  
>> -static struct drm_encoder *imx_pd_connector_best_encoder(
>> -		struct drm_connector *connector)
>> +static struct drm_encoder *
>> +imx_pd_connector_best_encoder(struct drm_connector *connector,
>> +			      struct drm_crtc *crtc)
>>  {
>>  	struct imx_parallel_display *imxpd = con_to_imxpd(connector);
>>  
>> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> index 59a11026dceb..c0578779fb19 100644
>> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> @@ -1253,7 +1253,8 @@ static int mtk_hdmi_conn_mode_valid(struct drm_connector *conn,
>>  	return drm_mode_validate_size(mode, 0x1fff, 0x1fff);
>>  }
>>  
>> -static struct drm_encoder *mtk_hdmi_conn_best_enc(struct drm_connector *conn)
>> +static struct drm_encoder *mtk_hdmi_conn_best_enc(struct drm_connector *conn,
>> +						  struct drm_crtc *crtc)
>>  {
>>  	struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
>>  
>> diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
>> index 8918539a19aa..4059f04030ee 100644
>> --- a/drivers/gpu/drm/mgag200/mgag200_mode.c
>> +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
>> @@ -1664,8 +1664,9 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector,
>>  	return MODE_OK;
>>  }
>>  
>> -static struct drm_encoder *mga_connector_best_encoder(struct drm_connector
>> -						  *connector)
>> +static struct drm_encoder *
>> +mga_connector_best_encoder(struct drm_connector *connector,
>> +			   struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  	/* pick the encoder ids */
>> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
>> index 4cb1cb68878b..8cbede64819e 100644
>> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
>> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
>> @@ -426,7 +426,8 @@ static int dsi_mgr_connector_mode_valid(struct drm_connector *connector,
>>  }
>>  
>>  static struct drm_encoder *
>> -dsi_mgr_connector_best_encoder(struct drm_connector *connector)
>> +dsi_mgr_connector_best_encoder(struct drm_connector *connector,
>> +			       struct drm_crtc *crtc)
>>  {
>>  	int id = dsi_mgr_connector_get_id(connector);
>>  	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
>> diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
>> index b83465ae7c1b..a9bacb0a1e16 100644
>> --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
>> +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
>> @@ -826,7 +826,8 @@ nv50_mstc_atomic_best_encoder(struct drm_connector *connector,
>>  }
>>  
>>  static struct drm_encoder *
>> -nv50_mstc_best_encoder(struct drm_connector *connector)
>> +nv50_mstc_best_encoder(struct drm_connector *connector,
>> +		       struct drm_crtc *crtc)
>>  {
>>  	struct nv50_mstc *mstc = nv50_mstc(connector);
>>  	if (mstc->port) {
>> diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
>> index 7b557c354307..ee4bf532b932 100644
>> --- a/drivers/gpu/drm/nouveau/nouveau_connector.c
>> +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
>> @@ -1063,7 +1063,8 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
>>  }
>>  
>>  static struct drm_encoder *
>> -nouveau_connector_best_encoder(struct drm_connector *connector)
>> +nouveau_connector_best_encoder(struct drm_connector *connector,
>> +			       struct drm_crtc *crtc)
>>  {
>>  	struct nouveau_connector *nv_connector = nouveau_connector(connector);
>>  
>> diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
>> index 768207fbbae3..fa5c84f35531 100644
>> --- a/drivers/gpu/drm/qxl/qxl_display.c
>> +++ b/drivers/gpu/drm/qxl/qxl_display.c
>> @@ -978,7 +978,8 @@ static enum drm_mode_status qxl_conn_mode_valid(struct drm_connector *connector,
>>  	return MODE_BAD;
>>  }
>>  
>> -static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector)
>> +static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector,
>> +					    struct drm_crtc *crtc)
>>  {
>>  	struct qxl_output *qxl_output =
>>  		drm_connector_to_qxl_output(connector);
>> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
>> index 2aea2bdff99b..8bf7298dccb3 100644
>> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
>> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
>> @@ -158,7 +158,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
>>  		else if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
>>  			const struct drm_connector_helper_funcs *connector_funcs =
>>  				connector->helper_private;
>> -			struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
>> +			struct drm_encoder *encoder = connector_funcs->best_encoder(connector, NULL);
>>  			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
>>  			struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
>>  
>> @@ -250,7 +250,7 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
>>  	bool connected;
>>  	int i;
>>  
>> -	best_encoder = connector_funcs->best_encoder(connector);
>> +	best_encoder = connector_funcs->best_encoder(connector, NULL);
>>  
>>  	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
>>  		if (connector->encoder_ids[i] == 0)
>> @@ -391,7 +391,8 @@ static int radeon_ddc_get_modes(struct drm_connector *connector)
>>  	return 0;
>>  }
>>  
>> -static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
>> +static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector,
>> +						      struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  	/* pick the encoder ids */
>> @@ -402,7 +403,7 @@ static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *conn
>>  
>>  static void radeon_get_native_mode(struct drm_connector *connector)
>>  {
>> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
>> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>>  	struct radeon_encoder *radeon_encoder;
>>  
>>  	if (encoder == NULL)
>> @@ -728,7 +729,7 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct
>>  			radeon_encoder = to_radeon_encoder(connector->encoder);
>>  		else {
>>  			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
>> -			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
>> +			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
>>  		}
>>  
>>  		switch (val) {
>> @@ -755,7 +756,7 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct
>>  			radeon_encoder = to_radeon_encoder(connector->encoder);
>>  		else {
>>  			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
>> -			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
>> +			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
>>  		}
>>  
>>  		if (radeon_encoder->output_csc == val)
>> @@ -824,7 +825,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
>>  	radeon_connector_get_edid(connector);
>>  	ret = radeon_ddc_get_modes(connector);
>>  	if (ret > 0) {
>> -		encoder = radeon_best_single_encoder(connector);
>> +		encoder = radeon_best_single_encoder(connector, NULL);
>>  		if (encoder) {
>>  			radeon_fixup_lvds_native_mode(encoder, connector);
>>  			/* add scaled modes */
>> @@ -833,7 +834,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
>>  		return ret;
>>  	}
>>  
>> -	encoder = radeon_best_single_encoder(connector);
>> +	encoder = radeon_best_single_encoder(connector, NULL);
>>  	if (!encoder)
>>  		return 0;
>>  
>> @@ -855,7 +856,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
>>  static enum drm_mode_status radeon_lvds_mode_valid(struct drm_connector *connector,
>>  				  struct drm_display_mode *mode)
>>  {
>> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
>> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>>  
>>  	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>>  		return MODE_PANEL;
>> @@ -888,7 +889,7 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
>>  	struct drm_device *dev = connector->dev;
>>  	struct radeon_device *rdev = dev->dev_private;
>>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
>> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>>  	enum drm_connector_status ret = connector_status_disconnected;
>>  	int r;
>>  
>> @@ -965,7 +966,7 @@ static int radeon_lvds_set_property(struct drm_connector *connector,
>>  		radeon_encoder = to_radeon_encoder(connector->encoder);
>>  	else {
>>  		const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
>> -		radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
>> +		radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
>>  	}
>>  
>>  	switch (value) {
>> @@ -1044,7 +1045,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
>>  			return connector_status_disconnected;
>>  	}
>>  
>> -	encoder = radeon_best_single_encoder(connector);
>> +	encoder = radeon_best_single_encoder(connector, NULL);
>>  	if (!encoder)
>>  		ret = connector_status_disconnected;
>>  
>> @@ -1139,7 +1140,7 @@ static int radeon_tv_get_modes(struct drm_connector *connector)
>>  	struct drm_display_mode *tv_mode;
>>  	struct drm_encoder *encoder;
>>  
>> -	encoder = radeon_best_single_encoder(connector);
>> +	encoder = radeon_best_single_encoder(connector, NULL);
>>  	if (!encoder)
>>  		return 0;
>>  
>> @@ -1182,7 +1183,7 @@ radeon_tv_detect(struct drm_connector *connector, bool force)
>>  			return connector_status_disconnected;
>>  	}
>>  
>> -	encoder = radeon_best_single_encoder(connector);
>> +	encoder = radeon_best_single_encoder(connector, NULL);
>>  	if (!encoder)
>>  		ret = connector_status_disconnected;
>>  	else {
>> @@ -1439,7 +1440,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>>  		const struct drm_connector_helper_funcs *connector_funcs =
>>  			connector->helper_private;
>>  
>> -		encoder = connector_funcs->best_encoder(connector);
>> +		encoder = connector_funcs->best_encoder(connector, NULL);
>>  		if (encoder && (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)) {
>>  			radeon_connector_get_edid(connector);
>>  			radeon_audio_detect(connector, encoder, ret);
>> @@ -1456,7 +1457,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>>  }
>>  
>>  /* okay need to be smart in here about which encoder to pick */
>> -static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
>> +static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector,
>> +					      struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>> @@ -1556,7 +1558,7 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
>>  {
>>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>>  	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
>> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
>> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>>  	int ret;
>>  
>>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
>> @@ -1695,7 +1697,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
>>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>>  	enum drm_connector_status ret = connector_status_disconnected;
>>  	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
>> -	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
>> +	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>>  	int r;
>>  
>>  	if (radeon_dig_connector->is_mst)
>> @@ -1812,7 +1814,7 @@ static enum drm_mode_status radeon_dp_mode_valid(struct drm_connector *connector
>>  
>>  	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
>>  	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
>> -		struct drm_encoder *encoder = radeon_best_single_encoder(connector);
>> +		struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
>>  
>>  		if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
>>  			return MODE_PANEL;
>> diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
>> index cd8a3ee16649..fd5a0dae0e1f 100644
>> --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
>> +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
>> @@ -224,7 +224,8 @@ radeon_dp_mst_mode_valid(struct drm_connector *connector,
>>  }
>>  
>>  static struct
>> -drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector)
>> +drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector,
>> +				     struct drm_crtc *crtc)
>>  {
>>  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
>>  
>> @@ -613,7 +614,7 @@ radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector)
>>  	struct radeon_encoder_mst *mst_enc;
>>  	struct drm_encoder *encoder;
>>  	const struct drm_connector_helper_funcs *connector_funcs = connector->base.helper_private;
>> -	struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base);
>> +	struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base, NULL);
>>  
>>  	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
>>  	radeon_encoder = kzalloc(sizeof(*radeon_encoder), GFP_KERNEL);
>> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
>> index e7738939a86d..cdc991d5c28e 100644
>> --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
>> +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
>> @@ -668,7 +668,8 @@ static int shmob_drm_connector_get_modes(struct drm_connector *connector)
>>  }
>>  
>>  static struct drm_encoder *
>> -shmob_drm_connector_best_encoder(struct drm_connector *connector)
>> +shmob_drm_connector_best_encoder(struct drm_connector *connector,
>> +				 struct drm_crtc *crtc)
>>  {
>>  	struct shmob_drm_connector *scon = to_shmob_connector(connector);
>>  
>> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
>> index d616d64a6725..197962eca1af 100644
>> --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
>> +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
>> @@ -178,8 +178,9 @@ static int panel_connector_mode_valid(struct drm_connector *connector,
>>  	return tilcdc_crtc_mode_valid(priv->crtc, mode);
>>  }
>>  
>> -static struct drm_encoder *panel_connector_best_encoder(
>> -		struct drm_connector *connector)
>> +static struct drm_encoder *
>> +panel_connector_best_encoder(struct drm_connector *connector,
>> +			     struct drm_crtc *crtc)
>>  {
>>  	struct panel_connector *panel_connector = to_panel_connector(connector);
>>  	return panel_connector->encoder;
>> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
>> index c45cabb38db0..0ef8221c5334 100644
>> --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
>> +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
>> @@ -191,8 +191,9 @@ static int tfp410_connector_mode_valid(struct drm_connector *connector,
>>  	return tilcdc_crtc_mode_valid(priv->crtc, mode);
>>  }
>>  
>> -static struct drm_encoder *tfp410_connector_best_encoder(
>> -		struct drm_connector *connector)
>> +static struct drm_encoder *
>> +tfp410_connector_best_encoder(struct drm_connector *connector,
>> +			      struct drm_crtc *crtc)
>>  {
>>  	struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
>>  	return tfp410_connector->encoder;
>> diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
>> index 09dc585aa46f..803ae6515892 100644
>> --- a/drivers/gpu/drm/udl/udl_connector.c
>> +++ b/drivers/gpu/drm/udl/udl_connector.c
>> @@ -145,7 +145,8 @@ udl_detect(struct drm_connector *connector, bool force)
>>  }
>>  
>>  static struct drm_encoder*
>> -udl_best_single_encoder(struct drm_connector *connector)
>> +udl_best_single_encoder(struct drm_connector *connector,
>> +			struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  	return drm_encoder_find(connector->dev, NULL, enc_id);
>> diff --git a/drivers/staging/vboxvideo/vbox_mode.c b/drivers/staging/vboxvideo/vbox_mode.c
>> index b265fe924556..bf0e93705e1c 100644
>> --- a/drivers/staging/vboxvideo/vbox_mode.c
>> +++ b/drivers/staging/vboxvideo/vbox_mode.c
>> @@ -370,8 +370,9 @@ static void vbox_encoder_destroy(struct drm_encoder *encoder)
>>  	kfree(encoder);
>>  }
>>  
>> -static struct drm_encoder *vbox_best_single_encoder(struct drm_connector
>> -						    *connector)
>> +static struct drm_encoder *
>> +vbox_best_single_encoder(struct drm_connector *connector,
>> +			 struct drm_crtc *crtc)
>>  {
>>  	int enc_id = connector->encoder_ids[0];
>>  
>> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
>> index 26aaba58d6ce..e0f00d43ed63 100644
>> --- a/include/drm/drm_atomic_helper.h
>> +++ b/include/drm/drm_atomic_helper.h
>> @@ -143,7 +143,8 @@ int drm_atomic_helper_page_flip_target(
>>  				uint32_t target,
>>  				struct drm_modeset_acquire_ctx *ctx);
>>  struct drm_encoder *
>> -drm_atomic_helper_best_encoder(struct drm_connector *connector);
>> +drm_atomic_helper_best_encoder(struct drm_connector *connector,
>> +			       struct drm_crtc *crtc);
>>  
>>  /* default implementations for state handling */
>>  void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
>> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
>> index 35e2a3a79fc5..a9b3a2c50877 100644
>> --- a/include/drm/drm_modeset_helper_vtables.h
>> +++ b/include/drm/drm_modeset_helper_vtables.h
>> @@ -885,7 +885,8 @@ struct drm_connector_helper_funcs {
>>  	/**
>>  	 * @best_encoder:
>>  	 *
>> -	 * This function should select the best encoder for the given connector.
>> +	 * This function should select the best encoder for the given connector
>> +	 * and crtc. For some driver internal use crtc may be NULL.
>>  	 *
>>  	 * This function is used by both the atomic helpers (in the
>>  	 * drm_atomic_helper_check_modeset() function) and in the legacy CRTC
>> @@ -911,7 +912,8 @@ struct drm_connector_helper_funcs {
>>  	 * will ensure that encoders aren't used twice, drivers should not check
>>  	 * for this.
>>  	 */
>> -	struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
>> +	struct drm_encoder *(*best_encoder)(struct drm_connector *connector,
>> +					    struct drm_crtc *crtc);
>>  
>>  	/**
>>  	 * @atomic_best_encoder:
>>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
>
diff mbox

Patch

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index 8e66851eb427..3dfa50ec2589 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -135,7 +135,8 @@  int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
 		else {
 			const struct drm_connector_helper_funcs *connector_funcs =
 				connector->helper_private;
-			struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
+			struct drm_encoder *encoder = connector_funcs->best_encoder(connector,
+										    NULL);
 			struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
 			struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
 
@@ -218,7 +219,7 @@  amdgpu_connector_update_scratch_regs(struct drm_connector *connector,
 	bool connected;
 	int i;
 
-	best_encoder = connector_funcs->best_encoder(connector);
+	best_encoder = connector_funcs->best_encoder(connector, NULL);
 
 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 		if (connector->encoder_ids[i] == 0)
@@ -358,7 +359,8 @@  static int amdgpu_connector_ddc_get_modes(struct drm_connector *connector)
 }
 
 static struct drm_encoder *
-amdgpu_connector_best_single_encoder(struct drm_connector *connector)
+amdgpu_connector_best_single_encoder(struct drm_connector *connector,
+				     struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 
@@ -370,7 +372,7 @@  amdgpu_connector_best_single_encoder(struct drm_connector *connector)
 
 static void amdgpu_get_native_mode(struct drm_connector *connector)
 {
-	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
+	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
 	struct amdgpu_encoder *amdgpu_encoder;
 
 	if (encoder == NULL)
@@ -593,7 +595,7 @@  static int amdgpu_connector_set_property(struct drm_connector *connector,
 			amdgpu_encoder = to_amdgpu_encoder(connector->encoder);
 		} else {
 			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
-			amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector));
+			amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector, NULL));
 		}
 
 		switch (val) {
@@ -663,7 +665,7 @@  static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
 	amdgpu_connector_get_edid(connector);
 	ret = amdgpu_connector_ddc_get_modes(connector);
 	if (ret > 0) {
-		encoder = amdgpu_connector_best_single_encoder(connector);
+		encoder = amdgpu_connector_best_single_encoder(connector, NULL);
 		if (encoder) {
 			amdgpu_connector_fixup_lcd_native_mode(encoder, connector);
 			/* add scaled modes */
@@ -672,7 +674,7 @@  static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
 		return ret;
 	}
 
-	encoder = amdgpu_connector_best_single_encoder(connector);
+	encoder = amdgpu_connector_best_single_encoder(connector, NULL);
 	if (!encoder)
 		return 0;
 
@@ -694,7 +696,7 @@  static int amdgpu_connector_lvds_get_modes(struct drm_connector *connector)
 static enum drm_mode_status amdgpu_connector_lvds_mode_valid(struct drm_connector *connector,
 					     struct drm_display_mode *mode)
 {
-	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
+	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
 
 	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
 		return MODE_PANEL;
@@ -725,7 +727,7 @@  static enum drm_connector_status
 amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)
 {
 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
-	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
+	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
 	enum drm_connector_status ret = connector_status_disconnected;
 	int r;
 
@@ -798,7 +800,7 @@  static int amdgpu_connector_set_lcd_property(struct drm_connector *connector,
 		amdgpu_encoder = to_amdgpu_encoder(connector->encoder);
 	else {
 		const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
-		amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector));
+		amdgpu_encoder = to_amdgpu_encoder(connector_funcs->best_encoder(connector, NULL));
 	}
 
 	switch (value) {
@@ -873,7 +875,7 @@  amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
 			return connector_status_disconnected;
 	}
 
-	encoder = amdgpu_connector_best_single_encoder(connector);
+	encoder = amdgpu_connector_best_single_encoder(connector, NULL);
 	if (!encoder)
 		ret = connector_status_disconnected;
 
@@ -1130,7 +1132,8 @@  amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
 
 /* okay need to be smart in here about which encoder to pick */
 static struct drm_encoder *
-amdgpu_connector_dvi_encoder(struct drm_connector *connector)
+amdgpu_connector_dvi_encoder(struct drm_connector *connector,
+			     struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
@@ -1224,7 +1227,7 @@  static int amdgpu_connector_dp_get_modes(struct drm_connector *connector)
 {
 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 	struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv;
-	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
+	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
 	int ret;
 
 	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
@@ -1363,7 +1366,7 @@  amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
 	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 	enum drm_connector_status ret = connector_status_disconnected;
 	struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv;
-	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
+	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
 	int r;
 
 	if (!drm_kms_helper_is_poll_worker()) {
@@ -1458,7 +1461,7 @@  static enum drm_mode_status amdgpu_connector_dp_mode_valid(struct drm_connector
 
 	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
 	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
-		struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
+		struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector, NULL);
 
 		if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
 			return MODE_PANEL;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
index dbf2ccd0c744..b02ce39e65b7 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
@@ -267,7 +267,8 @@  static int dce_virtual_early_init(void *handle)
 }
 
 static struct drm_encoder *
-dce_virtual_encoder(struct drm_connector *connector)
+dce_virtual_encoder(struct drm_connector *connector,
+		    struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 	struct drm_encoder *encoder;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 3e1c2a04d669..e56ed4e5818f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2758,7 +2758,8 @@  static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
 	.atomic_get_property = amdgpu_dm_connector_atomic_get_property
 };
 
-static struct drm_encoder *best_encoder(struct drm_connector *connector)
+static struct drm_encoder *best_encoder(struct drm_connector *connector,
+					struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 	struct drm_mode_object *obj;
@@ -3304,7 +3305,7 @@  static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
 	struct drm_encoder *encoder;
 	struct amdgpu_encoder *amdgpu_encoder;
 
-	encoder = helper->best_encoder(connector);
+	encoder = helper->best_encoder(connector, NULL);
 
 	if (encoder == NULL)
 		return;
@@ -3438,7 +3439,7 @@  static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
 	struct drm_encoder *encoder;
 	struct edid *edid = amdgpu_dm_connector->edid;
 
-	encoder = helper->best_encoder(connector);
+	encoder = helper->best_encoder(connector, NULL);
 	amdgpu_dm_connector_ddc_get_modes(connector, edid);
 	amdgpu_dm_connector_add_common_modes(encoder, connector);
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 4304d9e408b8..4544a1401caf 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -269,7 +269,8 @@  static int dm_dp_mst_get_modes(struct drm_connector *connector)
 	return ret;
 }
 
-static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector)
+static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector,
+					       struct drm_crtc *crtc)
 {
 	struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
 
@@ -302,7 +303,7 @@  dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector)
 	const struct drm_connector_helper_funcs *connector_funcs =
 		connector->base.helper_private;
 	struct drm_encoder *enc_master =
-		connector_funcs->best_encoder(&connector->base);
+		connector_funcs->best_encoder(&connector->base, NULL);
 
 	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
 	amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 036dff8a1f33..d5899aa41d37 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -709,7 +709,8 @@  static void ast_encoder_destroy(struct drm_encoder *encoder)
 }
 
 
-static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector)
+static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector,
+						   struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 	/* pick the encoder ids */
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 233980a78591..dc80a238feef 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -208,7 +208,8 @@  static enum drm_mode_status bochs_connector_mode_valid(struct drm_connector *con
 }
 
 static struct drm_encoder *
-bochs_connector_best_encoder(struct drm_connector *connector)
+bochs_connector_best_encoder(struct drm_connector *connector,
+			     struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 	/* pick the encoder ids */
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 2bcbfadb6ac5..0706471c8c63 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1137,7 +1137,8 @@  static int analogix_dp_get_modes(struct drm_connector *connector)
 }
 
 static struct drm_encoder *
-analogix_dp_best_encoder(struct drm_connector *connector)
+analogix_dp_best_encoder(struct drm_connector *connector,
+			 struct drm_crtc *crtc)
 {
 	struct analogix_dp_device *dp = to_dp(connector);
 
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 0fd9cf27542c..7cd954226fe3 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1155,7 +1155,8 @@  static void tc_connector_set_polling(struct tc_data *tc,
 }
 
 static struct drm_encoder *
-tc_connector_best_encoder(struct drm_connector *connector)
+tc_connector_best_encoder(struct drm_connector *connector,
+			  struct drm_crtc *crtc)
 {
 	struct tc_data *tc = connector_to_tc(connector);
 
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
index b529f8c8e2a6..378ebc3f25e8 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -451,8 +451,9 @@  static int cirrus_vga_get_modes(struct drm_connector *connector)
 	return count;
 }
 
-static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
-						  *connector)
+static struct drm_encoder *
+cirrus_connector_best_encoder(struct drm_connector *connector,
+			      struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 	/* pick the encoder ids */
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 232fa11a5e31..bd3aebbfd5b4 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -115,9 +115,11 @@  static int handle_conflicting_encoders(struct drm_atomic_state *state,
 		if (funcs->atomic_best_encoder)
 			new_encoder = funcs->atomic_best_encoder(connector, new_conn_state);
 		else if (funcs->best_encoder)
-			new_encoder = funcs->best_encoder(connector);
+			new_encoder = funcs->best_encoder(connector,
+							  new_conn_state->crtc);
 		else
-			new_encoder = drm_atomic_helper_best_encoder(connector);
+			new_encoder = drm_atomic_helper_best_encoder(connector,
+								     new_conn_state->crtc);
 
 		if (new_encoder) {
 			if (encoder_mask & (1 << drm_encoder_index(new_encoder))) {
@@ -312,9 +314,11 @@  update_connector_routing(struct drm_atomic_state *state,
 		new_encoder = funcs->atomic_best_encoder(connector,
 							 new_connector_state);
 	else if (funcs->best_encoder)
-		new_encoder = funcs->best_encoder(connector);
+		new_encoder = funcs->best_encoder(connector,
+						  new_connector_state->crtc);
 	else
-		new_encoder = drm_atomic_helper_best_encoder(connector);
+		new_encoder = drm_atomic_helper_best_encoder(connector,
+							     new_connector_state->crtc);
 
 	if (!new_encoder) {
 		DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n",
@@ -3318,13 +3322,15 @@  EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
  * drm_atomic_helper_best_encoder - Helper for
  * 	&drm_connector_helper_funcs.best_encoder callback
  * @connector: Connector control structure
+ * @crtc: DRM crtc
  *
  * This is a &drm_connector_helper_funcs.best_encoder callback helper for
  * connectors that support exactly 1 encoder, statically determined at driver
  * init time.
  */
 struct drm_encoder *
-drm_atomic_helper_best_encoder(struct drm_connector *connector)
+drm_atomic_helper_best_encoder(struct drm_connector *connector,
+			       struct drm_crtc *crtc)
 {
 	WARN_ON(connector->encoder_ids[1]);
 	return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 5a84c3bc915d..f9318fc11fb1 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -637,7 +637,8 @@  int drm_crtc_helper_set_config(struct drm_mode_set *set,
 		new_encoder = connector->encoder;
 		for (ro = 0; ro < set->num_connectors; ro++) {
 			if (set->connectors[ro] == connector) {
-				new_encoder = connector_funcs->best_encoder(connector);
+				new_encoder = connector_funcs->best_encoder(connector,
+									    set->crtc);
 				/* if we can't get an encoder for a connector
 				   we are setting now - then fail */
 				if (new_encoder == NULL)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index cab14f253384..ce91ae12cccb 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -2331,9 +2331,8 @@  static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
 	int c, o;
 	struct drm_connector *connector;
 	const struct drm_connector_helper_funcs *connector_funcs;
-	struct drm_encoder *encoder;
 	int my_score, best_score, score;
-	struct drm_fb_helper_crtc **crtcs, *crtc;
+	struct drm_fb_helper_crtc **crtcs;
 	struct drm_fb_helper_connector *fb_helper_conn;
 
 	if (n == fb_helper->connector_count)
@@ -2362,28 +2361,32 @@  static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
 
 	connector_funcs = connector->helper_private;
 
-	/*
-	 * If the DRM device implements atomic hooks and ->best_encoder() is
-	 * NULL we fallback to the default drm_atomic_helper_best_encoder()
-	 * helper.
-	 */
-	if (drm_drv_uses_atomic_modeset(fb_helper->dev) &&
-	    !connector_funcs->best_encoder)
-		encoder = drm_atomic_helper_best_encoder(connector);
-	else
-		encoder = connector_funcs->best_encoder(connector);
-
-	if (!encoder)
-		goto out;
-
 	/*
 	 * select a crtc for this connector and then attempt to configure
 	 * remaining connectors
 	 */
 	for (c = 0; c < fb_helper->crtc_count; c++) {
-		crtc = &fb_helper->crtc_info[c];
+		struct drm_encoder *encoder;
+		struct drm_fb_helper_crtc *crtc = &fb_helper->crtc_info[c];
 
-		if ((encoder->possible_crtcs & (1 << c)) == 0)
+		/*
+		 * If the DRM device implements atomic hooks and ->best_encoder() is
+		 * NULL we fallback to the default drm_atomic_helper_best_encoder()
+		 * helper.
+		 */
+		if (drm_drv_uses_atomic_modeset(fb_helper->dev) &&
+		    !connector_funcs->best_encoder)
+			encoder = drm_atomic_helper_best_encoder(connector,
+								 crtc->mode_set.crtc);
+		else
+			encoder = connector_funcs->best_encoder(connector,
+								crtc->mode_set.crtc);
+
+		if (!encoder)
+			continue;
+
+		if ((encoder->possible_crtcs &
+		     drm_crtc_mask(crtc->mode_set.crtc)) == 0)
 			continue;
 
 		for (o = 0; o < n; o++)
@@ -2410,7 +2413,7 @@  static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
 			       sizeof(struct drm_fb_helper_crtc *));
 		}
 	}
-out:
+
 	kfree(crtcs);
 	return best_score;
 }
diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
index c8f071c47daf..251b64653dc8 100644
--- a/drivers/gpu/drm/gma500/gma_display.c
+++ b/drivers/gpu/drm/gma500/gma_display.c
@@ -652,7 +652,8 @@  void gma_encoder_destroy(struct drm_encoder *encoder)
 }
 
 /* Currently there is only a 1:1 mapping of encoders and connectors */
-struct drm_encoder *gma_best_encoder(struct drm_connector *connector)
+struct drm_encoder *gma_best_encoder(struct drm_connector *connector,
+				     struct drm_crtc *crtc)
 {
 	struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
 
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index fe020926ea4f..9e5b059a9e5b 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -377,8 +377,9 @@  static enum drm_mode_status mdfld_dsi_connector_mode_valid(struct drm_connector
 	return MODE_OK;
 }
 
-static struct drm_encoder *mdfld_dsi_connector_best_encoder(
-				struct drm_connector *connector)
+static struct drm_encoder *
+mdfld_dsi_connector_best_encoder(struct drm_connector *connector,
+				 struct drm_crtc *crtc)
 {
 	struct mdfld_dsi_connector *dsi_connector =
 				mdfld_dsi_connector(connector);
diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
index e05e5399af2d..e903525b9d30 100644
--- a/drivers/gpu/drm/gma500/psb_intel_drv.h
+++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
@@ -230,7 +230,8 @@  extern void oaktrail_lvds_i2c_init(struct drm_encoder *encoder);
 extern void mid_dsi_init(struct drm_device *dev,
 		    struct psb_intel_mode_device *mode_dev, int dsi_num);
 
-extern struct drm_encoder *gma_best_encoder(struct drm_connector *connector);
+extern struct drm_encoder *gma_best_encoder(struct drm_connector *connector,
+					    struct drm_crtc *crtc);
 extern void gma_connector_attach_encoder(struct gma_connector *connector,
 					 struct gma_encoder *encoder);
 
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
index d2f4749ebf8d..89a0104f9855 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -34,7 +34,8 @@  static enum drm_mode_status hibmc_connector_mode_valid(struct drm_connector *con
 }
 
 static struct drm_encoder *
-hibmc_connector_best_encoder(struct drm_connector *connector)
+hibmc_connector_best_encoder(struct drm_connector *connector,
+			     struct drm_crtc *crtc)
 {
 	return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
 }
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 0038c976536a..422347d977b4 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -1267,7 +1267,8 @@  static enum drm_mode_status tda998x_connector_mode_valid(struct drm_connector *c
 }
 
 static struct drm_encoder *
-tda998x_connector_best_encoder(struct drm_connector *connector)
+tda998x_connector_best_encoder(struct drm_connector *connector,
+			       struct drm_crtc *crtc)
 {
 	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
 
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 5890500a3a8b..d9119d516579 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -403,20 +403,23 @@  static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *c
 	return &intel_dp->mst_encoders[crtc->pipe]->base.base;
 }
 
-static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector)
+static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector,
+						  struct drm_crtc *_crtc)
 {
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct intel_dp *intel_dp = intel_connector->mst_port;
+	struct intel_crtc *crtc = to_intel_crtc(_crtc);
+
 	if (!intel_dp)
 		return NULL;
-	return &intel_dp->mst_encoders[0]->base.base;
+	return &intel_dp->mst_encoders[crtc->pipe]->base.base;
 }
 
 static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = {
 	.get_modes = intel_dp_mst_get_modes,
 	.mode_valid = intel_dp_mst_mode_valid,
 	.atomic_best_encoder = intel_mst_atomic_best_encoder,
-	.best_encoder = intel_mst_best_encoder,
+	.best_encoder = intel_mst_best_encoder, /* only for fb_helper */
 	.atomic_check = intel_dp_mst_atomic_check,
 };
 
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 56dd7a9a8e25..f1523cccc090 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -163,8 +163,9 @@  static int imx_ldb_connector_get_modes(struct drm_connector *connector)
 	return num_modes;
 }
 
-static struct drm_encoder *imx_ldb_connector_best_encoder(
-		struct drm_connector *connector)
+static struct drm_encoder *
+imx_ldb_connector_best_encoder(struct drm_connector *connector,
+			       struct drm_crtc *crtc)
 {
 	struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
 
diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index bc27c2699464..71f49ac835ec 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -265,8 +265,9 @@  static int imx_tve_connector_mode_valid(struct drm_connector *connector,
 	return MODE_BAD;
 }
 
-static struct drm_encoder *imx_tve_connector_best_encoder(
-		struct drm_connector *connector)
+static struct drm_encoder *
+imx_tve_connector_best_encoder(struct drm_connector *connector,
+			       struct drm_crtc *crtc)
 {
 	struct imx_tve *tve = con_to_tve(connector);
 
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index aedecda9728a..438f95dee73e 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -89,8 +89,9 @@  static int imx_pd_connector_get_modes(struct drm_connector *connector)
 	return num_modes;
 }
 
-static struct drm_encoder *imx_pd_connector_best_encoder(
-		struct drm_connector *connector)
+static struct drm_encoder *
+imx_pd_connector_best_encoder(struct drm_connector *connector,
+			      struct drm_crtc *crtc)
 {
 	struct imx_parallel_display *imxpd = con_to_imxpd(connector);
 
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 59a11026dceb..c0578779fb19 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1253,7 +1253,8 @@  static int mtk_hdmi_conn_mode_valid(struct drm_connector *conn,
 	return drm_mode_validate_size(mode, 0x1fff, 0x1fff);
 }
 
-static struct drm_encoder *mtk_hdmi_conn_best_enc(struct drm_connector *conn)
+static struct drm_encoder *mtk_hdmi_conn_best_enc(struct drm_connector *conn,
+						  struct drm_crtc *crtc)
 {
 	struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 8918539a19aa..4059f04030ee 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1664,8 +1664,9 @@  static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector,
 	return MODE_OK;
 }
 
-static struct drm_encoder *mga_connector_best_encoder(struct drm_connector
-						  *connector)
+static struct drm_encoder *
+mga_connector_best_encoder(struct drm_connector *connector,
+			   struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 	/* pick the encoder ids */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 4cb1cb68878b..8cbede64819e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -426,7 +426,8 @@  static int dsi_mgr_connector_mode_valid(struct drm_connector *connector,
 }
 
 static struct drm_encoder *
-dsi_mgr_connector_best_encoder(struct drm_connector *connector)
+dsi_mgr_connector_best_encoder(struct drm_connector *connector,
+			       struct drm_crtc *crtc)
 {
 	int id = dsi_mgr_connector_get_id(connector);
 	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index b83465ae7c1b..a9bacb0a1e16 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -826,7 +826,8 @@  nv50_mstc_atomic_best_encoder(struct drm_connector *connector,
 }
 
 static struct drm_encoder *
-nv50_mstc_best_encoder(struct drm_connector *connector)
+nv50_mstc_best_encoder(struct drm_connector *connector,
+		       struct drm_crtc *crtc)
 {
 	struct nv50_mstc *mstc = nv50_mstc(connector);
 	if (mstc->port) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 7b557c354307..ee4bf532b932 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1063,7 +1063,8 @@  nouveau_connector_mode_valid(struct drm_connector *connector,
 }
 
 static struct drm_encoder *
-nouveau_connector_best_encoder(struct drm_connector *connector)
+nouveau_connector_best_encoder(struct drm_connector *connector,
+			       struct drm_crtc *crtc)
 {
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 768207fbbae3..fa5c84f35531 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -978,7 +978,8 @@  static enum drm_mode_status qxl_conn_mode_valid(struct drm_connector *connector,
 	return MODE_BAD;
 }
 
-static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector)
+static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector,
+					    struct drm_crtc *crtc)
 {
 	struct qxl_output *qxl_output =
 		drm_connector_to_qxl_output(connector);
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 2aea2bdff99b..8bf7298dccb3 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -158,7 +158,7 @@  int radeon_get_monitor_bpc(struct drm_connector *connector)
 		else if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
 			const struct drm_connector_helper_funcs *connector_funcs =
 				connector->helper_private;
-			struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
+			struct drm_encoder *encoder = connector_funcs->best_encoder(connector, NULL);
 			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 			struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 
@@ -250,7 +250,7 @@  radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
 	bool connected;
 	int i;
 
-	best_encoder = connector_funcs->best_encoder(connector);
+	best_encoder = connector_funcs->best_encoder(connector, NULL);
 
 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 		if (connector->encoder_ids[i] == 0)
@@ -391,7 +391,8 @@  static int radeon_ddc_get_modes(struct drm_connector *connector)
 	return 0;
 }
 
-static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
+static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector,
+						      struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 	/* pick the encoder ids */
@@ -402,7 +403,7 @@  static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *conn
 
 static void radeon_get_native_mode(struct drm_connector *connector)
 {
-	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
 	struct radeon_encoder *radeon_encoder;
 
 	if (encoder == NULL)
@@ -728,7 +729,7 @@  static int radeon_connector_set_property(struct drm_connector *connector, struct
 			radeon_encoder = to_radeon_encoder(connector->encoder);
 		else {
 			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
-			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
+			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
 		}
 
 		switch (val) {
@@ -755,7 +756,7 @@  static int radeon_connector_set_property(struct drm_connector *connector, struct
 			radeon_encoder = to_radeon_encoder(connector->encoder);
 		else {
 			const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
-			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
+			radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
 		}
 
 		if (radeon_encoder->output_csc == val)
@@ -824,7 +825,7 @@  static int radeon_lvds_get_modes(struct drm_connector *connector)
 	radeon_connector_get_edid(connector);
 	ret = radeon_ddc_get_modes(connector);
 	if (ret > 0) {
-		encoder = radeon_best_single_encoder(connector);
+		encoder = radeon_best_single_encoder(connector, NULL);
 		if (encoder) {
 			radeon_fixup_lvds_native_mode(encoder, connector);
 			/* add scaled modes */
@@ -833,7 +834,7 @@  static int radeon_lvds_get_modes(struct drm_connector *connector)
 		return ret;
 	}
 
-	encoder = radeon_best_single_encoder(connector);
+	encoder = radeon_best_single_encoder(connector, NULL);
 	if (!encoder)
 		return 0;
 
@@ -855,7 +856,7 @@  static int radeon_lvds_get_modes(struct drm_connector *connector)
 static enum drm_mode_status radeon_lvds_mode_valid(struct drm_connector *connector,
 				  struct drm_display_mode *mode)
 {
-	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
 
 	if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
 		return MODE_PANEL;
@@ -888,7 +889,7 @@  radeon_lvds_detect(struct drm_connector *connector, bool force)
 	struct drm_device *dev = connector->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
 	enum drm_connector_status ret = connector_status_disconnected;
 	int r;
 
@@ -965,7 +966,7 @@  static int radeon_lvds_set_property(struct drm_connector *connector,
 		radeon_encoder = to_radeon_encoder(connector->encoder);
 	else {
 		const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
-		radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
+		radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector, NULL));
 	}
 
 	switch (value) {
@@ -1044,7 +1045,7 @@  radeon_vga_detect(struct drm_connector *connector, bool force)
 			return connector_status_disconnected;
 	}
 
-	encoder = radeon_best_single_encoder(connector);
+	encoder = radeon_best_single_encoder(connector, NULL);
 	if (!encoder)
 		ret = connector_status_disconnected;
 
@@ -1139,7 +1140,7 @@  static int radeon_tv_get_modes(struct drm_connector *connector)
 	struct drm_display_mode *tv_mode;
 	struct drm_encoder *encoder;
 
-	encoder = radeon_best_single_encoder(connector);
+	encoder = radeon_best_single_encoder(connector, NULL);
 	if (!encoder)
 		return 0;
 
@@ -1182,7 +1183,7 @@  radeon_tv_detect(struct drm_connector *connector, bool force)
 			return connector_status_disconnected;
 	}
 
-	encoder = radeon_best_single_encoder(connector);
+	encoder = radeon_best_single_encoder(connector, NULL);
 	if (!encoder)
 		ret = connector_status_disconnected;
 	else {
@@ -1439,7 +1440,7 @@  radeon_dvi_detect(struct drm_connector *connector, bool force)
 		const struct drm_connector_helper_funcs *connector_funcs =
 			connector->helper_private;
 
-		encoder = connector_funcs->best_encoder(connector);
+		encoder = connector_funcs->best_encoder(connector, NULL);
 		if (encoder && (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)) {
 			radeon_connector_get_edid(connector);
 			radeon_audio_detect(connector, encoder, ret);
@@ -1456,7 +1457,8 @@  radeon_dvi_detect(struct drm_connector *connector, bool force)
 }
 
 /* okay need to be smart in here about which encoder to pick */
-static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
+static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector,
+					      struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
@@ -1556,7 +1558,7 @@  static int radeon_dp_get_modes(struct drm_connector *connector)
 {
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
-	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
 	int ret;
 
 	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
@@ -1695,7 +1697,7 @@  radeon_dp_detect(struct drm_connector *connector, bool force)
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	enum drm_connector_status ret = connector_status_disconnected;
 	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
-	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+	struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
 	int r;
 
 	if (radeon_dig_connector->is_mst)
@@ -1812,7 +1814,7 @@  static enum drm_mode_status radeon_dp_mode_valid(struct drm_connector *connector
 
 	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
 	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
-		struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+		struct drm_encoder *encoder = radeon_best_single_encoder(connector, NULL);
 
 		if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
 			return MODE_PANEL;
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c
index cd8a3ee16649..fd5a0dae0e1f 100644
--- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -224,7 +224,8 @@  radeon_dp_mst_mode_valid(struct drm_connector *connector,
 }
 
 static struct
-drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector)
+drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector,
+				     struct drm_crtc *crtc)
 {
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 
@@ -613,7 +614,7 @@  radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector)
 	struct radeon_encoder_mst *mst_enc;
 	struct drm_encoder *encoder;
 	const struct drm_connector_helper_funcs *connector_funcs = connector->base.helper_private;
-	struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base);
+	struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base, NULL);
 
 	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
 	radeon_encoder = kzalloc(sizeof(*radeon_encoder), GFP_KERNEL);
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
index e7738939a86d..cdc991d5c28e 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -668,7 +668,8 @@  static int shmob_drm_connector_get_modes(struct drm_connector *connector)
 }
 
 static struct drm_encoder *
-shmob_drm_connector_best_encoder(struct drm_connector *connector)
+shmob_drm_connector_best_encoder(struct drm_connector *connector,
+				 struct drm_crtc *crtc)
 {
 	struct shmob_drm_connector *scon = to_shmob_connector(connector);
 
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
index d616d64a6725..197962eca1af 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
@@ -178,8 +178,9 @@  static int panel_connector_mode_valid(struct drm_connector *connector,
 	return tilcdc_crtc_mode_valid(priv->crtc, mode);
 }
 
-static struct drm_encoder *panel_connector_best_encoder(
-		struct drm_connector *connector)
+static struct drm_encoder *
+panel_connector_best_encoder(struct drm_connector *connector,
+			     struct drm_crtc *crtc)
 {
 	struct panel_connector *panel_connector = to_panel_connector(connector);
 	return panel_connector->encoder;
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
index c45cabb38db0..0ef8221c5334 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
@@ -191,8 +191,9 @@  static int tfp410_connector_mode_valid(struct drm_connector *connector,
 	return tilcdc_crtc_mode_valid(priv->crtc, mode);
 }
 
-static struct drm_encoder *tfp410_connector_best_encoder(
-		struct drm_connector *connector)
+static struct drm_encoder *
+tfp410_connector_best_encoder(struct drm_connector *connector,
+			      struct drm_crtc *crtc)
 {
 	struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
 	return tfp410_connector->encoder;
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index 09dc585aa46f..803ae6515892 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -145,7 +145,8 @@  udl_detect(struct drm_connector *connector, bool force)
 }
 
 static struct drm_encoder*
-udl_best_single_encoder(struct drm_connector *connector)
+udl_best_single_encoder(struct drm_connector *connector,
+			struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 	return drm_encoder_find(connector->dev, NULL, enc_id);
diff --git a/drivers/staging/vboxvideo/vbox_mode.c b/drivers/staging/vboxvideo/vbox_mode.c
index b265fe924556..bf0e93705e1c 100644
--- a/drivers/staging/vboxvideo/vbox_mode.c
+++ b/drivers/staging/vboxvideo/vbox_mode.c
@@ -370,8 +370,9 @@  static void vbox_encoder_destroy(struct drm_encoder *encoder)
 	kfree(encoder);
 }
 
-static struct drm_encoder *vbox_best_single_encoder(struct drm_connector
-						    *connector)
+static struct drm_encoder *
+vbox_best_single_encoder(struct drm_connector *connector,
+			 struct drm_crtc *crtc)
 {
 	int enc_id = connector->encoder_ids[0];
 
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 26aaba58d6ce..e0f00d43ed63 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -143,7 +143,8 @@  int drm_atomic_helper_page_flip_target(
 				uint32_t target,
 				struct drm_modeset_acquire_ctx *ctx);
 struct drm_encoder *
-drm_atomic_helper_best_encoder(struct drm_connector *connector);
+drm_atomic_helper_best_encoder(struct drm_connector *connector,
+			       struct drm_crtc *crtc);
 
 /* default implementations for state handling */
 void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index 35e2a3a79fc5..a9b3a2c50877 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -885,7 +885,8 @@  struct drm_connector_helper_funcs {
 	/**
 	 * @best_encoder:
 	 *
-	 * This function should select the best encoder for the given connector.
+	 * This function should select the best encoder for the given connector
+	 * and crtc. For some driver internal use crtc may be NULL.
 	 *
 	 * This function is used by both the atomic helpers (in the
 	 * drm_atomic_helper_check_modeset() function) and in the legacy CRTC
@@ -911,7 +912,8 @@  struct drm_connector_helper_funcs {
 	 * will ensure that encoders aren't used twice, drivers should not check
 	 * for this.
 	 */
-	struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
+	struct drm_encoder *(*best_encoder)(struct drm_connector *connector,
+					    struct drm_crtc *crtc);
 
 	/**
 	 * @atomic_best_encoder: