/*
* Copyright 2016-2023 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "dm_services.h"
#include "dc.h"
#include "mod_freesync.h"
#include "core_types.h"
#define MOD_FREESYNC_MAX_CONCURRENT_STREAMS 32
#define MIN_REFRESH_RANGE 10
/* Refresh rate ramp at a fixed rate of 65 Hz/second */
#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
/* Number of elements in the render times cache array */
#define RENDER_TIMES_MAX_COUNT 10
/* Threshold to exit/exit BTR (to avoid frequent enter-exits at the lower limit) */
#define BTR_MAX_MARGIN 2500
/* Threshold to change BTR multiplier (to avoid frequent changes) */
#define BTR_DRIFT_MARGIN 2000
/* Threshold to exit fixed refresh rate */
#define FIXED_REFRESH_EXIT_MARGIN_IN_HZ 1
/* Number of consecutive frames to check before entering/exiting fixed refresh */
#define FIXED_REFRESH_ENTER_FRAME_COUNT 5
#define FIXED_REFRESH_EXIT_FRAME_COUNT 10
/* Flip interval workaround constants */
#define VSYNCS_BETWEEN_FLIP_THRESHOLD 2
#define FREESYNC_CONSEC_FLIP_AFTER_VSYNC 5
#define FREESYNC_VSYNC_TO_FLIP_DELTA_IN_US 500
struct core_freesync {
struct mod_freesync public;
struct dc *dc;
};
#define MOD_FREESYNC_TO_CORE(mod_freesync)\
container_of(mod_freesync, struct core_freesync, public)
struct mod_freesync *mod_freesync_create(struct dc *dc)
{
struct core_freesync *core_freesync =
kzalloc(sizeof(struct core_freesync), GFP_KERNEL);
if (core_freesync == NULL)
goto fail_alloc_context;
if (dc == NULL)
goto fail_construct;
core_freesync->dc = dc;
return &core_freesync->public;
fail_construct:
kfree(core_freesync);
fail_alloc_context:
return NULL;
}
void mod_freesync_destroy(struct mod_freesync *mod_freesync)
{
struct core_freesync *core_freesync = NULL;
if (mod_freesync == NULL)
return;
core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
kfree(core_freesync);
}
#if 0 /* Unused currently */
static unsigned int calc_refresh_in_uhz_from_duration(
unsigned int duration_in_ns)
{
unsigned int refresh_in_uhz =
((unsigned int)(div64_u64((1000000000ULL * 1000000),
duration_in_ns)));
return refresh_in_uhz;
}
#endif
static unsigned int calc_duration_in_us_from_refresh_in_uhz(
unsigned int refresh_in_uhz)
{
unsigned int duration_in_us =
((unsigned int)(div64_u64((1000000000ULL * 1000),
refresh_in_uhz)));
return duration_in