1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Support for Intel Camera Imaging ISP subsystem.
4  * Copyright (c) 2015, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  */
15 
16 #include "assert_support.h"
17 #include "sh_css_metrics.h"
18 
19 #include "sp.h"
20 #include "isp.h"
21 
22 #include "sh_css_internal.h"
23 
24 #define MULTIPLE_PCS 0
25 #define SUSPEND      0
26 #define NOF_PCS      1
27 #define RESUME_MASK  0x8
28 #define STOP_MASK    0x0
29 
30 static bool pc_histogram_enabled;
31 static struct sh_css_pc_histogram *isp_histogram;
32 static struct sh_css_pc_histogram *sp_histogram;
33 
34 struct sh_css_metrics sh_css_metrics;
35 
36 void
sh_css_metrics_start_frame(void)37 sh_css_metrics_start_frame(void)
38 {
39 	sh_css_metrics.frame_metrics.num_frames++;
40 }
41 
42 static void
clear_histogram(struct sh_css_pc_histogram * histogram)43 clear_histogram(struct sh_css_pc_histogram *histogram)
44 {
45 	unsigned int i;
46 
47 	assert(histogram);
48 
49 	for (i = 0; i < histogram->length; i++) {
50 		histogram->run[i] = 0;
51 		histogram->stall[i] = 0;
52 		histogram->msink[i] = 0xFFFF;
53 	}
54 }
55 
56 void
sh_css_metrics_enable_pc_histogram(bool enable)57 sh_css_metrics_enable_pc_histogram(bool enable)
58 {
59 	pc_histogram_enabled = enable;
60 }
61 
62 static void
make_histogram(struct sh_css_pc_histogram * histogram,unsigned int length)63 make_histogram(struct sh_css_pc_histogram *histogram, unsigned int length)
64 {
65 	assert(histogram);
66 
67 	if (histogram->length)
68 		return;
69 	if (histogram->run)
70 		return;
71 	histogram->run = kvmalloc(length * sizeof(*histogram->run),
72 				  GFP_KERNEL);
73 	if (!histogram->run)
74 		return;
75 	histogram->stall = kvmalloc(length * sizeof(*histogram->stall),
76 				    GFP_KERNEL);
77 	if (!histogram->stall)
78 		return;
79 	histogram->msink = kvmalloc(length * sizeof(*histogram->msink),
80 				    GFP_KERNEL);
81 	if (!histogram->msink)
82 		return;
83 
84 	histogram->length = length;
85 	clear_histogram(histogram);
86 }
87 
88 static void
insert_binary_metrics(struct sh_css_binary_metrics ** l,struct sh_css_binary_metrics * metrics)89 insert_binary_metrics(struct sh_css_binary_metrics **l,
90 		      struct sh_css_binary_metrics *metrics)
91 {
92 	assert(l);
93 	assert(*l);
94 	assert(metrics);
95 
96 	for (; *l; l = &(*l)->next)
97 		if (*l == metrics)
98 			return;
99 
100 	*l = metrics;
101 	metrics->next = NULL;
102 }
103 
104 void
sh_css_metrics_start_binary(struct sh_css_binary_metrics * metrics)105 sh_css_metrics_start_binary(struct sh_css_binary_metrics *metrics)
106 {
107 	assert(metrics);
108 
109 	if (!pc_histogram_enabled)
110 		return;
111 
112 	isp_histogram = &metrics->isp_histogram;
113 	sp_histogram = &metrics->sp_histogram;
114 	make_histogram(isp_histogram, ISP_PMEM_DEPTH);
115 	make_histogram(sp_histogram, SP_PMEM_DEPTH);
116 	insert_binary_metrics(&sh_css_metrics.binary_metrics, metrics);
117 }
118 
119 void
sh_css_metrics_sample_pcs(void)120 sh_css_metrics_sample_pcs(void)
121 {
122 	bool stall;
123 	unsigned int pc;
124 	unsigned int msink;
125 
126 #if SUSPEND
127 	unsigned int sc = 0;
128 	unsigned int stopped_sc = 0;
129 	unsigned int resume_sc = 0;
130 #endif
131 
132 #if MULTIPLE_PCS
133 	int i;
134 	unsigned int pc_tab[NOF_PCS];
135 
136 	for (i = 0; i < NOF_PCS; i++)
137 		pc_tab[i] = 0;
138 #endif
139 
140 	if (!pc_histogram_enabled)
141 		return;
142 
143 	if (isp_histogram) {
144 #if SUSPEND
145 		/* STOP the ISP */
146 		isp_ctrl_store(ISP0_ID, ISP_SC_REG, STOP_MASK);
147 #endif
148 		msink = isp_ctrl_load(ISP0_ID, ISP_CTRL_SINK_REG);
149 #if MULTIPLE_PCS
150 		for (i = 0; i < NOF_PCS; i++)
151 			pc_tab[i] = isp_ctrl_load(ISP0_ID, ISP_PC_REG);
152 #else
153 		pc = isp_ctrl_load(ISP0_ID, ISP_PC_REG);
154 #endif
155 
156 #if SUSPEND
157 		/* RESUME the ISP */
158 		isp_ctrl_store(ISP0_ID, ISP_SC_REG, RESUME_MASK);
159 #endif
160 		isp_histogram->msink[pc] &= msink;
161 		stall = (msink != 0x7FF);
162 
163 		if (stall)
164 			isp_histogram->stall[pc]++;
165 		else
166 			isp_histogram->run[pc]++;
167 	}
168 
169 	if (sp_histogram && 0) {
170 		msink = sp_ctrl_load(SP0_ID, SP_CTRL_SINK_REG);
171 		pc = sp_ctrl_load(SP0_ID, SP_PC_REG);
172 		sp_histogram->msink[pc] &= msink;
173 		stall = (msink != 0x7FF);
174 		if (stall)
175 			sp_histogram->stall[pc]++;
176 		else
177 			sp_histogram->run[pc]++;
178 	}
179 }
180