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

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
......@@ -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;
}
......@@ -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,
......
......@@ -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,
};
......
......@@ -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;
......
......@@ -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,
......
......@@ -27,6 +27,8 @@
#include "dm_services_types.h"
struct abm_save_restore;
struct abm {
struct dc_context *ctx;
const struct abm_funcs *funcs;
......@@ -55,6 +57,10 @@ struct abm_funcs {
unsigned int bytes,
unsigned int inst);
bool (*set_abm_pause)(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int otg_inst);
bool (*save_restore)(
struct abm *abm,
unsigned int panel_inst,
struct abm_save_restore *pData);
bool (*set_pipe_ex)(struct abm *abm,
unsigned int otg_inst,
unsigned int option,
......
......@@ -144,6 +144,96 @@
#define PHYSICAL_ADDRESS_LOC union large_integer
#endif
#define ABM_NUM_OF_ACE_SEGMENTS 5
union abm_flags {
struct {
/**
* @abm_enabled: indicates if abm is enabled.
*/
unsigned int abm_enabled : 1;
/**
* @disable_abm_requested: indicates if driver has requested abm to be disabled.
*/
unsigned int disable_abm_requested : 1;
/**
* @disable_abm_immediately: indicates if driver has requested abm to be disabled immediately.
*/
unsigned int disable_abm_immediately : 1;
/**
* @disable_abm_immediate_keep_gain: indicates if driver has requested abm
* to be disabled immediately and keep gain.
*/
unsigned int disable_abm_immediate_keep_gain : 1;
/**
* @fractional_pwm: indicates if fractional duty cycle for backlight pwm is enabled.
*/
unsigned int fractional_pwm : 1;
/**
* @abm_gradual_bl_change: indicates if algorithm has completed gradual adjustment
* of user backlight level.
*/
unsigned int abm_gradual_bl_change : 1;
} bitfields;
unsigned int u32all;
};
struct abm_save_restore {
/**
* @flags: Misc. ABM flags.
*/
union abm_flags flags;
/**
* @pause: true: pause ABM and get state
* false: un-pause ABM after setting state
*/
uint32_t pause;
/**
* @next_ace_slope: Next ACE slopes to be programmed in HW (u3.13)
*/
uint32_t next_ace_slope[ABM_NUM_OF_ACE_SEGMENTS];
/**
* @next_ace_thresh: Next ACE thresholds to be programmed in HW (u10.6)
*/
uint32_t next_ace_thresh[ABM_NUM_OF_ACE_SEGMENTS];
/**
* @next_ace_offset: Next ACE offsets to be programmed in HW (u10.6)
*/
uint32_t next_ace_offset[ABM_NUM_OF_ACE_SEGMENTS];
/**
* @knee_threshold: Current x-position of ACE knee (u0.16).
*/
uint32_t knee_threshold;
/**
* @current_gain: Current backlight reduction (u16.16).
*/
uint32_t current_gain;
/**
* @curr_bl_level: Current actual backlight level converging to target backlight level.
*/
uint16_t curr_bl_level;
/**
* @curr_user_bl_level: Current nominal backlight level converging to level requested by user.
*/
uint16_t curr_user_bl_level;
};
/**
* OS/FW agnostic memcpy
*/
......@@ -2672,6 +2762,12 @@ enum dmub_cmd_abm_type {
* unregister vertical interrupt after steady state is reached
*/
DMUB_CMD__ABM_PAUSE = 6,
/**
* * Save and Restore ABM state. On save we save parameters, and
* on restore we update state with passed in data.
*/
DMUB_CMD__ABM_SAVE_RESTORE = 7,
};
/**
......@@ -3071,6 +3167,36 @@ struct dmub_rb_cmd_abm_pause {
struct dmub_cmd_abm_pause_data abm_pause_data;
};
/**
* Definition of a DMUB_CMD__ABM_SAVE_RESTORE command.
*/
struct dmub_rb_cmd_abm_save_restore {
/**
* Command header.
*/
struct dmub_cmd_header header;
/**
* OTG hw instance
*/
uint8_t otg_inst;
/**
* Enable or disable ABM pause
*/
uint8_t freeze;
/**
* Explicit padding to 4 byte boundary.
*/
uint8_t debug;
/**
* Data passed from driver to FW in a DMUB_CMD__ABM_INIT_CONFIG command.
*/
struct dmub_cmd_abm_init_config_data abm_init_config_data;
};
/**
* Data passed from driver to FW in a DMUB_CMD__QUERY_FEATURE_CAPS command.
*/
......@@ -3508,6 +3634,11 @@ union dmub_rb_cmd {
*/
struct dmub_rb_cmd_abm_pause abm_pause;
/**
* Definition of a DMUB_CMD__ABM_SAVE_RESTORE command.
*/
struct dmub_rb_cmd_abm_save_restore abm_save_restore;
/**
* Definition of a DMUB_CMD__DP_AUX_ACCESS command.
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment