Linux Audio

Check our new training course

Linux BSP development engineering services

Need help to port Linux and bootloaders to your hardware?
Loading...
Note: File does not exist in v5.14.15.
  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		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}
105DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_isp_regs);
106
107static 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}
126DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_rsz_regs);
127
128static 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}
144DEFINE_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
149static 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}
192DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_input_status);
193
194void 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
246void rkisp1_debug_cleanup(struct rkisp1_device *rkisp1)
247{
248	debugfs_remove_recursive(rkisp1->debug.debugfs_dir);
249}