Commit da915efa authored by Reza Amini's avatar Reza Amini Committed by Alex Deucher
Browse files

drm/amd/display: ABM pause toggle



[why]
Allow ABM states to be transferred across display
adapters for smooth display transitions.

[how]
We call DMUB to pause and get ABM states. We
transfer data to other gpu, and deliver data and
ask ABM to un-pause.

Reviewed-by: default avatarHarry Vanzylldejong <harry.vanzylldejong@amd.com>
Acked-by: default avatarAlan Liu <haoping.liu@amd.com>
Signed-off-by: default avatarReza Amini <reza.amini@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 085f7bd9
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -5276,3 +5276,56 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo
	if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause)
		pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst);
}

/*****************************************************************************
 *  dc_abm_save_restore() - Interface to DC for save+pause and restore+un-pause
 *                          ABM
 *  @dc: dc structure
 *	@stream: stream where vsync int state changed
 *  @pData: abm hw states
 *
 ****************************************************************************/
bool dc_abm_save_restore(
		struct dc *dc,
		struct dc_stream_state *stream,
		struct abm_save_restore *pData)
{
	int i;
	int edp_num;
	struct pipe_ctx *pipe = NULL;
	struct dc_link *link = stream->sink->link;
	struct dc_link *edp_links[MAX_NUM_EDP];


	/*find primary pipe associated with stream*/
	for (i = 0; i < MAX_PIPES; i++) {
		pipe = &dc->current_state->res_ctx.pipe_ctx[i];

		if (pipe->stream == stream && pipe->stream_res.tg)
			break;
	}

	if (i == MAX_PIPES) {
		ASSERT(0);
		return false;
	}

	dc_get_edp_links(dc, edp_links, &edp_num);

	/* Determine panel inst */
	for (i = 0; i < edp_num; i++)
		if (edp_links[i] == link)
			break;

	if (i == edp_num)
		return false;

	if (pipe->stream_res.abm &&
		pipe->stream_res.abm->funcs->save_restore)
		return pipe->stream_res.abm->funcs->save_restore(
				pipe->stream_res.abm,
				i,
				pData);
	return false;
}
+7 −0
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@
#include "inc/hw/dmcu.h"
#include "dml/display_mode_lib.h"

struct abm_save_restore;

/* forward declaration */
struct aux_payload;
struct set_config_cmd_payload;
@@ -2244,6 +2246,11 @@ void dc_z10_save_init(struct dc *dc);
bool dc_is_dmub_outbox_supported(struct dc *dc);
bool dc_enable_dmub_notifications(struct dc *dc);

bool dc_abm_save_restore(
		struct dc *dc,
		struct dc_stream_state *stream,
		struct abm_save_restore *pData);

void dc_enable_dmub_outbox(struct dc *dc);

bool dc_process_dmub_aux_transfer_async(struct dc *dc,
+28 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "dmub_abm_lcd.h"
#include "dc.h"
#include "core_types.h"
#include "dmub_cmd.h"

#define TO_DMUB_ABM(abm)\
	container_of(abm, struct dce_abm, base)
@@ -118,6 +119,32 @@ static bool dmub_abm_set_pause_ex(struct abm *abm, bool pause, unsigned int pane
	return ret;
}

/*****************************************************************************
 *  dmub_abm_save_restore_ex() - calls dmub_abm_save_restore for preserving DMUB's
 *                              Varibright states for LCD only. OLED is TBD
 *  @abm: used to check get dc context
 *  @panel_inst: panel instance index
 *  @pData: contains command to pause/un-pause abm and abm parameters
 *
 *
 ***************************************************************************/
static bool dmub_abm_save_restore_ex(
		struct abm *abm,
		unsigned int panel_inst,
		struct abm_save_restore *pData)
{
	bool ret = false;
	unsigned int feature_support;
	struct dc_context *dc = abm->ctx;

	feature_support = abm_feature_support(abm, panel_inst);

	if (feature_support == ABM_LCD_SUPPORT)
		ret = dmub_abm_save_restore(dc, panel_inst, pData);

	return ret;
}

static bool dmub_abm_set_pipe_ex(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst)
{
	bool ret = false;
@@ -155,6 +182,7 @@ static const struct abm_funcs abm_funcs = {
	.get_target_backlight = dmub_abm_get_target_backlight_ex,
	.init_abm_config = dmub_abm_init_config_ex,
	.set_abm_pause = dmub_abm_set_pause_ex,
	.save_restore = dmub_abm_save_restore_ex,
	.set_pipe_ex = dmub_abm_set_pipe_ex,
	.set_backlight_level_pwm = dmub_abm_set_backlight_level_pwm_ex,
};
+46 −0
Original line number Diff line number Diff line
@@ -208,6 +208,52 @@ bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, un
	return true;
}


/*****************************************************************************
 *  dmub_abm_save_restore() - dmub interface for abm save+pause and restore+
 *                           un-pause
 *  @dc: dc context
 *  @panel_inst: panel instance index
 *  @pData: contains command to pause/un-pause abm and exchange abm parameters
 *
 *  When called Pause will get abm data and store in pData, and un-pause will
 *  set/apply abm data stored in pData.
 *
 *****************************************************************************/
bool dmub_abm_save_restore(
		struct dc_context *dc,
		unsigned int panel_inst,
		struct abm_save_restore *pData)
{
	union dmub_rb_cmd cmd;
	uint8_t panel_mask = 0x01 << panel_inst;
	unsigned int bytes = sizeof(struct abm_save_restore);

	// TODO: Optimize by only reading back final 4 bytes
	dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb);

	// Copy iramtable into cw7
	memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)pData, bytes);

	memset(&cmd, 0, sizeof(cmd));
	cmd.abm_save_restore.header.type = DMUB_CMD__ABM;
	cmd.abm_save_restore.header.sub_type = DMUB_CMD__ABM_SAVE_RESTORE;

	cmd.abm_save_restore.abm_init_config_data.src.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr;
	cmd.abm_save_restore.abm_init_config_data.bytes = bytes;
	cmd.abm_save_restore.abm_init_config_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
	cmd.abm_save_restore.abm_init_config_data.panel_mask = panel_mask;

	cmd.abm_save_restore.header.payload_bytes = sizeof(struct dmub_rb_cmd_abm_save_restore);

	dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);

	// Copy iramtable data into local structure
	memcpy((void *)pData, dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, bytes);

	return true;
}

bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst)
{
	union dmub_rb_cmd cmd;
+6 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@

#include "abm.h"

struct abm_save_restore;

void dmub_abm_init(struct abm *abm, uint32_t backlight);
bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask);
unsigned int dmub_abm_get_current_backlight(struct abm *abm);
@@ -38,6 +40,10 @@ void dmub_abm_init_config(struct abm *abm,
	unsigned int inst);

bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst);
bool dmub_abm_save_restore(
		struct dc_context *dc,
		unsigned int panel_inst,
		struct abm_save_restore *pData);
bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst);
bool dmub_abm_set_backlight_level(struct abm *abm,
		unsigned int backlight_pwm_u16_16,
Loading