xref: /linux/drivers/media/platform/rockchip/rkisp1/rkisp1-debug.c (revision 06d07429858317ded2db7986113a9e0129cd599b)
1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2 /*
3  * Rockchip ISP1 Driver - Base driver
4  *
5  * Copyright (C) 2019 Collabora, Ltd.
6  *
7  * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd.
8  * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
9  */
10 
11 #include <linux/debugfs.h>
12 #include <linux/delay.h>
13 #include <linux/device.h>
14 #include <linux/minmax.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/seq_file.h>
17 #include <linux/string.h>
18 
19 #include "rkisp1-common.h"
20 #include "rkisp1-regs.h"
21 
22 struct rkisp1_debug_register {
23 	u32 reg;
24 	u32 shd;
25 	const char * const name;
26 };
27 
28 #define RKISP1_DEBUG_REG(name)		{ RKISP1_CIF_##name, 0, #name }
29 #define RKISP1_DEBUG_SHD_REG(name) { \
30 	RKISP1_CIF_##name, RKISP1_CIF_##name##_SHD, #name \
31 }
32 
33 /* Keep this up-to-date when adding new registers. */
34 #define RKISP1_MAX_REG_LENGTH		21
35 
rkisp1_debug_dump_regs(struct rkisp1_device * rkisp1,struct seq_file * m,unsigned int offset,const struct rkisp1_debug_register * regs)36 static int rkisp1_debug_dump_regs(struct rkisp1_device *rkisp1,
37 				  struct seq_file *m, unsigned int offset,
38 				  const struct rkisp1_debug_register *regs)
39 {
40 	const int width = RKISP1_MAX_REG_LENGTH;
41 	u32 val, shd;
42 	int ret;
43 
44 	ret = pm_runtime_get_if_in_use(rkisp1->dev);
45 	if (ret <= 0)
46 		return ret ? : -ENODATA;
47 
48 	for (; regs->name; ++regs) {
49 		val = rkisp1_read(rkisp1, offset + regs->reg);
50 
51 		if (regs->shd) {
52 			shd = rkisp1_read(rkisp1, offset + regs->shd);
53 			seq_printf(m, "%*s: 0x%08x/0x%08x\n", width, regs->name,
54 				   val, shd);
55 		} else {
56 			seq_printf(m, "%*s: 0x%08x\n", width, regs->name, val);
57 		}
58 	}
59 
60 	pm_runtime_put(rkisp1->dev);
61 
62 	return 0;
63 }
64 
rkisp1_debug_dump_core_regs_show(struct seq_file * m,void * p)65 static int rkisp1_debug_dump_core_regs_show(struct seq_file *m, void *p)
66 {
67 	static const struct rkisp1_debug_register registers[] = {
68 		RKISP1_DEBUG_REG(VI_CCL),
69 		RKISP1_DEBUG_REG(VI_ICCL),
70 		RKISP1_DEBUG_REG(VI_IRCL),
71 		RKISP1_DEBUG_REG(VI_DPCL),
72 		RKISP1_DEBUG_REG(MI_CTRL),
73 		RKISP1_DEBUG_REG(MI_BYTE_CNT),
74 		RKISP1_DEBUG_REG(MI_CTRL_SHD),
75 		RKISP1_DEBUG_REG(MI_RIS),
76 		RKISP1_DEBUG_REG(MI_STATUS),
77 		RKISP1_DEBUG_REG(MI_DMA_CTRL),
78 		RKISP1_DEBUG_REG(MI_DMA_STATUS),
79 		{ /* Sentinel */ },
80 	};
81 	struct rkisp1_device *rkisp1 = m->private;
82 
83 	return rkisp1_debug_dump_regs(rkisp1, m, 0, registers);
84 }
85 DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_core_regs);
86 
rkisp1_debug_dump_isp_regs_show(struct seq_file * m,void * p)87 static int rkisp1_debug_dump_isp_regs_show(struct seq_file *m, void *p)
88 {
89 	static const struct rkisp1_debug_register registers[] = {
90 		RKISP1_DEBUG_REG(ISP_CTRL),
91 		RKISP1_DEBUG_REG(ISP_ACQ_PROP),
92 		RKISP1_DEBUG_REG(ISP_FLAGS_SHD),
93 		RKISP1_DEBUG_REG(ISP_RIS),
94 		RKISP1_DEBUG_REG(ISP_ERR),
95 		RKISP1_DEBUG_SHD_REG(ISP_IS_H_OFFS),
96 		RKISP1_DEBUG_SHD_REG(ISP_IS_V_OFFS),
97 		RKISP1_DEBUG_SHD_REG(ISP_IS_H_SIZE),
98 		RKISP1_DEBUG_SHD_REG(ISP_IS_V_SIZE),
99 		{ /* Sentinel */ },
100 	};
101 	struct rkisp1_device *rkisp1 = m->private;
102 
103 	return rkisp1_debug_dump_regs(rkisp1, m, 0, registers);
104 }
105 DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_isp_regs);
106 
rkisp1_debug_dump_rsz_regs_show(struct seq_file * m,void * p)107 static int rkisp1_debug_dump_rsz_regs_show(struct seq_file *m, void *p)
108 {
109 	static const struct rkisp1_debug_register registers[] = {
110 		RKISP1_DEBUG_SHD_REG(RSZ_CTRL),
111 		RKISP1_DEBUG_SHD_REG(RSZ_SCALE_HY),
112 		RKISP1_DEBUG_SHD_REG(RSZ_SCALE_HCB),
113 		RKISP1_DEBUG_SHD_REG(RSZ_SCALE_HCR),
114 		RKISP1_DEBUG_SHD_REG(RSZ_SCALE_VY),
115 		RKISP1_DEBUG_SHD_REG(RSZ_SCALE_VC),
116 		RKISP1_DEBUG_SHD_REG(RSZ_PHASE_HY),
117 		RKISP1_DEBUG_SHD_REG(RSZ_PHASE_HC),
118 		RKISP1_DEBUG_SHD_REG(RSZ_PHASE_VY),
119 		RKISP1_DEBUG_SHD_REG(RSZ_PHASE_VC),
120 		{ /* Sentinel */ },
121 	};
122 	struct rkisp1_resizer *rsz = m->private;
123 
124 	return rkisp1_debug_dump_regs(rsz->rkisp1, m, rsz->regs_base, registers);
125 }
126 DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_rsz_regs);
127 
rkisp1_debug_dump_mi_mp_show(struct seq_file * m,void * p)128 static int rkisp1_debug_dump_mi_mp_show(struct seq_file *m, void *p)
129 {
130 	static const struct rkisp1_debug_register registers[] = {
131 		RKISP1_DEBUG_REG(MI_MP_Y_BASE_AD_INIT),
132 		RKISP1_DEBUG_REG(MI_MP_Y_BASE_AD_INIT2),
133 		RKISP1_DEBUG_REG(MI_MP_Y_BASE_AD_SHD),
134 		RKISP1_DEBUG_REG(MI_MP_Y_SIZE_INIT),
135 		RKISP1_DEBUG_REG(MI_MP_Y_SIZE_INIT),
136 		RKISP1_DEBUG_REG(MI_MP_Y_SIZE_SHD),
137 		RKISP1_DEBUG_REG(MI_MP_Y_OFFS_CNT_SHD),
138 		{ /* Sentinel */ },
139 	};
140 	struct rkisp1_device *rkisp1 = m->private;
141 
142 	return rkisp1_debug_dump_regs(rkisp1, m, 0, registers);
143 }
144 DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_mi_mp);
145 
146 #define RKISP1_DEBUG_DATA_COUNT_BINS	32
147 #define RKISP1_DEBUG_DATA_COUNT_STEP	(4096 / RKISP1_DEBUG_DATA_COUNT_BINS)
148 
rkisp1_debug_input_status_show(struct seq_file * m,void * p)149 static int rkisp1_debug_input_status_show(struct seq_file *m, void *p)
150 {
151 	struct rkisp1_device *rkisp1 = m->private;
152 	u16 data_count[RKISP1_DEBUG_DATA_COUNT_BINS] = { };
153 	unsigned int hsync_count = 0;
154 	unsigned int vsync_count = 0;
155 	unsigned int i;
156 	u32 data;
157 	u32 val;
158 	int ret;
159 
160 	ret = pm_runtime_get_if_in_use(rkisp1->dev);
161 	if (ret <= 0)
162 		return ret ? : -ENODATA;
163 
164 	/* Sample the ISP input port status 10000 times with a 1µs interval. */
165 	for (i = 0; i < 10000; ++i) {
166 		val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_FLAGS_SHD);
167 
168 		data = (val & RKISP1_CIF_ISP_FLAGS_SHD_S_DATA_MASK)
169 		     >> RKISP1_CIF_ISP_FLAGS_SHD_S_DATA_SHIFT;
170 		data_count[data / RKISP1_DEBUG_DATA_COUNT_STEP]++;
171 
172 		if (val & RKISP1_CIF_ISP_FLAGS_SHD_S_HSYNC)
173 			hsync_count++;
174 		if (val & RKISP1_CIF_ISP_FLAGS_SHD_S_VSYNC)
175 			vsync_count++;
176 
177 		udelay(1);
178 	}
179 
180 	pm_runtime_put(rkisp1->dev);
181 
182 	seq_printf(m, "vsync: %u, hsync: %u\n", vsync_count, hsync_count);
183 	seq_puts(m, "data:\n");
184 	for (i = 0; i < ARRAY_SIZE(data_count); ++i)
185 		seq_printf(m, "- [%04u:%04u]: %u\n",
186 			   i * RKISP1_DEBUG_DATA_COUNT_STEP,
187 			   (i + 1) * RKISP1_DEBUG_DATA_COUNT_STEP - 1,
188 			   data_count[i]);
189 
190 	return 0;
191 }
192 DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_input_status);
193 
rkisp1_debug_init(struct rkisp1_device * rkisp1)194 void rkisp1_debug_init(struct rkisp1_device *rkisp1)
195 {
196 	struct rkisp1_debug *debug = &rkisp1->debug;
197 	struct dentry *regs_dir;
198 
199 	debug->debugfs_dir = debugfs_create_dir(dev_name(rkisp1->dev), NULL);
200 
201 	debugfs_create_ulong("data_loss", 0444, debug->debugfs_dir,
202 			     &debug->data_loss);
203 	debugfs_create_ulong("outform_size_err", 0444,  debug->debugfs_dir,
204 			     &debug->outform_size_error);
205 	debugfs_create_ulong("img_stabilization_size_error", 0444,
206 			     debug->debugfs_dir,
207 			     &debug->img_stabilization_size_error);
208 	debugfs_create_ulong("inform_size_error", 0444,  debug->debugfs_dir,
209 			     &debug->inform_size_error);
210 	debugfs_create_ulong("irq_delay", 0444,  debug->debugfs_dir,
211 			     &debug->irq_delay);
212 	debugfs_create_ulong("mipi_error", 0444, debug->debugfs_dir,
213 			     &debug->mipi_error);
214 	debugfs_create_ulong("stats_error", 0444, debug->debugfs_dir,
215 			     &debug->stats_error);
216 	debugfs_create_ulong("mp_stop_timeout", 0444, debug->debugfs_dir,
217 			     &debug->stop_timeout[RKISP1_MAINPATH]);
218 	debugfs_create_ulong("sp_stop_timeout", 0444, debug->debugfs_dir,
219 			     &debug->stop_timeout[RKISP1_SELFPATH]);
220 	debugfs_create_ulong("mp_frame_drop", 0444, debug->debugfs_dir,
221 			     &debug->frame_drop[RKISP1_MAINPATH]);
222 	debugfs_create_ulong("sp_frame_drop", 0444, debug->debugfs_dir,
223 			     &debug->frame_drop[RKISP1_SELFPATH]);
224 	debugfs_create_ulong("complete_frames", 0444, debug->debugfs_dir,
225 			     &debug->complete_frames);
226 	debugfs_create_file("input_status", 0444, debug->debugfs_dir, rkisp1,
227 			    &rkisp1_debug_input_status_fops);
228 
229 	regs_dir = debugfs_create_dir("regs", debug->debugfs_dir);
230 
231 	debugfs_create_file("core", 0444, regs_dir, rkisp1,
232 			    &rkisp1_debug_dump_core_regs_fops);
233 	debugfs_create_file("isp", 0444, regs_dir, rkisp1,
234 			    &rkisp1_debug_dump_isp_regs_fops);
235 	debugfs_create_file("mrsz", 0444, regs_dir,
236 			    &rkisp1->resizer_devs[RKISP1_MAINPATH],
237 			    &rkisp1_debug_dump_rsz_regs_fops);
238 	debugfs_create_file("srsz", 0444, regs_dir,
239 			    &rkisp1->resizer_devs[RKISP1_SELFPATH],
240 			    &rkisp1_debug_dump_rsz_regs_fops);
241 
242 	debugfs_create_file("mi_mp", 0444, regs_dir, rkisp1,
243 			    &rkisp1_debug_dump_mi_mp_fops);
244 }
245 
rkisp1_debug_cleanup(struct rkisp1_device * rkisp1)246 void rkisp1_debug_cleanup(struct rkisp1_device *rkisp1)
247 {
248 	debugfs_remove_recursive(rkisp1->debug.debugfs_dir);
249 }
250