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
22struct 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
36static 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
65static 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}
85DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_core_regs);
86
87static 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		{ /* Sentinel */ },
96	};
97	struct rkisp1_device *rkisp1 = m->private;
98
99	return rkisp1_debug_dump_regs(rkisp1, m, 0, registers);
100}
101DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_isp_regs);
102
103static int rkisp1_debug_dump_rsz_regs_show(struct seq_file *m, void *p)
104{
105	static const struct rkisp1_debug_register registers[] = {
106		RKISP1_DEBUG_SHD_REG(RSZ_CTRL),
107		RKISP1_DEBUG_SHD_REG(RSZ_SCALE_HY),
108		RKISP1_DEBUG_SHD_REG(RSZ_SCALE_HCB),
109		RKISP1_DEBUG_SHD_REG(RSZ_SCALE_HCR),
110		RKISP1_DEBUG_SHD_REG(RSZ_SCALE_VY),
111		RKISP1_DEBUG_SHD_REG(RSZ_SCALE_VC),
112		RKISP1_DEBUG_SHD_REG(RSZ_PHASE_HY),
113		RKISP1_DEBUG_SHD_REG(RSZ_PHASE_HC),
114		RKISP1_DEBUG_SHD_REG(RSZ_PHASE_VY),
115		RKISP1_DEBUG_SHD_REG(RSZ_PHASE_VC),
116		{ /* Sentinel */ },
117	};
118	struct rkisp1_resizer *rsz = m->private;
119
120	return rkisp1_debug_dump_regs(rsz->rkisp1, m, rsz->regs_base, registers);
121}
122DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_rsz_regs);
123
124static int rkisp1_debug_dump_mi_mp_show(struct seq_file *m, void *p)
125{
126	static const struct rkisp1_debug_register registers[] = {
127		RKISP1_DEBUG_REG(MI_MP_Y_BASE_AD_INIT),
128		RKISP1_DEBUG_REG(MI_MP_Y_BASE_AD_INIT2),
129		RKISP1_DEBUG_REG(MI_MP_Y_BASE_AD_SHD),
130		RKISP1_DEBUG_REG(MI_MP_Y_SIZE_INIT),
131		RKISP1_DEBUG_REG(MI_MP_Y_SIZE_INIT),
132		RKISP1_DEBUG_REG(MI_MP_Y_SIZE_SHD),
133		RKISP1_DEBUG_REG(MI_MP_Y_OFFS_CNT_SHD),
134		{ /* Sentinel */ },
135	};
136	struct rkisp1_device *rkisp1 = m->private;
137
138	return rkisp1_debug_dump_regs(rkisp1, m, 0, registers);
139}
140DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_mi_mp);
141
142#define RKISP1_DEBUG_DATA_COUNT_BINS	32
143#define RKISP1_DEBUG_DATA_COUNT_STEP	(4096 / RKISP1_DEBUG_DATA_COUNT_BINS)
144
145static int rkisp1_debug_input_status_show(struct seq_file *m, void *p)
146{
147	struct rkisp1_device *rkisp1 = m->private;
148	u16 data_count[RKISP1_DEBUG_DATA_COUNT_BINS] = { };
149	unsigned int hsync_count = 0;
150	unsigned int vsync_count = 0;
151	unsigned int i;
152	u32 data;
153	u32 val;
154	int ret;
155
156	ret = pm_runtime_get_if_in_use(rkisp1->dev);
157	if (ret <= 0)
158		return ret ? : -ENODATA;
159
160	/* Sample the ISP input port status 10000 times with a 1µs interval. */
161	for (i = 0; i < 10000; ++i) {
162		val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_FLAGS_SHD);
163
164		data = (val & RKISP1_CIF_ISP_FLAGS_SHD_S_DATA_MASK)
165		     >> RKISP1_CIF_ISP_FLAGS_SHD_S_DATA_SHIFT;
166		data_count[data / RKISP1_DEBUG_DATA_COUNT_STEP]++;
167
168		if (val & RKISP1_CIF_ISP_FLAGS_SHD_S_HSYNC)
169			hsync_count++;
170		if (val & RKISP1_CIF_ISP_FLAGS_SHD_S_VSYNC)
171			vsync_count++;
172
173		udelay(1);
174	}
175
176	pm_runtime_put(rkisp1->dev);
177
178	seq_printf(m, "vsync: %u, hsync: %u\n", vsync_count, hsync_count);
179	seq_puts(m, "data:\n");
180	for (i = 0; i < ARRAY_SIZE(data_count); ++i)
181		seq_printf(m, "- [%04u:%04u]: %u\n",
182			   i * RKISP1_DEBUG_DATA_COUNT_STEP,
183			   (i + 1) * RKISP1_DEBUG_DATA_COUNT_STEP - 1,
184			   data_count[i]);
185
186	return 0;
187}
188DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_input_status);
189
190void rkisp1_debug_init(struct rkisp1_device *rkisp1)
191{
192	struct rkisp1_debug *debug = &rkisp1->debug;
193	struct dentry *regs_dir;
194
195	debug->debugfs_dir = debugfs_create_dir(dev_name(rkisp1->dev), NULL);
196
197	debugfs_create_ulong("data_loss", 0444, debug->debugfs_dir,
198			     &debug->data_loss);
199	debugfs_create_ulong("outform_size_err", 0444,  debug->debugfs_dir,
200			     &debug->outform_size_error);
201	debugfs_create_ulong("img_stabilization_size_error", 0444,
202			     debug->debugfs_dir,
203			     &debug->img_stabilization_size_error);
204	debugfs_create_ulong("inform_size_error", 0444,  debug->debugfs_dir,
205			     &debug->inform_size_error);
206	debugfs_create_ulong("irq_delay", 0444,  debug->debugfs_dir,
207			     &debug->irq_delay);
208	debugfs_create_ulong("mipi_error", 0444, debug->debugfs_dir,
209			     &debug->mipi_error);
210	debugfs_create_ulong("stats_error", 0444, debug->debugfs_dir,
211			     &debug->stats_error);
212	debugfs_create_ulong("mp_stop_timeout", 0444, debug->debugfs_dir,
213			     &debug->stop_timeout[RKISP1_MAINPATH]);
214	debugfs_create_ulong("sp_stop_timeout", 0444, debug->debugfs_dir,
215			     &debug->stop_timeout[RKISP1_SELFPATH]);
216	debugfs_create_ulong("mp_frame_drop", 0444, debug->debugfs_dir,
217			     &debug->frame_drop[RKISP1_MAINPATH]);
218	debugfs_create_ulong("sp_frame_drop", 0444, debug->debugfs_dir,
219			     &debug->frame_drop[RKISP1_SELFPATH]);
220	debugfs_create_file("input_status", 0444, debug->debugfs_dir, rkisp1,
221			    &rkisp1_debug_input_status_fops);
222
223	regs_dir = debugfs_create_dir("regs", debug->debugfs_dir);
224
225	debugfs_create_file("core", 0444, regs_dir, rkisp1,
226			    &rkisp1_debug_dump_core_regs_fops);
227	debugfs_create_file("isp", 0444, regs_dir, rkisp1,
228			    &rkisp1_debug_dump_isp_regs_fops);
229	debugfs_create_file("mrsz", 0444, regs_dir,
230			    &rkisp1->resizer_devs[RKISP1_MAINPATH],
231			    &rkisp1_debug_dump_rsz_regs_fops);
232	debugfs_create_file("srsz", 0444, regs_dir,
233			    &rkisp1->resizer_devs[RKISP1_SELFPATH],
234			    &rkisp1_debug_dump_rsz_regs_fops);
235
236	debugfs_create_file("mi_mp", 0444, regs_dir, rkisp1,
237			    &rkisp1_debug_dump_mi_mp_fops);
238}
239
240void rkisp1_debug_cleanup(struct rkisp1_device *rkisp1)
241{
242	debugfs_remove_recursive(rkisp1->debug.debugfs_dir);
243}
244