| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
- /*
- * Rockchip ISP1 Driver - Base driver
- *
- * Copyright (C) 2019 Collabora, Ltd.
- *
- * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd.
- * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
- */
- #include <linux/debugfs.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- #include <linux/minmax.h>
- #include <linux/pm_runtime.h>
- #include <linux/seq_file.h>
- #include <linux/string.h>
- #include "rkisp1-common.h"
- #include "rkisp1-regs.h"
- struct rkisp1_debug_register {
- u32 reg;
- u32 shd;
- const char * const name;
- };
- #define RKISP1_DEBUG_REG(name) { RKISP1_CIF_##name, 0, #name }
- #define RKISP1_DEBUG_SHD_REG(name) { \
- RKISP1_CIF_##name, RKISP1_CIF_##name##_SHD, #name \
- }
- /* Keep this up-to-date when adding new registers. */
- #define RKISP1_MAX_REG_LENGTH 21
- static int rkisp1_debug_dump_regs(struct rkisp1_device *rkisp1,
- struct seq_file *m, unsigned int offset,
- const struct rkisp1_debug_register *regs)
- {
- const int width = RKISP1_MAX_REG_LENGTH;
- u32 val, shd;
- int ret;
- ret = pm_runtime_get_if_in_use(rkisp1->dev);
- if (ret <= 0)
- return ret ? : -ENODATA;
- for (; regs->name; ++regs) {
- val = rkisp1_read(rkisp1, offset + regs->reg);
- if (regs->shd) {
- shd = rkisp1_read(rkisp1, offset + regs->shd);
- seq_printf(m, "%*s: 0x%08x/0x%08x\n", width, regs->name,
- val, shd);
- } else {
- seq_printf(m, "%*s: 0x%08x\n", width, regs->name, val);
- }
- }
- pm_runtime_put(rkisp1->dev);
- return 0;
- }
- static int rkisp1_debug_dump_core_regs_show(struct seq_file *m, void *p)
- {
- static const struct rkisp1_debug_register registers[] = {
- RKISP1_DEBUG_REG(VI_CCL),
- RKISP1_DEBUG_REG(VI_ICCL),
- RKISP1_DEBUG_REG(VI_IRCL),
- RKISP1_DEBUG_REG(VI_DPCL),
- RKISP1_DEBUG_REG(MI_CTRL),
- RKISP1_DEBUG_REG(MI_BYTE_CNT),
- RKISP1_DEBUG_REG(MI_CTRL_SHD),
- RKISP1_DEBUG_REG(MI_RIS),
- RKISP1_DEBUG_REG(MI_STATUS),
- RKISP1_DEBUG_REG(MI_DMA_CTRL),
- RKISP1_DEBUG_REG(MI_DMA_STATUS),
- { /* Sentinel */ },
- };
- struct rkisp1_device *rkisp1 = m->private;
- return rkisp1_debug_dump_regs(rkisp1, m, 0, registers);
- }
- DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_core_regs);
- static int rkisp1_debug_dump_isp_regs_show(struct seq_file *m, void *p)
- {
- static const struct rkisp1_debug_register registers[] = {
- RKISP1_DEBUG_REG(ISP_CTRL),
- RKISP1_DEBUG_REG(ISP_ACQ_PROP),
- RKISP1_DEBUG_REG(ISP_FLAGS_SHD),
- RKISP1_DEBUG_REG(ISP_RIS),
- RKISP1_DEBUG_REG(ISP_ERR),
- RKISP1_DEBUG_SHD_REG(ISP_IS_H_OFFS),
- RKISP1_DEBUG_SHD_REG(ISP_IS_V_OFFS),
- RKISP1_DEBUG_SHD_REG(ISP_IS_H_SIZE),
- RKISP1_DEBUG_SHD_REG(ISP_IS_V_SIZE),
- { /* Sentinel */ },
- };
- struct rkisp1_device *rkisp1 = m->private;
- return rkisp1_debug_dump_regs(rkisp1, m, 0, registers);
- }
- DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_isp_regs);
- static int rkisp1_debug_dump_rsz_regs_show(struct seq_file *m, void *p)
- {
- static const struct rkisp1_debug_register registers[] = {
- RKISP1_DEBUG_SHD_REG(RSZ_CTRL),
- RKISP1_DEBUG_SHD_REG(RSZ_SCALE_HY),
- RKISP1_DEBUG_SHD_REG(RSZ_SCALE_HCB),
- RKISP1_DEBUG_SHD_REG(RSZ_SCALE_HCR),
- RKISP1_DEBUG_SHD_REG(RSZ_SCALE_VY),
- RKISP1_DEBUG_SHD_REG(RSZ_SCALE_VC),
- RKISP1_DEBUG_SHD_REG(RSZ_PHASE_HY),
- RKISP1_DEBUG_SHD_REG(RSZ_PHASE_HC),
- RKISP1_DEBUG_SHD_REG(RSZ_PHASE_VY),
- RKISP1_DEBUG_SHD_REG(RSZ_PHASE_VC),
- { /* Sentinel */ },
- };
- struct rkisp1_resizer *rsz = m->private;
- return rkisp1_debug_dump_regs(rsz->rkisp1, m, rsz->regs_base, registers);
- }
- DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_rsz_regs);
- static int rkisp1_debug_dump_mi_mp_show(struct seq_file *m, void *p)
- {
- static const struct rkisp1_debug_register registers[] = {
- RKISP1_DEBUG_REG(MI_MP_Y_BASE_AD_INIT),
- RKISP1_DEBUG_REG(MI_MP_Y_BASE_AD_INIT2),
- RKISP1_DEBUG_REG(MI_MP_Y_BASE_AD_SHD),
- RKISP1_DEBUG_REG(MI_MP_Y_SIZE_INIT),
- RKISP1_DEBUG_REG(MI_MP_Y_SIZE_INIT),
- RKISP1_DEBUG_REG(MI_MP_Y_SIZE_SHD),
- RKISP1_DEBUG_REG(MI_MP_Y_OFFS_CNT_SHD),
- { /* Sentinel */ },
- };
- struct rkisp1_device *rkisp1 = m->private;
- return rkisp1_debug_dump_regs(rkisp1, m, 0, registers);
- }
- DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_mi_mp);
- #define RKISP1_DEBUG_DATA_COUNT_BINS 32
- #define RKISP1_DEBUG_DATA_COUNT_STEP (4096 / RKISP1_DEBUG_DATA_COUNT_BINS)
- static int rkisp1_debug_input_status_show(struct seq_file *m, void *p)
- {
- struct rkisp1_device *rkisp1 = m->private;
- u16 data_count[RKISP1_DEBUG_DATA_COUNT_BINS] = { };
- unsigned int hsync_count = 0;
- unsigned int vsync_count = 0;
- unsigned int i;
- u32 data;
- u32 val;
- int ret;
- ret = pm_runtime_get_if_in_use(rkisp1->dev);
- if (ret <= 0)
- return ret ? : -ENODATA;
- /* Sample the ISP input port status 10000 times with a 1µs interval. */
- for (i = 0; i < 10000; ++i) {
- val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_FLAGS_SHD);
- data = (val & RKISP1_CIF_ISP_FLAGS_SHD_S_DATA_MASK)
- >> RKISP1_CIF_ISP_FLAGS_SHD_S_DATA_SHIFT;
- data_count[data / RKISP1_DEBUG_DATA_COUNT_STEP]++;
- if (val & RKISP1_CIF_ISP_FLAGS_SHD_S_HSYNC)
- hsync_count++;
- if (val & RKISP1_CIF_ISP_FLAGS_SHD_S_VSYNC)
- vsync_count++;
- udelay(1);
- }
- pm_runtime_put(rkisp1->dev);
- seq_printf(m, "vsync: %u, hsync: %u\n", vsync_count, hsync_count);
- seq_puts(m, "data:\n");
- for (i = 0; i < ARRAY_SIZE(data_count); ++i)
- seq_printf(m, "- [%04u:%04u]: %u\n",
- i * RKISP1_DEBUG_DATA_COUNT_STEP,
- (i + 1) * RKISP1_DEBUG_DATA_COUNT_STEP - 1,
- data_count[i]);
- return 0;
- }
- DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_input_status);
- void rkisp1_debug_init(struct rkisp1_device *rkisp1)
- {
- struct rkisp1_debug *debug = &rkisp1->debug;
- struct dentry *regs_dir;
- debug->debugfs_dir = debugfs_create_dir(dev_name(rkisp1->dev), NULL);
- debugfs_create_ulong("data_loss", 0444, debug->debugfs_dir,
- &debug->data_loss);
- debugfs_create_ulong("outform_size_err", 0444, debug->debugfs_dir,
- &debug->outform_size_error);
- debugfs_create_ulong("img_stabilization_size_error", 0444,
- debug->debugfs_dir,
- &debug->img_stabilization_size_error);
- debugfs_create_ulong("inform_size_error", 0444, debug->debugfs_dir,
- &debug->inform_size_error);
- debugfs_create_ulong("irq_delay", 0444, debug->debugfs_dir,
- &debug->irq_delay);
- debugfs_create_ulong("mipi_error", 0444, debug->debugfs_dir,
- &debug->mipi_error);
- debugfs_create_ulong("stats_error", 0444, debug->debugfs_dir,
- &debug->stats_error);
- debugfs_create_ulong("mp_stop_timeout", 0444, debug->debugfs_dir,
- &debug->stop_timeout[RKISP1_MAINPATH]);
- debugfs_create_ulong("sp_stop_timeout", 0444, debug->debugfs_dir,
- &debug->stop_timeout[RKISP1_SELFPATH]);
- debugfs_create_ulong("mp_frame_drop", 0444, debug->debugfs_dir,
- &debug->frame_drop[RKISP1_MAINPATH]);
- debugfs_create_ulong("sp_frame_drop", 0444, debug->debugfs_dir,
- &debug->frame_drop[RKISP1_SELFPATH]);
- debugfs_create_ulong("complete_frames", 0444, debug->debugfs_dir,
- &debug->complete_frames);
- debugfs_create_file("input_status", 0444, debug->debugfs_dir, rkisp1,
- &rkisp1_debug_input_status_fops);
- regs_dir = debugfs_create_dir("regs", debug->debugfs_dir);
- debugfs_create_file("core", 0444, regs_dir, rkisp1,
- &rkisp1_debug_dump_core_regs_fops);
- debugfs_create_file("isp", 0444, regs_dir, rkisp1,
- &rkisp1_debug_dump_isp_regs_fops);
- debugfs_create_file("mrsz", 0444, regs_dir,
- &rkisp1->resizer_devs[RKISP1_MAINPATH],
- &rkisp1_debug_dump_rsz_regs_fops);
- debugfs_create_file("srsz", 0444, regs_dir,
- &rkisp1->resizer_devs[RKISP1_SELFPATH],
- &rkisp1_debug_dump_rsz_regs_fops);
- debugfs_create_file("mi_mp", 0444, regs_dir, rkisp1,
- &rkisp1_debug_dump_mi_mp_fops);
- }
- void rkisp1_debug_cleanup(struct rkisp1_device *rkisp1)
- {
- debugfs_remove_recursive(rkisp1->debug.debugfs_dir);
- }
|