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