mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 04:23:35 +02:00
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: Harry Vanzylldejong <harry.vanzylldejong@amd.com> Acked-by: Alan Liu <haoping.liu@amd.com> Signed-off-by: Reza Amini <reza.amini@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
085f7bd955
commit
da915efaa2
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user