aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-03-20 21:46:05 -0400
committerDave Airlie <airlied@redhat.com>2018-03-20 21:46:05 -0400
commit287d2ac36b6f2830ea4ef66c110abc0f47a9a658 (patch)
tree04214f156461a95c2f7ca5a8821063cad7fc515e /drivers/gpu/drm/amd/display/modules/freesync/freesync.c
parent963976cfe9c54d4d9e725e61c90c47a4af6b5ea2 (diff)
parent6da2b9332c572fcda94de9631f8fa514f574388a (diff)
Merge branch 'drm-next-4.17' of git://people.freedesktop.org/~agd5f/linux into drm-next
- Continued cleanup and restructuring of powerplay - Fetch VRAM type from vbios rather than hardcoding for SOC15 asics - Allow ttm to drop its backing store when drivers don't need it - DC bandwidth calc updates - Enable DC backlight control pre-DCE11 asics - Enable DC on all supported asics - DC Fixes for planes due to the way our hw is ordered vs what drm expects - DC CTM/regamma fixes - Misc cleanup and bug fixes * 'drm-next-4.17' of git://people.freedesktop.org/~agd5f/linux: (89 commits) amdgpu/dm: Default PRE_VEGA ASIC support to 'y' drm/amd/pp: Remove the cgs wrapper for notify smu version on APU drm/amd/display: fix dereferencing possible ERR_PTR() drm/amd/display: Refine disable VGA drm/amdgpu: Improve documentation of bo_ptr in amdgpu_bo_create_kernel drm/radeon: Don't turn off DP sink when disconnected drm/amd/pp: Rename file name cz_* to smu8_* drm/amd/pp: Replace function/struct name cz_* with smu8_* drm/amd/pp: Remove unneeded void * casts in cz_hwmgr.c/cz_smumgr.c drm/amd/pp: Mv cz uvd/vce pg/dpm functions to cz_hwmgr.c drm/amd/pp: Remove dead header file pp_asicblocks.h drm/amd/pp: Delete dead code on cz_clockpowergating.c drm/amdgpu: Call amdgpu_ucode_fini_bo in amd_powerplay.c drm/amdgpu: Remove wrapper layer of smu ip functions drm/amdgpu: Don't compared ip_block_type with ip_block_index drm/amdgpu: Plus NULL function pointer check drm/amd/pp: Move helper functions to smu_help.c drm/amd/pp: Replace rv_* with smu10_* drm/amd/pp: Fix function parameter not correct drm/amd/pp: Add rv_copy_table_from/to_smc to smu backend function table ...
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules/freesync/freesync.c')
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c155
1 files changed, 125 insertions, 30 deletions
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index b4723af368a5..27d4003aa2c7 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -33,7 +33,7 @@
33/* Refresh rate ramp at a fixed rate of 65 Hz/second */ 33/* Refresh rate ramp at a fixed rate of 65 Hz/second */
34#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65) 34#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
35/* Number of elements in the render times cache array */ 35/* Number of elements in the render times cache array */
36#define RENDER_TIMES_MAX_COUNT 20 36#define RENDER_TIMES_MAX_COUNT 10
37/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */ 37/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */
38#define BTR_EXIT_MARGIN 2000 38#define BTR_EXIT_MARGIN 2000
39/* Number of consecutive frames to check before entering/exiting fixed refresh*/ 39/* Number of consecutive frames to check before entering/exiting fixed refresh*/
@@ -46,13 +46,15 @@
46 46
47#define FREESYNC_NO_STATIC_FOR_INTERNAL_REGKEY "DalFreeSyncNoStaticForInternal" 47#define FREESYNC_NO_STATIC_FOR_INTERNAL_REGKEY "DalFreeSyncNoStaticForInternal"
48 48
49#define FREESYNC_DEFAULT_REGKEY "LCDFreeSyncDefault"
50
49struct gradual_static_ramp { 51struct gradual_static_ramp {
50 bool ramp_is_active; 52 bool ramp_is_active;
51 bool ramp_direction_is_up; 53 bool ramp_direction_is_up;
52 unsigned int ramp_current_frame_duration_in_ns; 54 unsigned int ramp_current_frame_duration_in_ns;
53}; 55};
54 56
55struct time_cache { 57struct freesync_time {
56 /* video (48Hz feature) related */ 58 /* video (48Hz feature) related */
57 unsigned int update_duration_in_ns; 59 unsigned int update_duration_in_ns;
58 60
@@ -64,6 +66,9 @@ struct time_cache {
64 66
65 unsigned int render_times_index; 67 unsigned int render_times_index;
66 unsigned int render_times[RENDER_TIMES_MAX_COUNT]; 68 unsigned int render_times[RENDER_TIMES_MAX_COUNT];
69
70 unsigned int min_window;
71 unsigned int max_window;
67}; 72};
68 73
69struct below_the_range { 74struct below_the_range {
@@ -98,11 +103,14 @@ struct freesync_state {
98 bool static_screen; 103 bool static_screen;
99 bool video; 104 bool video;
100 105
106 unsigned int vmin;
107 unsigned int vmax;
108
109 struct freesync_time time;
110
101 unsigned int nominal_refresh_rate_in_micro_hz; 111 unsigned int nominal_refresh_rate_in_micro_hz;
102 bool windowed_fullscreen; 112 bool windowed_fullscreen;
103 113
104 struct time_cache time;
105
106 struct gradual_static_ramp static_ramp; 114 struct gradual_static_ramp static_ramp;
107 struct below_the_range btr; 115 struct below_the_range btr;
108 struct fixed_refresh fixed_refresh; 116 struct fixed_refresh fixed_refresh;
@@ -119,14 +127,16 @@ struct freesync_entity {
119struct freesync_registry_options { 127struct freesync_registry_options {
120 bool drr_external_supported; 128 bool drr_external_supported;
121 bool drr_internal_supported; 129 bool drr_internal_supported;
130 bool lcd_freesync_default_set;
131 int lcd_freesync_default_value;
122}; 132};
123 133
124struct core_freesync { 134struct core_freesync {
125 struct mod_freesync public; 135 struct mod_freesync public;
126 struct dc *dc; 136 struct dc *dc;
137 struct freesync_registry_options opts;
127 struct freesync_entity *map; 138 struct freesync_entity *map;
128 int num_entities; 139 int num_entities;
129 struct freesync_registry_options opts;
130}; 140};
131 141
132#define MOD_FREESYNC_TO_CORE(mod_freesync)\ 142#define MOD_FREESYNC_TO_CORE(mod_freesync)\
@@ -146,7 +156,7 @@ struct mod_freesync *mod_freesync_create(struct dc *dc)
146 goto fail_alloc_context; 156 goto fail_alloc_context;
147 157
148 core_freesync->map = kzalloc(sizeof(struct freesync_entity) * MOD_FREESYNC_MAX_CONCURRENT_STREAMS, 158 core_freesync->map = kzalloc(sizeof(struct freesync_entity) * MOD_FREESYNC_MAX_CONCURRENT_STREAMS,
149 GFP_KERNEL); 159 GFP_KERNEL);
150 160
151 if (core_freesync->map == NULL) 161 if (core_freesync->map == NULL)
152 goto fail_alloc_map; 162 goto fail_alloc_map;
@@ -183,6 +193,16 @@ struct mod_freesync *mod_freesync_create(struct dc *dc)
183 (data & 1) ? false : true; 193 (data & 1) ? false : true;
184 } 194 }
185 195
196 if (dm_read_persistent_data(dc->ctx, NULL, NULL,
197 FREESYNC_DEFAULT_REGKEY,
198 &data, sizeof(data), &flag)) {
199 core_freesync->opts.lcd_freesync_default_set = true;
200 core_freesync->opts.lcd_freesync_default_value = data;
201 } else {
202 core_freesync->opts.lcd_freesync_default_set = false;
203 core_freesync->opts.lcd_freesync_default_value = 0;
204 }
205
186 return &core_freesync->public; 206 return &core_freesync->public;
187 207
188fail_construct: 208fail_construct:
@@ -288,6 +308,18 @@ bool mod_freesync_add_stream(struct mod_freesync *mod_freesync,
288 core_freesync->map[core_freesync->num_entities].user_enable. 308 core_freesync->map[core_freesync->num_entities].user_enable.
289 enable_for_video = 309 enable_for_video =
290 (persistent_freesync_enable & 4) ? true : false; 310 (persistent_freesync_enable & 4) ? true : false;
311 /* If FreeSync display and LCDFreeSyncDefault is set, use as default values write back to userenable */
312 } else if (caps->supported && (core_freesync->opts.lcd_freesync_default_set)) {
313 core_freesync->map[core_freesync->num_entities].user_enable.enable_for_gaming =
314 (core_freesync->opts.lcd_freesync_default_value & 1) ? true : false;
315 core_freesync->map[core_freesync->num_entities].user_enable.enable_for_static =
316 (core_freesync->opts.lcd_freesync_default_value & 2) ? true : false;
317 core_freesync->map[core_freesync->num_entities].user_enable.enable_for_video =
318 (core_freesync->opts.lcd_freesync_default_value & 4) ? true : false;
319 dm_write_persistent_data(dc->ctx, stream->sink,
320 FREESYNC_REGISTRY_NAME,
321 "userenable", &core_freesync->opts.lcd_freesync_default_value,
322 sizeof(int), &flag);
291 } else { 323 } else {
292 core_freesync->map[core_freesync->num_entities].user_enable. 324 core_freesync->map[core_freesync->num_entities].user_enable.
293 enable_for_gaming = false; 325 enable_for_gaming = false;
@@ -330,6 +362,25 @@ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync,
330 return true; 362 return true;
331} 363}
332 364
365static void adjust_vmin_vmax(struct core_freesync *core_freesync,
366 struct dc_stream_state **streams,
367 int num_streams,
368 int map_index,
369 unsigned int v_total_min,
370 unsigned int v_total_max)
371{
372 if (num_streams == 0 || streams == NULL || num_streams > 1)
373 return;
374
375 core_freesync->map[map_index].state.vmin = v_total_min;
376 core_freesync->map[map_index].state.vmax = v_total_max;
377
378 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
379 num_streams, v_total_min,
380 v_total_max);
381}
382
383
333static void update_stream_freesync_context(struct core_freesync *core_freesync, 384static void update_stream_freesync_context(struct core_freesync *core_freesync,
334 struct dc_stream_state *stream) 385 struct dc_stream_state *stream)
335{ 386{
@@ -588,9 +639,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
588 update_stream_freesync_context(core_freesync, 639 update_stream_freesync_context(core_freesync,
589 streams[stream_idx]); 640 streams[stream_idx]);
590 641
591 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams, 642 adjust_vmin_vmax(core_freesync, streams,
592 num_streams, v_total_min, 643 num_streams, map_index,
593 v_total_max); 644 v_total_min,
645 v_total_max);
594 646
595 return true; 647 return true;
596 648
@@ -613,9 +665,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
613 core_freesync, 665 core_freesync,
614 streams[stream_idx]); 666 streams[stream_idx]);
615 667
616 dc_stream_adjust_vmin_vmax( 668 adjust_vmin_vmax(
617 core_freesync->dc, streams, 669 core_freesync, streams,
618 num_streams, v_total_nominal, 670 num_streams, map_index,
671 v_total_nominal,
619 v_total_nominal); 672 v_total_nominal);
620 } 673 }
621 return true; 674 return true;
@@ -632,9 +685,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
632 core_freesync, 685 core_freesync,
633 streams[stream_idx]); 686 streams[stream_idx]);
634 687
635 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams, 688 adjust_vmin_vmax(core_freesync, streams,
636 num_streams, v_total_nominal, 689 num_streams, map_index,
637 v_total_nominal); 690 v_total_nominal,
691 v_total_nominal);
638 692
639 /* Reset the cached variables */ 693 /* Reset the cached variables */
640 reset_freesync_state_variables(state); 694 reset_freesync_state_variables(state);
@@ -650,9 +704,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
650 * not support freesync because a former stream has 704 * not support freesync because a former stream has
651 * be programmed 705 * be programmed
652 */ 706 */
653 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams, 707 adjust_vmin_vmax(core_freesync, streams,
654 num_streams, v_total_nominal, 708 num_streams, map_index,
655 v_total_nominal); 709 v_total_nominal,
710 v_total_nominal);
656 /* Reset the cached variables */ 711 /* Reset the cached variables */
657 reset_freesync_state_variables(state); 712 reset_freesync_state_variables(state);
658 } 713 }
@@ -769,8 +824,9 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
769 vmin = inserted_frame_v_total; 824 vmin = inserted_frame_v_total;
770 825
771 /* Program V_TOTAL */ 826 /* Program V_TOTAL */
772 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams, 827 adjust_vmin_vmax(core_freesync, streams,
773 num_streams, vmin, vmax); 828 num_streams, index,
829 vmin, vmax);
774 } 830 }
775 831
776 if (state->btr.frame_counter > 0) 832 if (state->btr.frame_counter > 0)
@@ -804,9 +860,10 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
804 update_stream_freesync_context(core_freesync, streams[0]); 860 update_stream_freesync_context(core_freesync, streams[0]);
805 861
806 /* Program static screen ramp values */ 862 /* Program static screen ramp values */
807 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams, 863 adjust_vmin_vmax(core_freesync, streams,
808 num_streams, v_total, 864 num_streams, index,
809 v_total); 865 v_total,
866 v_total);
810 867
811 triggers.overlay_update = true; 868 triggers.overlay_update = true;
812 triggers.surface_update = true; 869 triggers.surface_update = true;
@@ -1063,9 +1120,9 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync,
1063 max_refresh); 1120 max_refresh);
1064 1121
1065 /* Program vtotal min/max */ 1122 /* Program vtotal min/max */
1066 dc_stream_adjust_vmin_vmax(core_freesync->dc, &streams, 1, 1123 adjust_vmin_vmax(core_freesync, &streams, 1, index,
1067 state->freesync_range.vmin, 1124 state->freesync_range.vmin,
1068 state->freesync_range.vmax); 1125 state->freesync_range.vmax);
1069 } 1126 }
1070 1127
1071 if (min_refresh != 0 && 1128 if (min_refresh != 0 &&
@@ -1399,11 +1456,9 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync,
1399 } else { 1456 } else {
1400 1457
1401 vmin = state->freesync_range.vmin; 1458 vmin = state->freesync_range.vmin;
1402
1403 vmax = vmin; 1459 vmax = vmin;
1404 1460 adjust_vmin_vmax(core_freesync, &stream, map_index,
1405 dc_stream_adjust_vmin_vmax(core_freesync->dc, &stream, 1461 1, vmin, vmax);
1406 1, vmin, vmax);
1407 } 1462 }
1408} 1463}
1409 1464
@@ -1457,3 +1512,43 @@ void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync,
1457 1512
1458 } 1513 }
1459} 1514}
1515
1516void mod_freesync_get_settings(struct mod_freesync *mod_freesync,
1517 struct dc_stream_state **streams, int num_streams,
1518 unsigned int *v_total_min, unsigned int *v_total_max,
1519 unsigned int *event_triggers,
1520 unsigned int *window_min, unsigned int *window_max,
1521 unsigned int *lfc_mid_point_in_us,
1522 unsigned int *inserted_frames,
1523 unsigned int *inserted_duration_in_us)
1524{
1525 unsigned int stream_index, map_index;
1526 struct core_freesync *core_freesync = NULL;
1527
1528 if (mod_freesync == NULL)
1529 return;
1530
1531 core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
1532
1533 for (stream_index = 0; stream_index < num_streams; stream_index++) {
1534
1535 map_index = map_index_from_stream(core_freesync,
1536 streams[stream_index]);
1537
1538 if (core_freesync->map[map_index].caps->supported) {
1539 struct freesync_state state =
1540 core_freesync->map[map_index].state;
1541 *v_total_min = state.vmin;
1542 *v_total_max = state.vmax;
1543 *event_triggers = 0;
1544 *window_min = state.time.min_window;
1545 *window_max = state.time.max_window;
1546 *lfc_mid_point_in_us = state.btr.mid_point_in_us;
1547 *inserted_frames = state.btr.frames_to_insert;
1548 *inserted_duration_in_us =
1549 state.btr.inserted_frame_duration_in_us;
1550 }
1551
1552 }
1553}
1554