aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/logger.c3
-rw-r--r--drivers/gpu/drm/amd/display/include/logger_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c129
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h9
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_stats.h65
-rw-r--r--drivers/gpu/drm/amd/display/modules/stats/stats.c334
6 files changed, 510 insertions, 31 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c
index 180a9d69d351..31bee054f43a 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/logger.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c
@@ -60,7 +60,8 @@ static const struct dc_log_type_info log_type_info_tbl[] = {
60 {LOG_EVENT_LINK_LOSS, "LinkLoss"}, 60 {LOG_EVENT_LINK_LOSS, "LinkLoss"},
61 {LOG_EVENT_UNDERFLOW, "Underflow"}, 61 {LOG_EVENT_UNDERFLOW, "Underflow"},
62 {LOG_IF_TRACE, "InterfaceTrace"}, 62 {LOG_IF_TRACE, "InterfaceTrace"},
63 {LOG_DTN, "DTN"} 63 {LOG_DTN, "DTN"},
64 {LOG_PROFILING, "Profiling"}
64}; 65};
65 66
66 67
diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h
index b727f5eeb3a9..427796bdc14a 100644
--- a/drivers/gpu/drm/amd/display/include/logger_types.h
+++ b/drivers/gpu/drm/amd/display/include/logger_types.h
@@ -98,6 +98,7 @@ enum dc_log_type {
98 LOG_EVENT_UNDERFLOW, 98 LOG_EVENT_UNDERFLOW,
99 LOG_IF_TRACE, 99 LOG_IF_TRACE,
100 LOG_PERF_TRACE, 100 LOG_PERF_TRACE,
101 LOG_PROFILING,
101 102
102 LOG_SECTION_TOTAL_COUNT 103 LOG_SECTION_TOTAL_COUNT
103}; 104};
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index b4723af368a5..e849b704f2f6 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*/
@@ -52,7 +52,7 @@ struct gradual_static_ramp {
52 unsigned int ramp_current_frame_duration_in_ns; 52 unsigned int ramp_current_frame_duration_in_ns;
53}; 53};
54 54
55struct time_cache { 55struct freesync_time {
56 /* video (48Hz feature) related */ 56 /* video (48Hz feature) related */
57 unsigned int update_duration_in_ns; 57 unsigned int update_duration_in_ns;
58 58
@@ -64,6 +64,9 @@ struct time_cache {
64 64
65 unsigned int render_times_index; 65 unsigned int render_times_index;
66 unsigned int render_times[RENDER_TIMES_MAX_COUNT]; 66 unsigned int render_times[RENDER_TIMES_MAX_COUNT];
67
68 unsigned int min_window;
69 unsigned int max_window;
67}; 70};
68 71
69struct below_the_range { 72struct below_the_range {
@@ -98,11 +101,14 @@ struct freesync_state {
98 bool static_screen; 101 bool static_screen;
99 bool video; 102 bool video;
100 103
104 unsigned int vmin;
105 unsigned int vmax;
106
107 struct freesync_time time;
108
101 unsigned int nominal_refresh_rate_in_micro_hz; 109 unsigned int nominal_refresh_rate_in_micro_hz;
102 bool windowed_fullscreen; 110 bool windowed_fullscreen;
103 111
104 struct time_cache time;
105
106 struct gradual_static_ramp static_ramp; 112 struct gradual_static_ramp static_ramp;
107 struct below_the_range btr; 113 struct below_the_range btr;
108 struct fixed_refresh fixed_refresh; 114 struct fixed_refresh fixed_refresh;
@@ -124,9 +130,9 @@ struct freesync_registry_options {
124struct core_freesync { 130struct core_freesync {
125 struct mod_freesync public; 131 struct mod_freesync public;
126 struct dc *dc; 132 struct dc *dc;
133 struct freesync_registry_options opts;
127 struct freesync_entity *map; 134 struct freesync_entity *map;
128 int num_entities; 135 int num_entities;
129 struct freesync_registry_options opts;
130}; 136};
131 137
132#define MOD_FREESYNC_TO_CORE(mod_freesync)\ 138#define MOD_FREESYNC_TO_CORE(mod_freesync)\
@@ -146,7 +152,7 @@ struct mod_freesync *mod_freesync_create(struct dc *dc)
146 goto fail_alloc_context; 152 goto fail_alloc_context;
147 153
148 core_freesync->map = kzalloc(sizeof(struct freesync_entity) * MOD_FREESYNC_MAX_CONCURRENT_STREAMS, 154 core_freesync->map = kzalloc(sizeof(struct freesync_entity) * MOD_FREESYNC_MAX_CONCURRENT_STREAMS,
149 GFP_KERNEL); 155 GFP_KERNEL);
150 156
151 if (core_freesync->map == NULL) 157 if (core_freesync->map == NULL)
152 goto fail_alloc_map; 158 goto fail_alloc_map;
@@ -330,6 +336,25 @@ bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync,
330 return true; 336 return true;
331} 337}
332 338
339static void adjust_vmin_vmax(struct core_freesync *core_freesync,
340 struct dc_stream_state **streams,
341 int num_streams,
342 int map_index,
343 unsigned int v_total_min,
344 unsigned int v_total_max)
345{
346 if (num_streams == 0 || streams == NULL || num_streams > 1)
347 return;
348
349 core_freesync->map[map_index].state.vmin = v_total_min;
350 core_freesync->map[map_index].state.vmax = v_total_max;
351
352 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams,
353 num_streams, v_total_min,
354 v_total_max);
355}
356
357
333static void update_stream_freesync_context(struct core_freesync *core_freesync, 358static void update_stream_freesync_context(struct core_freesync *core_freesync,
334 struct dc_stream_state *stream) 359 struct dc_stream_state *stream)
335{ 360{
@@ -588,9 +613,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
588 update_stream_freesync_context(core_freesync, 613 update_stream_freesync_context(core_freesync,
589 streams[stream_idx]); 614 streams[stream_idx]);
590 615
591 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams, 616 adjust_vmin_vmax(core_freesync, streams,
592 num_streams, v_total_min, 617 num_streams, map_index,
593 v_total_max); 618 v_total_min,
619 v_total_max);
594 620
595 return true; 621 return true;
596 622
@@ -613,9 +639,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
613 core_freesync, 639 core_freesync,
614 streams[stream_idx]); 640 streams[stream_idx]);
615 641
616 dc_stream_adjust_vmin_vmax( 642 adjust_vmin_vmax(
617 core_freesync->dc, streams, 643 core_freesync, streams,
618 num_streams, v_total_nominal, 644 num_streams, map_index,
645 v_total_nominal,
619 v_total_nominal); 646 v_total_nominal);
620 } 647 }
621 return true; 648 return true;
@@ -632,9 +659,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
632 core_freesync, 659 core_freesync,
633 streams[stream_idx]); 660 streams[stream_idx]);
634 661
635 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams, 662 adjust_vmin_vmax(core_freesync, streams,
636 num_streams, v_total_nominal, 663 num_streams, map_index,
637 v_total_nominal); 664 v_total_nominal,
665 v_total_nominal);
638 666
639 /* Reset the cached variables */ 667 /* Reset the cached variables */
640 reset_freesync_state_variables(state); 668 reset_freesync_state_variables(state);
@@ -650,9 +678,10 @@ static bool set_freesync_on_streams(struct core_freesync *core_freesync,
650 * not support freesync because a former stream has 678 * not support freesync because a former stream has
651 * be programmed 679 * be programmed
652 */ 680 */
653 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams, 681 adjust_vmin_vmax(core_freesync, streams,
654 num_streams, v_total_nominal, 682 num_streams, map_index,
655 v_total_nominal); 683 v_total_nominal,
684 v_total_nominal);
656 /* Reset the cached variables */ 685 /* Reset the cached variables */
657 reset_freesync_state_variables(state); 686 reset_freesync_state_variables(state);
658 } 687 }
@@ -769,8 +798,9 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
769 vmin = inserted_frame_v_total; 798 vmin = inserted_frame_v_total;
770 799
771 /* Program V_TOTAL */ 800 /* Program V_TOTAL */
772 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams, 801 adjust_vmin_vmax(core_freesync, streams,
773 num_streams, vmin, vmax); 802 num_streams, index,
803 vmin, vmax);
774 } 804 }
775 805
776 if (state->btr.frame_counter > 0) 806 if (state->btr.frame_counter > 0)
@@ -804,9 +834,10 @@ void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
804 update_stream_freesync_context(core_freesync, streams[0]); 834 update_stream_freesync_context(core_freesync, streams[0]);
805 835
806 /* Program static screen ramp values */ 836 /* Program static screen ramp values */
807 dc_stream_adjust_vmin_vmax(core_freesync->dc, streams, 837 adjust_vmin_vmax(core_freesync, streams,
808 num_streams, v_total, 838 num_streams, index,
809 v_total); 839 v_total,
840 v_total);
810 841
811 triggers.overlay_update = true; 842 triggers.overlay_update = true;
812 triggers.surface_update = true; 843 triggers.surface_update = true;
@@ -1063,9 +1094,9 @@ bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync,
1063 max_refresh); 1094 max_refresh);
1064 1095
1065 /* Program vtotal min/max */ 1096 /* Program vtotal min/max */
1066 dc_stream_adjust_vmin_vmax(core_freesync->dc, &streams, 1, 1097 adjust_vmin_vmax(core_freesync, &streams, 1, index,
1067 state->freesync_range.vmin, 1098 state->freesync_range.vmin,
1068 state->freesync_range.vmax); 1099 state->freesync_range.vmax);
1069 } 1100 }
1070 1101
1071 if (min_refresh != 0 && 1102 if (min_refresh != 0 &&
@@ -1399,11 +1430,9 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync,
1399 } else { 1430 } else {
1400 1431
1401 vmin = state->freesync_range.vmin; 1432 vmin = state->freesync_range.vmin;
1402
1403 vmax = vmin; 1433 vmax = vmin;
1404 1434 adjust_vmin_vmax(core_freesync, &stream, map_index,
1405 dc_stream_adjust_vmin_vmax(core_freesync->dc, &stream, 1435 1, vmin, vmax);
1406 1, vmin, vmax);
1407 } 1436 }
1408} 1437}
1409 1438
@@ -1457,3 +1486,43 @@ void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync,
1457 1486
1458 } 1487 }
1459} 1488}
1489
1490void mod_freesync_get_settings(struct mod_freesync *mod_freesync,
1491 struct dc_stream_state **streams, int num_streams,
1492 unsigned int *v_total_min, unsigned int *v_total_max,
1493 unsigned int *event_triggers,
1494 unsigned int *window_min, unsigned int *window_max,
1495 unsigned int *lfc_mid_point_in_us,
1496 unsigned int *inserted_frames,
1497 unsigned int *inserted_duration_in_us)
1498{
1499 unsigned int stream_index, map_index;
1500 struct core_freesync *core_freesync = NULL;
1501
1502 if (mod_freesync == NULL)
1503 return;
1504
1505 core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
1506
1507 for (stream_index = 0; stream_index < num_streams; stream_index++) {
1508
1509 map_index = map_index_from_stream(core_freesync,
1510 streams[stream_index]);
1511
1512 if (core_freesync->map[map_index].caps->supported) {
1513 struct freesync_state state =
1514 core_freesync->map[map_index].state;
1515 *v_total_min = state.vmin;
1516 *v_total_max = state.vmax;
1517 *event_triggers = 0;
1518 *window_min = state.time.min_window;
1519 *window_max = state.time.max_window;
1520 *lfc_mid_point_in_us = state.btr.mid_point_in_us;
1521 *inserted_frames = state.btr.frames_to_insert;
1522 *inserted_duration_in_us =
1523 state.btr.inserted_frame_duration_in_us;
1524 }
1525
1526 }
1527}
1528
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
index 84b53425f2c8..f083e1619dbe 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
@@ -164,4 +164,13 @@ void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync,
164 struct dc_stream_state **streams, int num_streams, 164 struct dc_stream_state **streams, int num_streams,
165 unsigned int curr_time_stamp); 165 unsigned int curr_time_stamp);
166 166
167void mod_freesync_get_settings(struct mod_freesync *mod_freesync,
168 struct dc_stream_state **streams, int num_streams,
169 unsigned int *v_total_min, unsigned int *v_total_max,
170 unsigned int *event_triggers,
171 unsigned int *window_min, unsigned int *window_max,
172 unsigned int *lfc_mid_point_in_us,
173 unsigned int *inserted_frames,
174 unsigned int *inserted_duration_in_us);
175
167#endif 176#endif
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h b/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h
new file mode 100644
index 000000000000..3230e2adb870
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h
@@ -0,0 +1,65 @@
1/*
2 * Copyright 2016 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26#ifndef MODULES_INC_MOD_STATS_H_
27#define MODULES_INC_MOD_STATS_H_
28
29#include "dm_services.h"
30
31struct mod_stats {
32 int dummy;
33};
34
35struct mod_stats_caps {
36 bool dummy;
37};
38
39struct mod_stats *mod_stats_create(struct dc *dc);
40
41void mod_stats_destroy(struct mod_stats *mod_stats);
42
43bool mod_stats_init(struct mod_stats *mod_stats);
44
45void mod_stats_dump(struct mod_stats *mod_stats);
46
47void mod_stats_reset_data(struct mod_stats *mod_stats);
48
49void mod_stats_update_flip(struct mod_stats *mod_stats,
50 unsigned long timestamp_in_ns);
51
52void mod_stats_update_vupdate(struct mod_stats *mod_stats,
53 unsigned long timestamp_in_ns);
54
55void mod_stats_update_freesync(struct mod_stats *mod_stats,
56 unsigned int v_total_min,
57 unsigned int v_total_max,
58 unsigned int event_triggers,
59 unsigned int window_min,
60 unsigned int window_max,
61 unsigned int lfc_mid_point_in_us,
62 unsigned int inserted_frames,
63 unsigned int inserted_frame_duration_in_us);
64
65#endif /* MODULES_INC_MOD_STATS_H_ */
diff --git a/drivers/gpu/drm/amd/display/modules/stats/stats.c b/drivers/gpu/drm/amd/display/modules/stats/stats.c
new file mode 100644
index 000000000000..041f87b73d5f
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/modules/stats/stats.c
@@ -0,0 +1,334 @@
1/*
2 * Copyright 2016 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26#include "mod_stats.h"
27#include "dm_services.h"
28#include "dc.h"
29#include "core_types.h"
30
31#define DAL_STATS_ENABLE_REGKEY "DalStatsEnable"
32#define DAL_STATS_ENABLE_REGKEY_DEFAULT 0x00000001
33#define DAL_STATS_ENABLE_REGKEY_ENABLED 0x00000001
34
35#define DAL_STATS_ENTRIES_REGKEY "DalStatsEntries"
36#define DAL_STATS_ENTRIES_REGKEY_DEFAULT 0x00350000
37#define DAL_STATS_ENTRIES_REGKEY_MAX 0x01000000
38
39#define MOD_STATS_NUM_VSYNCS 5
40
41struct stats_time_cache {
42 unsigned long flip_timestamp_in_ns;
43 unsigned long vupdate_timestamp_in_ns;
44
45 unsigned int render_time_in_us;
46 unsigned int avg_render_time_in_us_last_ten;
47 unsigned int v_sync_time_in_us[MOD_STATS_NUM_VSYNCS];
48 unsigned int num_vsync_between_flips;
49
50 unsigned int flip_to_vsync_time_in_us;
51 unsigned int vsync_to_flip_time_in_us;
52
53 unsigned int min_window;
54 unsigned int max_window;
55 unsigned int v_total_min;
56 unsigned int v_total_max;
57 unsigned int event_triggers;
58
59 unsigned int lfc_mid_point_in_us;
60 unsigned int num_frames_inserted;
61 unsigned int inserted_duration_in_us;
62
63 unsigned int flags;
64};
65
66struct core_stats {
67 struct mod_stats public;
68 struct dc *dc;
69
70 struct stats_time_cache *time;
71 unsigned int index;
72
73 bool enabled;
74 unsigned int entries;
75};
76
77#define MOD_STATS_TO_CORE(mod_stats)\
78 container_of(mod_stats, struct core_stats, public)
79
80bool mod_stats_init(struct mod_stats *mod_stats)
81{
82 bool result = false;
83 struct core_stats *core_stats = NULL;
84 struct dc *dc = NULL;
85
86 if (mod_stats == NULL)
87 return false;
88
89 core_stats = MOD_STATS_TO_CORE(mod_stats);
90 dc = core_stats->dc;
91
92 return result;
93}
94
95struct mod_stats *mod_stats_create(struct dc *dc)
96{
97 struct core_stats *core_stats = NULL;
98 struct persistent_data_flag flag;
99 unsigned int reg_data;
100 int i = 0;
101
102 core_stats = kzalloc(sizeof(struct core_stats), GFP_KERNEL);
103
104 if (core_stats == NULL)
105 goto fail_alloc_context;
106
107 if (dc == NULL)
108 goto fail_construct;
109
110 core_stats->dc = dc;
111
112 core_stats->enabled = DAL_STATS_ENABLE_REGKEY_DEFAULT;
113 if (dm_read_persistent_data(dc->ctx, NULL, NULL,
114 DAL_STATS_ENABLE_REGKEY,
115 &reg_data, sizeof(unsigned int), &flag))
116 core_stats->enabled = reg_data;
117
118 core_stats->entries = DAL_STATS_ENTRIES_REGKEY_DEFAULT;
119 if (dm_read_persistent_data(dc->ctx, NULL, NULL,
120 DAL_STATS_ENTRIES_REGKEY,
121 &reg_data, sizeof(unsigned int), &flag)) {
122 if (reg_data > DAL_STATS_ENTRIES_REGKEY_MAX)
123 core_stats->entries = DAL_STATS_ENTRIES_REGKEY_MAX;
124 else
125 core_stats->entries = reg_data;
126 }
127
128 core_stats->time = kzalloc(sizeof(struct stats_time_cache) * core_stats->entries,
129 GFP_KERNEL);
130
131 if (core_stats->time == NULL)
132 goto fail_construct;
133
134 /* Purposely leave index 0 unused so we don't need special logic to
135 * handle calculation cases that depend on previous flip data.
136 */
137 core_stats->index = 1;
138
139 return &core_stats->public;
140
141fail_construct:
142 kfree(core_stats);
143
144fail_alloc_context:
145 return NULL;
146}
147
148void mod_stats_destroy(struct mod_stats *mod_stats)
149{
150 if (mod_stats != NULL) {
151 struct core_stats *core_stats = MOD_STATS_TO_CORE(mod_stats);
152
153 if (core_stats->time != NULL)
154 kfree(core_stats->time);
155
156 kfree(core_stats);
157 }
158}
159
160void mod_stats_dump(struct mod_stats *mod_stats)
161{
162 struct dc *dc = NULL;
163 struct dal_logger *logger = NULL;
164 struct core_stats *core_stats = NULL;
165 struct stats_time_cache *time = NULL;
166 unsigned int index = 0;
167
168 if (mod_stats == NULL)
169 return;
170
171 core_stats = MOD_STATS_TO_CORE(mod_stats);
172 dc = core_stats->dc;
173 logger = dc->ctx->logger;
174 time = core_stats->time;
175
176 //LogEntry* pLog = GetLog()->Open(LogMajor_ISR, LogMinor_ISR_FreeSyncSW);
177
178 //if (!pLog->IsDummyEntry())
179 {
180 dm_logger_write(logger, LOG_PROFILING, "==Display Caps==\n");
181 dm_logger_write(logger, LOG_PROFILING, "\n");
182 dm_logger_write(logger, LOG_PROFILING, "\n");
183
184 dm_logger_write(logger, LOG_PROFILING, "==Stats==\n");
185 dm_logger_write(logger, LOG_PROFILING,
186 "render avgRender minWindow midPoint maxWindow vsyncToFlip flipToVsync #vsyncBetweenFlip #frame insertDuration vTotalMin vTotalMax eventTrigs vSyncTime1 vSyncTime2 vSyncTime3 vSyncTime4 vSyncTime5 flags\n");
187
188 for (int i = 0; i < core_stats->index && i < core_stats->entries; i++) {
189 dm_logger_write(logger, LOG_PROFILING,
190 "%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u\n",
191 time[i].render_time_in_us,
192 time[i].avg_render_time_in_us_last_ten,
193 time[i].min_window,
194 time[i].lfc_mid_point_in_us,
195 time[i].max_window,
196 time[i].vsync_to_flip_time_in_us,
197 time[i].flip_to_vsync_time_in_us,
198 time[i].num_vsync_between_flips,
199 time[i].num_frames_inserted,
200 time[i].inserted_duration_in_us,
201 time[i].v_total_min,
202 time[i].v_total_max,
203 time[i].event_triggers,
204 time[i].v_sync_time_in_us[0],
205 time[i].v_sync_time_in_us[1],
206 time[i].v_sync_time_in_us[2],
207 time[i].v_sync_time_in_us[3],
208 time[i].v_sync_time_in_us[4],
209 time[i].flags);
210 }
211 }
212 //GetLog()->Close(pLog);
213 //GetLog()->UnSetLogMask(LogMajor_ISR, LogMinor_ISR_FreeSyncSW);
214}
215
216void mod_stats_reset_data(struct mod_stats *mod_stats)
217{
218 struct core_stats *core_stats = NULL;
219 struct stats_time_cache *time = NULL;
220 unsigned int index = 0;
221
222 if (mod_stats == NULL)
223 return;
224
225 core_stats = MOD_STATS_TO_CORE(mod_stats);
226
227 memset(core_stats->time, 0,
228 sizeof(struct stats_time_cache) * core_stats->entries);
229
230 core_stats->index = 0;
231}
232
233void mod_stats_update_flip(struct mod_stats *mod_stats,
234 unsigned long timestamp_in_ns)
235{
236 struct core_stats *core_stats = NULL;
237 struct stats_time_cache *time = NULL;
238 unsigned int index = 0;
239
240 if (mod_stats == NULL)
241 return;
242
243 core_stats = MOD_STATS_TO_CORE(mod_stats);
244
245 if (core_stats->index >= core_stats->entries)
246 return;
247
248 time = core_stats->time;
249 index = core_stats->index;
250
251 time[index].flip_timestamp_in_ns = timestamp_in_ns;
252 time[index].render_time_in_us =
253 timestamp_in_ns - time[index - 1].flip_timestamp_in_ns;
254
255 if (index >= 10) {
256 for (unsigned int i = 0; i < 10; i++)
257 time[index].avg_render_time_in_us_last_ten +=
258 time[index - i].render_time_in_us;
259 time[index].avg_render_time_in_us_last_ten /= 10;
260 }
261
262 if (time[index].num_vsync_between_flips > 0)
263 time[index].vsync_to_flip_time_in_us =
264 timestamp_in_ns - time[index].vupdate_timestamp_in_ns;
265 else
266 time[index].vsync_to_flip_time_in_us =
267 timestamp_in_ns - time[index - 1].vupdate_timestamp_in_ns;
268
269 core_stats->index++;
270}
271
272void mod_stats_update_vupdate(struct mod_stats *mod_stats,
273 unsigned long timestamp_in_ns)
274{
275 struct core_stats *core_stats = NULL;
276 struct stats_time_cache *time = NULL;
277 unsigned int index = 0;
278
279 if (mod_stats == NULL)
280 return;
281
282 core_stats = MOD_STATS_TO_CORE(mod_stats);
283
284 if (core_stats->index >= core_stats->entries)
285 return;
286
287 time = core_stats->time;
288 index = core_stats->index;
289
290 time[index].vupdate_timestamp_in_ns = timestamp_in_ns;
291 if (time[index].num_vsync_between_flips < MOD_STATS_NUM_VSYNCS)
292 time[index].v_sync_time_in_us[time[index].num_vsync_between_flips] =
293 timestamp_in_ns - time[index - 1].vupdate_timestamp_in_ns;
294 time[index].flip_to_vsync_time_in_us =
295 timestamp_in_ns - time[index - 1].flip_timestamp_in_ns;
296
297 time[index].num_vsync_between_flips++;
298}
299
300void mod_stats_update_freesync(struct mod_stats *mod_stats,
301 unsigned int v_total_min,
302 unsigned int v_total_max,
303 unsigned int event_triggers,
304 unsigned int window_min,
305 unsigned int window_max,
306 unsigned int lfc_mid_point_in_us,
307 unsigned int inserted_frames,
308 unsigned int inserted_duration_in_us)
309{
310 struct core_stats *core_stats = NULL;
311 struct stats_time_cache *time = NULL;
312 unsigned int index = 0;
313
314 if (mod_stats == NULL)
315 return;
316
317 core_stats = MOD_STATS_TO_CORE(mod_stats);
318
319 if (core_stats->index >= core_stats->entries)
320 return;
321
322 time = core_stats->time;
323 index = core_stats->index;
324
325 time[index].v_total_min = v_total_min;
326 time[index].v_total_max = v_total_max;
327 time[index].event_triggers = event_triggers;
328 time[index].min_window = window_min;
329 time[index].max_window = window_max;
330 time[index].lfc_mid_point_in_us = lfc_mid_point_in_us;
331 time[index].num_frames_inserted = inserted_frames;
332 time[index].inserted_duration_in_us = inserted_duration_in_us;
333}
334