|
@@ -33,7 +33,7 @@
|
|
/* Refresh rate ramp at a fixed rate of 65 Hz/second */
|
|
/* Refresh rate ramp at a fixed rate of 65 Hz/second */
|
|
#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
|
|
#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
|
|
/* Number of elements in the render times cache array */
|
|
/* Number of elements in the render times cache array */
|
|
-#define RENDER_TIMES_MAX_COUNT 20
|
|
|
|
|
|
+#define RENDER_TIMES_MAX_COUNT 10
|
|
/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */
|
|
/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */
|
|
#define BTR_EXIT_MARGIN 2000
|
|
#define BTR_EXIT_MARGIN 2000
|
|
/* Number of consecutive frames to check before entering/exiting fixed refresh*/
|
|
/* Number of consecutive frames to check before entering/exiting fixed refresh*/
|
|
@@ -52,7 +52,7 @@ struct gradual_static_ramp {
|
|
unsigned int ramp_current_frame_duration_in_ns;
|
|
unsigned int ramp_current_frame_duration_in_ns;
|
|
};
|
|
};
|
|
|
|
|
|
-struct time_cache {
|
|
|
|
|
|
+struct freesync_time {
|
|
/* video (48Hz feature) related */
|
|
/* video (48Hz feature) related */
|
|
unsigned int update_duration_in_ns;
|
|
unsigned int update_duration_in_ns;
|
|
|
|
|
|
@@ -64,6 +64,9 @@ struct time_cache {
|
|
|
|
|
|
unsigned int render_times_index;
|
|
unsigned int render_times_index;
|
|
unsigned int render_times[RENDER_TIMES_MAX_COUNT];
|
|
unsigned int render_times[RENDER_TIMES_MAX_COUNT];
|
|
|
|
+
|
|
|
|
+ unsigned int min_window;
|
|
|
|
+ unsigned int max_window;
|
|
};
|
|
};
|
|
|
|
|
|
struct below_the_range {
|
|
struct below_the_range {
|
|
@@ -98,11 +101,14 @@ struct freesync_state {
|
|
bool static_screen;
|
|
bool static_screen;
|
|
bool video;
|
|
bool video;
|
|
|
|
|
|
|
|
+ unsigned int vmin;
|
|
|
|
+ unsigned int vmax;
|
|
|
|
+
|
|
|
|
+ struct freesync_time time;
|
|
|
|
+
|
|
unsigned int nominal_refresh_rate_in_micro_hz;
|
|
unsigned int nominal_refresh_rate_in_micro_hz;
|
|
bool windowed_fullscreen;
|
|
bool windowed_fullscreen;
|
|
|
|
|
|
- struct time_cache time;
|
|
|
|
-
|
|
|
|
struct gradual_static_ramp static_ramp;
|
|
struct gradual_static_ramp static_ramp;
|
|
struct below_the_range btr;
|
|
struct below_the_range btr;
|
|
struct fixed_refresh fixed_refresh;
|
|
struct fixed_refresh fixed_refresh;
|
|
@@ -124,9 +130,9 @@ struct freesync_registry_options {
|
|
struct core_freesync {
|
|
struct core_freesync {
|
|
struct mod_freesync public;
|
|
struct mod_freesync public;
|
|
struct dc *dc;
|
|
struct dc *dc;
|
|
|
|
+ struct freesync_registry_options opts;
|
|
struct freesync_entity *map;
|
|
struct freesync_entity *map;
|
|
int num_entities;
|
|
int num_entities;
|
|
- struct freesync_registry_options opts;
|
|
|
|
};
|
|
};
|
|
|
|
|
|
#define MOD_FREESYNC_TO_CORE(mod_freesync)\
|
|
#define MOD_FREESYNC_TO_CORE(mod_freesync)\
|
|
@@ -146,7 +152,7 @@ struct mod_freesync *mod_freesync_create(struct dc *dc)
|
|
goto fail_alloc_context;
|
|
goto fail_alloc_context;
|
|
|
|
|
|
core_freesync->map = kzalloc(sizeof(struct freesync_entity) * MOD_FREESYNC_MAX_CONCURRENT_STREAMS,
|
|
core_freesync->map = kzalloc(sizeof(struct freesync_entity) * MOD_FREESYNC_MAX_CONCURRENT_STREAMS,
|
|
- GFP_KERNEL);
|
|
|
|
|
|
+ GFP_KERNEL);
|
|
|
|
|
|
if (core_freesync->map == NULL)
|
|
if (core_freesync->map == NULL)
|
|
goto fail_alloc_map;
|
|
goto fail_alloc_map;
|
|
@@ -330,6 +336,25 @@ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync,
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void adjust_vmin_vmax(struct core_freesync *core_freesync,
|
|
|
|
+ struct dc_stream_state **streams,
|
|
|
|
+ int num_streams,
|
|
|
|
+ int map_index,
|
|
|
|
+ unsigned int v_total_min,
|
|
|
|
+ unsigned int v_total_max)
|
|
|
|
+{
|
|
|
|
+ if (num_streams == 0 || streams == NULL || num_streams > 1)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ core_freesync->map[map_index].state.vmin = v_total_min;
|
|
|
|
+ core_freesync->map[map_index].state.vmax = v_total_max;
|
|
|
|
+
|
|
|
|
+ dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
|
|
|
|
+ num_streams, v_total_min,
|
|
|
|
+ v_total_max);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
static void update_stream_freesync_context(struct core_freesync *core_freesync,
|
|
static void update_stream_freesync_context(struct core_freesync *core_freesync,
|
|
struct dc_stream_state *stream)
|
|
struct dc_stream_state *stream)
|
|
{
|
|
{
|
|
@@ -588,9 +613,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
|
|
update_stream_freesync_context(core_freesync,
|
|
update_stream_freesync_context(core_freesync,
|
|
streams[stream_idx]);
|
|
streams[stream_idx]);
|
|
|
|
|
|
- dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
|
|
|
|
- num_streams, v_total_min,
|
|
|
|
- v_total_max);
|
|
|
|
|
|
+ adjust_vmin_vmax(core_freesync, streams,
|
|
|
|
+ num_streams, map_index,
|
|
|
|
+ v_total_min,
|
|
|
|
+ v_total_max);
|
|
|
|
|
|
return true;
|
|
return true;
|
|
|
|
|
|
@@ -613,9 +639,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
|
|
core_freesync,
|
|
core_freesync,
|
|
streams[stream_idx]);
|
|
streams[stream_idx]);
|
|
|
|
|
|
- dc_stream_adjust_vmin_vmax(
|
|
|
|
- core_freesync->dc, streams,
|
|
|
|
- num_streams, v_total_nominal,
|
|
|
|
|
|
+ adjust_vmin_vmax(
|
|
|
|
+ core_freesync, streams,
|
|
|
|
+ num_streams, map_index,
|
|
|
|
+ v_total_nominal,
|
|
v_total_nominal);
|
|
v_total_nominal);
|
|
}
|
|
}
|
|
return true;
|
|
return true;
|
|
@@ -632,9 +659,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
|
|
core_freesync,
|
|
core_freesync,
|
|
streams[stream_idx]);
|
|
streams[stream_idx]);
|
|
|
|
|
|
- dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
|
|
|
|
- num_streams, v_total_nominal,
|
|
|
|
- v_total_nominal);
|
|
|
|
|
|
+ adjust_vmin_vmax(core_freesync, streams,
|
|
|
|
+ num_streams, map_index,
|
|
|
|
+ v_total_nominal,
|
|
|
|
+ v_total_nominal);
|
|
|
|
|
|
/* Reset the cached variables */
|
|
/* Reset the cached variables */
|
|
reset_freesync_state_variables(state);
|
|
reset_freesync_state_variables(state);
|
|
@@ -650,9 +678,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
|
|
* not support freesync because a former stream has
|
|
* not support freesync because a former stream has
|
|
* be programmed
|
|
* be programmed
|
|
*/
|
|
*/
|
|
- dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
|
|
|
|
- num_streams, v_total_nominal,
|
|
|
|
- v_total_nominal);
|
|
|
|
|
|
+ adjust_vmin_vmax(core_freesync, streams,
|
|
|
|
+ num_streams, map_index,
|
|
|
|
+ v_total_nominal,
|
|
|
|
+ v_total_nominal);
|
|
/* Reset the cached variables */
|
|
/* Reset the cached variables */
|
|
reset_freesync_state_variables(state);
|
|
reset_freesync_state_variables(state);
|
|
}
|
|
}
|
|
@@ -769,8 +798,9 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
|
|
vmin = inserted_frame_v_total;
|
|
vmin = inserted_frame_v_total;
|
|
|
|
|
|
/* Program V_TOTAL */
|
|
/* Program V_TOTAL */
|
|
- dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
|
|
|
|
- num_streams, vmin, vmax);
|
|
|
|
|
|
+ adjust_vmin_vmax(core_freesync, streams,
|
|
|
|
+ num_streams, index,
|
|
|
|
+ vmin, vmax);
|
|
}
|
|
}
|
|
|
|
|
|
if (state->btr.frame_counter > 0)
|
|
if (state->btr.frame_counter > 0)
|
|
@@ -804,9 +834,10 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
|
|
update_stream_freesync_context(core_freesync, streams[0]);
|
|
update_stream_freesync_context(core_freesync, streams[0]);
|
|
|
|
|
|
/* Program static screen ramp values */
|
|
/* Program static screen ramp values */
|
|
- dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
|
|
|
|
- num_streams, v_total,
|
|
|
|
- v_total);
|
|
|
|
|
|
+ adjust_vmin_vmax(core_freesync, streams,
|
|
|
|
+ num_streams, index,
|
|
|
|
+ v_total,
|
|
|
|
+ v_total);
|
|
|
|
|
|
triggers.overlay_update = true;
|
|
triggers.overlay_update = true;
|
|
triggers.surface_update = true;
|
|
triggers.surface_update = true;
|
|
@@ -1063,9 +1094,9 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync,
|
|
max_refresh);
|
|
max_refresh);
|
|
|
|
|
|
/* Program vtotal min/max */
|
|
/* Program vtotal min/max */
|
|
- dc_stream_adjust_vmin_vmax(core_freesync->dc, &streams, 1,
|
|
|
|
- state->freesync_range.vmin,
|
|
|
|
- state->freesync_range.vmax);
|
|
|
|
|
|
+ adjust_vmin_vmax(core_freesync, &streams, 1, index,
|
|
|
|
+ state->freesync_range.vmin,
|
|
|
|
+ state->freesync_range.vmax);
|
|
}
|
|
}
|
|
|
|
|
|
if (min_refresh != 0 &&
|
|
if (min_refresh != 0 &&
|
|
@@ -1399,11 +1430,9 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync,
|
|
} else {
|
|
} else {
|
|
|
|
|
|
vmin = state->freesync_range.vmin;
|
|
vmin = state->freesync_range.vmin;
|
|
-
|
|
|
|
vmax = vmin;
|
|
vmax = vmin;
|
|
-
|
|
|
|
- dc_stream_adjust_vmin_vmax(core_freesync->dc, &stream,
|
|
|
|
- 1, vmin, vmax);
|
|
|
|
|
|
+ adjust_vmin_vmax(core_freesync, &stream, map_index,
|
|
|
|
+ 1, vmin, vmax);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1457,3 +1486,43 @@ void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync,
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+void mod_freesync_get_settings(struct mod_freesync *mod_freesync,
|
|
|
|
+ struct dc_stream_state **streams, int num_streams,
|
|
|
|
+ unsigned int *v_total_min, unsigned int *v_total_max,
|
|
|
|
+ unsigned int *event_triggers,
|
|
|
|
+ unsigned int *window_min, unsigned int *window_max,
|
|
|
|
+ unsigned int *lfc_mid_point_in_us,
|
|
|
|
+ unsigned int *inserted_frames,
|
|
|
|
+ unsigned int *inserted_duration_in_us)
|
|
|
|
+{
|
|
|
|
+ unsigned int stream_index, map_index;
|
|
|
|
+ struct core_freesync *core_freesync = NULL;
|
|
|
|
+
|
|
|
|
+ if (mod_freesync == NULL)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
|
|
|
|
+
|
|
|
|
+ for (stream_index = 0; stream_index < num_streams; stream_index++) {
|
|
|
|
+
|
|
|
|
+ map_index = map_index_from_stream(core_freesync,
|
|
|
|
+ streams[stream_index]);
|
|
|
|
+
|
|
|
|
+ if (core_freesync->map[map_index].caps->supported) {
|
|
|
|
+ struct freesync_state state =
|
|
|
|
+ core_freesync->map[map_index].state;
|
|
|
|
+ *v_total_min = state.vmin;
|
|
|
|
+ *v_total_max = state.vmax;
|
|
|
|
+ *event_triggers = 0;
|
|
|
|
+ *window_min = state.time.min_window;
|
|
|
|
+ *window_max = state.time.max_window;
|
|
|
|
+ *lfc_mid_point_in_us = state.btr.mid_point_in_us;
|
|
|
|
+ *inserted_frames = state.btr.frames_to_insert;
|
|
|
|
+ *inserted_duration_in_us =
|
|
|
|
+ state.btr.inserted_frame_duration_in_us;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|