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 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 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 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 { /* Sentinel */ }, 96 }; 97 struct rkisp1_device *rkisp1 = m->private; 98 99 return rkisp1_debug_dump_regs(rkisp1, m, 0, registers); 100 } 101 DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_isp_regs); 102 103 static 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 } 122 DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_dump_rsz_regs); 123 124 static 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 } 140 DEFINE_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 145 static 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 } 188 DEFINE_SHOW_ATTRIBUTE(rkisp1_debug_input_status); 189 190 void 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 240 void rkisp1_debug_cleanup(struct rkisp1_device *rkisp1) 241 { 242 debugfs_remove_recursive(rkisp1->debug.debugfs_dir); 243 } 244