diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display')
28 files changed, 273 insertions, 121 deletions
| 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 e4b33c67b634..4ba8b54a2695 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2196,6 +2196,7 @@ void amdgpu_dm_update_connector_after_detect(  			drm_connector_update_edid_property(connector,  							   aconnector->edid); +			drm_add_edid_modes(connector, aconnector->edid);  			if (aconnector->dc_link->aux_mode)  				drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux, @@ -2833,12 +2834,18 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)  				    &dm_atomic_state_funcs);  	r = amdgpu_display_modeset_create_props(adev); -	if (r) +	if (r) { +		dc_release_state(state->context); +		kfree(state);  		return r; +	}  	r = amdgpu_dm_audio_init(adev); -	if (r) +	if (r) { +		dc_release_state(state->context); +		kfree(state);  		return r; +	}  	return 0;  } @@ -2855,6 +2862,8 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm)  #if defined(CONFIG_ACPI)  	struct amdgpu_dm_backlight_caps caps; +	memset(&caps, 0, sizeof(caps)); +  	if (dm->backlight_caps.caps_valid)  		return; @@ -2893,51 +2902,50 @@ static int set_backlight_via_aux(struct dc_link *link, uint32_t brightness)  	return rc ? 0 : 1;  } -static u32 convert_brightness(const struct amdgpu_dm_backlight_caps *caps, -			      const uint32_t user_brightness) +static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps, +				unsigned *min, unsigned *max)  { -	u32 min, max, conversion_pace; -	u32 brightness = user_brightness; -  	if (!caps) -		goto out; +		return 0; -	if (!caps->aux_support) { -		max = caps->max_input_signal; -		min = caps->min_input_signal; -		/* -		 * The brightness input is in the range 0-255 -		 * It needs to be rescaled to be between the -		 * requested min and max input signal -		 * It also needs to be scaled up by 0x101 to -		 * match the DC interface which has a range of -		 * 0 to 0xffff -		 */ -		conversion_pace = 0x101; -		brightness = -			user_brightness -			* conversion_pace -			* (max - min) -			/ AMDGPU_MAX_BL_LEVEL -			+ min * conversion_pace; +	if (caps->aux_support) { +		// Firmware limits are in nits, DC API wants millinits. +		*max = 1000 * caps->aux_max_input_signal; +		*min = 1000 * caps->aux_min_input_signal;  	} else { -		/* TODO -		 * We are doing a linear interpolation here, which is OK but -		 * does not provide the optimal result. We probably want -		 * something close to the Perceptual Quantizer (PQ) curve. -		 */ -		max = caps->aux_max_input_signal; -		min = caps->aux_min_input_signal; - -		brightness = (AMDGPU_MAX_BL_LEVEL - user_brightness) * min -			       + user_brightness * max; -		// Multiple the value by 1000 since we use millinits -		brightness *= 1000; -		brightness = DIV_ROUND_CLOSEST(brightness, AMDGPU_MAX_BL_LEVEL); +		// Firmware limits are 8-bit, PWM control is 16-bit. +		*max = 0x101 * caps->max_input_signal; +		*min = 0x101 * caps->min_input_signal;  	} +	return 1; +} + +static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps, +					uint32_t brightness) +{ +	unsigned min, max; + +	if (!get_brightness_range(caps, &min, &max)) +		return brightness; + +	// Rescale 0..255 to min..max +	return min + DIV_ROUND_CLOSEST((max - min) * brightness, +				       AMDGPU_MAX_BL_LEVEL); +} + +static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps, +				      uint32_t brightness) +{ +	unsigned min, max; + +	if (!get_brightness_range(caps, &min, &max)) +		return brightness; -out: -	return brightness; +	if (brightness < min) +		return 0; +	// Rescale min..max to 0..255 +	return DIV_ROUND_CLOSEST(AMDGPU_MAX_BL_LEVEL * (brightness - min), +				 max - min);  }  static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) @@ -2953,7 +2961,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)  	link = (struct dc_link *)dm->backlight_link; -	brightness = convert_brightness(&caps, bd->props.brightness); +	brightness = convert_brightness_from_user(&caps, bd->props.brightness);  	// Change brightness based on AUX property  	if (caps.aux_support)  		return set_backlight_via_aux(link, brightness); @@ -2970,7 +2978,7 @@ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)  	if (ret == DC_ERROR_UNEXPECTED)  		return bd->props.brightness; -	return ret; +	return convert_brightness_to_user(&dm->backlight_caps, ret);  }  static const struct backlight_ops amdgpu_dm_backlight_ops = { @@ -5270,19 +5278,6 @@ static void dm_crtc_helper_disable(struct drm_crtc *crtc)  {  } -static bool does_crtc_have_active_cursor(struct drm_crtc_state *new_crtc_state) -{ -	struct drm_device *dev = new_crtc_state->crtc->dev; -	struct drm_plane *plane; - -	drm_for_each_plane_mask(plane, dev, new_crtc_state->plane_mask) { -		if (plane->type == DRM_PLANE_TYPE_CURSOR) -			return true; -	} - -	return false; -} -  static int count_crtc_active_planes(struct drm_crtc_state *new_crtc_state)  {  	struct drm_atomic_state *state = new_crtc_state->state; @@ -5346,19 +5341,20 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,  		return ret;  	} -	/* In some use cases, like reset, no stream is attached */ -	if (!dm_crtc_state->stream) -		return 0; -  	/* -	 * We want at least one hardware plane enabled to use -	 * the stream with a cursor enabled. +	 * We require the primary plane to be enabled whenever the CRTC is, otherwise +	 * drm_mode_cursor_universal may end up trying to enable the cursor plane while all other +	 * planes are disabled, which is not supported by the hardware. And there is legacy +	 * userspace which stops using the HW cursor altogether in response to the resulting EINVAL.  	 */ -	if (state->enable && state->active && -	    does_crtc_have_active_cursor(state) && -	    dm_crtc_state->active_planes == 0) +	if (state->enable && +	    !(state->plane_mask & drm_plane_mask(crtc->primary)))  		return -EINVAL; +	/* In some use cases, like reset, no stream is attached */ +	if (!dm_crtc_state->stream) +		return 0; +  	if (dc_validate_stream(dc, dm_crtc_state->stream) == DC_OK)  		return 0; 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 e85b58f0f416..336aaa09be46 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 @@ -67,7 +67,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,  	result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,  				      &operation_result); -	if (payload.write) +	if (payload.write && result >= 0)  		result = msg->size;  	if (result < 0) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 078b7e344185..2d5c7daaee23 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1108,6 +1108,18 @@ static enum bp_result bios_parser_enable_disp_power_gating(  		action);  } +static enum bp_result bios_parser_enable_lvtma_control( +	struct dc_bios *dcb, +	uint8_t uc_pwr_on) +{ +	struct bios_parser *bp = BP_FROM_DCB(dcb); + +	if (!bp->cmd_tbl.enable_lvtma_control) +		return BP_RESULT_FAILURE; + +	return bp->cmd_tbl.enable_lvtma_control(bp, uc_pwr_on); +} +  static bool bios_parser_is_accelerated_mode(  	struct dc_bios *dcb)  { @@ -2208,7 +2220,9 @@ static const struct dc_vbios_funcs vbios_funcs = {  	.get_board_layout_info = bios_get_board_layout_info,  	.pack_data_tables = bios_parser_pack_data_tables, -	.get_atom_dc_golden_table = bios_get_atom_dc_golden_table +	.get_atom_dc_golden_table = bios_get_atom_dc_golden_table, + +	.enable_lvtma_control = bios_parser_enable_lvtma_control  };  static bool bios_parser2_construct( diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index bed91572f82a..eb3ae5c3677c 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -904,6 +904,33 @@ static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id)  	return 0;  } +/****************************************************************************** + ****************************************************************************** + ** + **                  LVTMA CONTROL + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result enable_lvtma_control( +	struct bios_parser *bp, +	uint8_t uc_pwr_on); + +static void init_enable_lvtma_control(struct bios_parser *bp) +{ +	/* TODO add switch for table vrsion */ +	bp->cmd_tbl.enable_lvtma_control = enable_lvtma_control; + +} + +static enum bp_result enable_lvtma_control( +	struct bios_parser *bp, +	uint8_t uc_pwr_on) +{ +	enum bp_result result = BP_RESULT_FAILURE; +	return result; +} +  void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp)  {  	init_dig_encoder_control(bp); @@ -919,4 +946,5 @@ void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp)  	init_set_dce_clock(bp);  	init_get_smu_clock_info(bp); +	init_enable_lvtma_control(bp);  } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h index 7a2af24dfe60..7bdce013cde5 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h @@ -94,7 +94,8 @@ struct cmd_tbl {  		struct bp_set_dce_clock_parameters *bp_params);  	unsigned int (*get_smu_clock_info)(  			struct bios_parser *bp, uint8_t id); - +	enum bp_result (*enable_lvtma_control)(struct bios_parser *bp, +			uint8_t uc_pwr_on);  };  void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index c664404a75d4..543afa34d87a 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -94,6 +94,15 @@ int rn_get_active_display_cnt_wa(  	return display_count;  } +void rn_set_low_power_state(struct clk_mgr *clk_mgr_base) +{ +	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + +	rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_LOW_POWER); +	/* update power state */ +	clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; +} +  void rn_update_clocks(struct clk_mgr *clk_mgr_base,  			struct dc_state *context,  			bool safe_to_lower) @@ -516,6 +525,7 @@ static struct clk_mgr_funcs dcn21_funcs = {  	.init_clocks = rn_init_clocks,  	.enable_pme_wa = rn_enable_pme_wa,  	.are_clock_states_equal = rn_are_clock_states_equal, +	.set_low_power_state = rn_set_low_power_state,  	.notify_wm_ranges = rn_notify_wm_ranges,  	.notify_link_rate_change = rn_notify_link_rate_change,  }; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 4bd6e03a7ef3..437d1a7a16fe 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -763,6 +763,7 @@ static bool detect_dp(struct dc_link *link,  		sink_caps->signal = dp_passive_dongle_detection(link->ddc,  								sink_caps,  								audio_support); +		link->dpcd_caps.dongle_type = sink_caps->dongle_type;  	}  	return true; @@ -3289,7 +3290,6 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx)  #if defined(CONFIG_DRM_AMD_DC_HDCP)  	update_psp_stream_config(pipe_ctx, true);  #endif -  	dc->hwss.blank_stream(pipe_ctx);  	if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 9bc03f26efda..b2be6ad5101d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -4409,9 +4409,9 @@ bool dc_link_get_backlight_level_nits(struct dc_link *link,  			link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))  		return false; -	if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK, +	if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK,  			dpcd_backlight_get.raw, -			sizeof(union dpcd_source_backlight_get))) +			sizeof(union dpcd_source_backlight_get)) != DC_OK)  		return false;  	*backlight_millinits_avg = @@ -4450,9 +4450,9 @@ bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_milli  		link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))  		return false; -	if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, +	if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,  		(uint8_t *) backlight_millinits, -		sizeof(uint32_t))) +		sizeof(uint32_t)) != DC_OK)  		return false;  	return true; diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index d06d07042a12..0811f941f430 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -136,6 +136,10 @@ struct dc_vbios_funcs {  	enum bp_result (*get_atom_dc_golden_table)(  			struct dc_bios *dcb); + +	enum bp_result (*enable_lvtma_control)( +		struct dc_bios *bios, +		uint8_t uc_pwr_on);  };  struct bios_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 633442bc7ef2..d9888f316da6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -233,7 +233,7 @@ struct dc_stream_state {  	union stream_update_flags update_flags;  }; -#define ABM_LEVEL_IMMEDIATE_DISABLE 0xFFFFFFFF +#define ABM_LEVEL_IMMEDIATE_DISABLE 255  struct dc_stream_update {  	struct dc_stream_state *stream; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h index 70ec691e14d2..99c68ca9c7e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h @@ -49,7 +49,7 @@  #define DCN_PANEL_CNTL_REG_LIST()\  	DCN_PANEL_CNTL_SR(PWRSEQ_CNTL, LVTMA), \  	DCN_PANEL_CNTL_SR(PWRSEQ_STATE, LVTMA), \ -	DCE_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \ +	DCN_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \  	SR(BL_PWM_CNTL), \  	SR(BL_PWM_CNTL2), \  	SR(BL_PWM_PERIOD_CNTL), \ diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 49380ed3aeae..45c9e9027886 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -842,6 +842,17 @@ void dce110_edp_power_control(  		cntl.coherent = false;  		cntl.lanes_number = LANE_COUNT_FOUR;  		cntl.hpd_sel = link->link_enc->hpd_source; + +		if (ctx->dc->ctx->dmub_srv && +				ctx->dc->debug.dmub_command_table) { +			if (cntl.action == TRANSMITTER_CONTROL_POWER_ON) +				bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, +						LVTMA_CONTROL_POWER_ON); +			else +				bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, +						LVTMA_CONTROL_POWER_OFF); +		} +  		bp_result = link_transmitter_control(ctx->dc_bios, &cntl);  		if (!power_up) @@ -919,8 +930,21 @@ void dce110_edp_backlight_control(  		/*edp 1.2*/  	if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON)  		edp_receiver_ready_T7(link); + +	if (ctx->dc->ctx->dmub_srv && +			ctx->dc->debug.dmub_command_table) { +		if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) +			ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, +					LVTMA_CONTROL_LCD_BLON); +		else +			ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, +					LVTMA_CONTROL_LCD_BLOFF); +	} +  	link_transmitter_control(ctx->dc_bios, &cntl); + +  	if (enable && link->dpcd_sink_ext_caps.bits.oled)  		msleep(OLED_POST_T7_DELAY); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a643927e272b..fa643ec5a876 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1450,33 +1450,42 @@ void dcn10_init_hw(struct dc *dc)  void dcn10_power_down_on_boot(struct dc *dc)  {  	int i = 0; +	struct dc_link *edp_link; -	if (dc->config.power_down_display_on_boot) { -		struct dc_link *edp_link = get_edp_link(dc); - -		if (edp_link && -				edp_link->link_enc->funcs->is_dig_enabled && -				edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && -				dc->hwseq->funcs.edp_backlight_control && -				dc->hwss.power_down && -				dc->hwss.edp_power_control) { -			dc->hwseq->funcs.edp_backlight_control(edp_link, false); -			dc->hwss.power_down(dc); -			dc->hwss.edp_power_control(edp_link, false); -		} else { -			for (i = 0; i < dc->link_count; i++) { -				struct dc_link *link = dc->links[i]; - -				if (link->link_enc->funcs->is_dig_enabled && -						link->link_enc->funcs->is_dig_enabled(link->link_enc) && -						dc->hwss.power_down) { -					dc->hwss.power_down(dc); -					break; -				} +	if (!dc->config.power_down_display_on_boot) +		return; + +	edp_link = get_edp_link(dc); +	if (edp_link && +			edp_link->link_enc->funcs->is_dig_enabled && +			edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && +			dc->hwseq->funcs.edp_backlight_control && +			dc->hwss.power_down && +			dc->hwss.edp_power_control) { +		dc->hwseq->funcs.edp_backlight_control(edp_link, false); +		dc->hwss.power_down(dc); +		dc->hwss.edp_power_control(edp_link, false); +	} else { +		for (i = 0; i < dc->link_count; i++) { +			struct dc_link *link = dc->links[i]; +			if (link->link_enc->funcs->is_dig_enabled && +					link->link_enc->funcs->is_dig_enabled(link->link_enc) && +					dc->hwss.power_down) { +				dc->hwss.power_down(dc); +				break;  			} +  		}  	} + +	/* +	 * Call update_clocks with empty context +	 * to send DISPLAY_OFF +	 * Otherwise DISPLAY_OFF may not be asserted +	 */ +	if (dc->clk_mgr->funcs->set_low_power_state) +		dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr);  }  void dcn10_reset_hw_ctx_wrap( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 17d5cb422025..8939541ad7af 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1213,6 +1213,7 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont  	bool video_large = false;  	bool desktop_large = false;  	bool dcc_disabled = false; +	bool mpo_enabled = false;  	for (i = 0; i < context->stream_count; i++) {  		if (context->stream_status[i].plane_count == 0) @@ -1221,6 +1222,9 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont  		if (context->stream_status[i].plane_count > 2)  			return DC_FAIL_UNSUPPORTED_1; +		if (context->stream_status[i].plane_count > 1) +			mpo_enabled = true; +  		for (j = 0; j < context->stream_status[i].plane_count; j++) {  			struct dc_plane_state *plane =  				context->stream_status[i].plane_states[j]; @@ -1244,6 +1248,10 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont  		}  	} +	/* Disable MPO in multi-display configurations. */ +	if (context->stream_count > 1 && mpo_enabled) +		return DC_FAIL_UNSUPPORTED_1; +  	/*  	 * Workaround: On DCN10 there is UMC issue that causes underflow when  	 * playing 4k video on 4k desktop with video downscaled and single channel diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index 07b2f9399671..842abb4c475b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -121,35 +121,35 @@ void enc1_update_generic_info_packet(  	switch (packet_index) {  	case 0:  		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, -				AFMT_GENERIC0_FRAME_UPDATE, 1); +				AFMT_GENERIC0_IMMEDIATE_UPDATE, 1);  		break;  	case 1:  		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, -				AFMT_GENERIC1_FRAME_UPDATE, 1); +				AFMT_GENERIC1_IMMEDIATE_UPDATE, 1);  		break;  	case 2:  		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, -				AFMT_GENERIC2_FRAME_UPDATE, 1); +				AFMT_GENERIC2_IMMEDIATE_UPDATE, 1);  		break;  	case 3:  		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, -				AFMT_GENERIC3_FRAME_UPDATE, 1); +				AFMT_GENERIC3_IMMEDIATE_UPDATE, 1);  		break;  	case 4:  		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, -				AFMT_GENERIC4_FRAME_UPDATE, 1); +				AFMT_GENERIC4_IMMEDIATE_UPDATE, 1);  		break;  	case 5:  		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, -				AFMT_GENERIC5_FRAME_UPDATE, 1); +				AFMT_GENERIC5_IMMEDIATE_UPDATE, 1);  		break;  	case 6:  		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, -				AFMT_GENERIC6_FRAME_UPDATE, 1); +				AFMT_GENERIC6_IMMEDIATE_UPDATE, 1);  		break;  	case 7:  		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, -				AFMT_GENERIC7_FRAME_UPDATE, 1); +				AFMT_GENERIC7_IMMEDIATE_UPDATE, 1);  		break;  	default:  		break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h index ed385b1477be..30eae7459d50 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h @@ -281,7 +281,14 @@ struct dcn10_stream_enc_registers {  	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\  	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\  	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\ +	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\ +	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\ +	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\ +	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\  	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\ +	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\ +	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\ +	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\  	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\  	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\  	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\ @@ -345,7 +352,14 @@ struct dcn10_stream_enc_registers {  	type AFMT_GENERIC2_FRAME_UPDATE;\  	type AFMT_GENERIC3_FRAME_UPDATE;\  	type AFMT_GENERIC4_FRAME_UPDATE;\ +	type AFMT_GENERIC0_IMMEDIATE_UPDATE;\ +	type AFMT_GENERIC1_IMMEDIATE_UPDATE;\ +	type AFMT_GENERIC2_IMMEDIATE_UPDATE;\ +	type AFMT_GENERIC3_IMMEDIATE_UPDATE;\  	type AFMT_GENERIC4_IMMEDIATE_UPDATE;\ +	type AFMT_GENERIC5_IMMEDIATE_UPDATE;\ +	type AFMT_GENERIC6_IMMEDIATE_UPDATE;\ +	type AFMT_GENERIC7_IMMEDIATE_UPDATE;\  	type AFMT_GENERIC5_FRAME_UPDATE;\  	type AFMT_GENERIC6_FRAME_UPDATE;\  	type AFMT_GENERIC7_FRAME_UPDATE;\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 66180b4332f1..c8cfd3ba1c15 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1457,8 +1457,8 @@ static void dcn20_update_dchubp_dpp(  	/* Any updates are handled in dc interface, just need to apply existing for plane enable */  	if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed || -			pipe_ctx->update_flags.bits.scaler || pipe_ctx->update_flags.bits.viewport) -			&& pipe_ctx->stream->cursor_attributes.address.quad_part != 0) { +			pipe_ctx->update_flags.bits.scaler || viewport_changed == true) && +			pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {  		dc->hwss.set_cursor_position(pipe_ctx);  		dc->hwss.set_cursor_attribute(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h index bf0044f7417e..dcbf28dd72d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h @@ -167,7 +167,9 @@  	LE_SF(DCIO_SOFT_RESET, UNIPHYB_SOFT_RESET, mask_sh),\  	LE_SF(DCIO_SOFT_RESET, UNIPHYC_SOFT_RESET, mask_sh),\  	LE_SF(DCIO_SOFT_RESET, UNIPHYD_SOFT_RESET, mask_sh),\ -	LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh) +	LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh),\ +	LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ +	LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh)  #define LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh)\  	LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 790baf552695..f31f48dd0da2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -409,8 +409,8 @@ static struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = {  			},  		},  	.num_states = 5, -	.sr_exit_time_us = 8.6, -	.sr_enter_plus_exit_time_us = 10.9, +	.sr_exit_time_us = 11.6, +	.sr_enter_plus_exit_time_us = 13.9,  	.urgent_latency_us = 4.0,  	.urgent_latency_pixel_data_only_us = 4.0,  	.urgent_latency_pixel_mixed_with_vm_data_us = 4.0, @@ -3141,7 +3141,7 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co  	int vlevel = 0;  	int pipe_split_from[MAX_PIPES];  	int pipe_cnt = 0; -	display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); +	display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC);  	DC_LOGGER_INIT(dc->ctx->logger);  	BW_VAL_TRACE_COUNT(); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h index 8e9fd59ccde8..2fbf879cd327 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h @@ -61,7 +61,10 @@  	DPCS_DCN2_MASK_SH_LIST(mask_sh),\  	LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT_18_BIT, mask_sh),\  	LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_TX_VBOOST_LVL, mask_sh),\ -	LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh) +	LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh),\ +	LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ +	LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) +  void dcn30_link_encoder_construct(  	struct dcn20_link_encoder *enc20, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 653a571e366d..ebe0cc5b833b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -491,6 +491,7 @@ static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = {  [id] = {\  	LE_DCN3_REG_LIST(id), \  	UNIPHY_DCN2_REG_LIST(phyid), \ +	SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \  }  static const struct dce110_aux_registers_shift aux_shift = { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index b54814f11b74..2beb284f89b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -63,6 +63,7 @@ typedef struct {  #define BPP_INVALID 0  #define BPP_BLENDED_PIPE 0xffffffff +#define DCN30_MAX_DSC_IMAGE_WIDTH 5184  static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib);  static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( @@ -3984,6 +3985,9 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l  				} else if (v->PlaneRequiredDISPCLKWithoutODMCombine > v->MaxDispclkRoundedDownToDFSGranularity) {  					v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1;  					v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; +				} else if (v->DSCEnabled[k] && (v->HActive[k] > DCN30_MAX_DSC_IMAGE_WIDTH)) { +					v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; +					v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1;  				} else {  					v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled;  					v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithoutODMCombine; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index 5994d2a33c40..947d6106f341 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -230,6 +230,8 @@ struct clk_mgr_funcs {  	int (*get_dp_ref_clk_frequency)(struct clk_mgr *clk_mgr); +	void (*set_low_power_state)(struct clk_mgr *clk_mgr); +  	void (*init_clocks)(struct clk_mgr *clk_mgr);  	void (*enable_pme_wa) (struct clk_mgr *clk_mgr); diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index c30437ae8395..21011edea337 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -101,6 +101,13 @@ enum bp_pipe_control_action {  	ASIC_PIPE_INIT  }; +enum bp_lvtma_control_action { +	LVTMA_CONTROL_LCD_BLOFF = 2, +	LVTMA_CONTROL_LCD_BLON = 3, +	LVTMA_CONTROL_POWER_ON = 12, +	LVTMA_CONTROL_POWER_OFF = 13 +}; +  struct bp_encoder_control {  	enum bp_encoder_control_action action;  	enum engine_id engine_id; diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index 89ef9f6860e5..16df2a485dd0 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -431,6 +431,9 @@ struct fixed31_32 dc_fixpt_log(struct fixed31_32 arg);   */  static inline struct fixed31_32 dc_fixpt_pow(struct fixed31_32 arg1, struct fixed31_32 arg2)  { +	if (arg1.value == 0) +		return arg2.value == 0 ? dc_fixpt_one : dc_fixpt_zero; +  	return dc_fixpt_exp(  		dc_fixpt_mul(  			dc_fixpt_log(arg1), diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 81820f3d6b3b..d988533d4af5 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -324,22 +324,44 @@ static void apply_below_the_range(struct core_freesync *core_freesync,  		/* Choose number of frames to insert based on how close it  		 * can get to the mid point of the variable range. +		 *  - Delta for CEIL: delta_from_mid_point_in_us_1 +		 *  - Delta for FLOOR: delta_from_mid_point_in_us_2  		 */ -		if ((frame_time_in_us / mid_point_frames_ceil) > in_out_vrr->min_duration_in_us && -				(delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2 || -						mid_point_frames_floor < 2)) { +		if ((last_render_time_in_us / mid_point_frames_ceil) < in_out_vrr->min_duration_in_us) { +			/* Check for out of range. +			 * If using CEIL produces a value that is out of range, +			 * then we are forced to use FLOOR. +			 */ +			frames_to_insert = mid_point_frames_floor; +		} else if (mid_point_frames_floor < 2) { +			/* Check if FLOOR would result in non-LFC. In this case +			 * choose to use CEIL +			 */ +			frames_to_insert = mid_point_frames_ceil; +		} else if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) { +			/* If choosing CEIL results in a frame duration that is +			 * closer to the mid point of the range. +			 * Choose CEIL +			 */  			frames_to_insert = mid_point_frames_ceil; -			delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 - -					delta_from_mid_point_in_us_1;  		} else { +			/* If choosing FLOOR results in a frame duration that is +			 * closer to the mid point of the range. +			 * Choose FLOOR +			 */  			frames_to_insert = mid_point_frames_floor; -			delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 - -					delta_from_mid_point_in_us_2;  		}  		/* Prefer current frame multiplier when BTR is enabled unless it drifts  		 * too far from the midpoint  		 */ +		if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) { +			delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 - +					delta_from_mid_point_in_us_1; +		} else { +			delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 - +					delta_from_mid_point_in_us_2; +		}  		if (in_out_vrr->btr.frames_to_insert != 0 &&  				delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) {  			if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) < diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h index d3192b9d0c3d..47f8ee2832ff 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h @@ -27,7 +27,7 @@  #define MOD_HDCP_LOG_H_  #ifdef CONFIG_DRM_AMD_DC_HDCP -#define HDCP_LOG_ERR(hdcp, ...) DRM_WARN(__VA_ARGS__) +#define HDCP_LOG_ERR(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__)  #define HDCP_LOG_VER(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__)  #define HDCP_LOG_FSM(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__)  #define HDCP_LOG_TOP(hdcp, ...) pr_debug("[HDCP_TOP]:"__VA_ARGS__) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c index fb1161dd7ea8..3a367a5968ae 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -88,7 +88,7 @@ enum mod_hdcp_status mod_hdcp_add_display_to_topology(struct mod_hdcp *hdcp,  	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;  	if (!psp->dtm_context.dtm_initialized) { -		DRM_ERROR("Failed to add display topology, DTM TA is not initialized."); +		DRM_INFO("Failed to add display topology, DTM TA is not initialized.");  		display->state = MOD_HDCP_DISPLAY_INACTIVE;  		return MOD_HDCP_STATUS_FAILURE;  	} |