Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
  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