1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) Rockchip Electronics Co., Ltd. */
3 #include <linux/clk.h>
4 #include <linux/math64.h>
5 #include <linux/proc_fs.h>
6 #include <linux/sem.h>
7 #include <linux/seq_file.h>
8 #include <linux/spinlock.h>
9 #include <linux/v4l2-mediabus.h>
10
11 #include "hw.h"
12 #include "dev.h"
13 #include "procfs.h"
14
15 #ifdef CONFIG_PROC_FS
16
17 static const struct {
18 const char *name;
19 u32 mbus_code;
20 } mbus_formats[] = {
21 /* media bus code */
22 { "RGB444_1X12", MEDIA_BUS_FMT_RGB444_1X12 },
23 { "RGB444_2X8_PADHI_BE", MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE },
24 { "RGB444_2X8_PADHI_LE", MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE },
25 { "RGB555_2X8_PADHI_BE", MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE },
26 { "RGB555_2X8_PADHI_LE", MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE },
27 { "RGB565_1X16", MEDIA_BUS_FMT_RGB565_1X16 },
28 { "BGR565_2X8_BE", MEDIA_BUS_FMT_BGR565_2X8_BE },
29 { "BGR565_2X8_LE", MEDIA_BUS_FMT_BGR565_2X8_LE },
30 { "RGB565_2X8_BE", MEDIA_BUS_FMT_RGB565_2X8_BE },
31 { "RGB565_2X8_LE", MEDIA_BUS_FMT_RGB565_2X8_LE },
32 { "RGB666_1X18", MEDIA_BUS_FMT_RGB666_1X18 },
33 { "RBG888_1X24", MEDIA_BUS_FMT_RBG888_1X24 },
34 { "RGB666_1X24_CPADHI", MEDIA_BUS_FMT_RGB666_1X24_CPADHI },
35 { "RGB666_1X7X3_SPWG", MEDIA_BUS_FMT_RGB666_1X7X3_SPWG },
36 { "BGR888_1X24", MEDIA_BUS_FMT_BGR888_1X24 },
37 { "GBR888_1X24", MEDIA_BUS_FMT_GBR888_1X24 },
38 { "RGB888_1X24", MEDIA_BUS_FMT_RGB888_1X24 },
39 { "RGB888_2X12_BE", MEDIA_BUS_FMT_RGB888_2X12_BE },
40 { "RGB888_2X12_LE", MEDIA_BUS_FMT_RGB888_2X12_LE },
41 { "RGB888_1X7X4_SPWG", MEDIA_BUS_FMT_RGB888_1X7X4_SPWG },
42 { "RGB888_1X7X4_JEIDA", MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA },
43 { "ARGB8888_1X32", MEDIA_BUS_FMT_ARGB8888_1X32 },
44 { "RGB888_1X32_PADHI", MEDIA_BUS_FMT_RGB888_1X32_PADHI },
45 { "RGB101010_1X30", MEDIA_BUS_FMT_RGB101010_1X30 },
46 { "RGB121212_1X36", MEDIA_BUS_FMT_RGB121212_1X36 },
47 { "RGB161616_1X48", MEDIA_BUS_FMT_RGB161616_1X48 },
48 { "Y8_1X8", MEDIA_BUS_FMT_Y8_1X8 },
49 { "UV8_1X8", MEDIA_BUS_FMT_UV8_1X8 },
50 { "UYVY8_1_5X8", MEDIA_BUS_FMT_UYVY8_1_5X8 },
51 { "VYUY8_1_5X8", MEDIA_BUS_FMT_VYUY8_1_5X8 },
52 { "YUYV8_1_5X8", MEDIA_BUS_FMT_YUYV8_1_5X8 },
53 { "YVYU8_1_5X8", MEDIA_BUS_FMT_YVYU8_1_5X8 },
54 { "UYVY8_2X8", MEDIA_BUS_FMT_UYVY8_2X8 },
55 { "VYUY8_2X8", MEDIA_BUS_FMT_VYUY8_2X8 },
56 { "YUYV8_2X8", MEDIA_BUS_FMT_YUYV8_2X8 },
57 { "YVYU8_2X8", MEDIA_BUS_FMT_YVYU8_2X8 },
58 { "Y10_1X10", MEDIA_BUS_FMT_Y10_1X10 },
59 { "Y10_2X8_PADHI_LE", MEDIA_BUS_FMT_Y10_2X8_PADHI_LE },
60 { "UYVY10_2X10", MEDIA_BUS_FMT_UYVY10_2X10 },
61 { "VYUY10_2X10", MEDIA_BUS_FMT_VYUY10_2X10 },
62 { "YUYV10_2X10", MEDIA_BUS_FMT_YUYV10_2X10 },
63 { "YVYU10_2X10", MEDIA_BUS_FMT_YVYU10_2X10 },
64 { "Y12_1X12", MEDIA_BUS_FMT_Y12_1X12 },
65 { "UYVY12_2X12", MEDIA_BUS_FMT_UYVY12_2X12 },
66 { "VYUY12_2X12", MEDIA_BUS_FMT_VYUY12_2X12 },
67 { "YUYV12_2X12", MEDIA_BUS_FMT_YUYV12_2X12 },
68 { "YVYU12_2X12", MEDIA_BUS_FMT_YVYU12_2X12 },
69 { "UYVY8_1X16", MEDIA_BUS_FMT_UYVY8_1X16 },
70 { "VYUY8_1X16", MEDIA_BUS_FMT_VYUY8_1X16 },
71 { "YUYV8_1X16", MEDIA_BUS_FMT_YUYV8_1X16 },
72 { "YVYU8_1X16", MEDIA_BUS_FMT_YVYU8_1X16 },
73 { "YDYUYDYV8_1X16", MEDIA_BUS_FMT_YDYUYDYV8_1X16 },
74 { "UYVY10_1X20", MEDIA_BUS_FMT_UYVY10_1X20 },
75 { "VYUY10_1X20", MEDIA_BUS_FMT_VYUY10_1X20 },
76 { "YUYV10_1X20", MEDIA_BUS_FMT_YUYV10_1X20 },
77 { "YVYU10_1X20", MEDIA_BUS_FMT_YVYU10_1X20 },
78 { "VUY8_1X24", MEDIA_BUS_FMT_VUY8_1X24 },
79 { "YUV8_1X24", MEDIA_BUS_FMT_YUV8_1X24 },
80 { "UYYVYY8_0_5X24", MEDIA_BUS_FMT_UYYVYY8_0_5X24 },
81 { "UYVY12_1X24", MEDIA_BUS_FMT_UYVY12_1X24 },
82 { "VYUY12_1X24", MEDIA_BUS_FMT_VYUY12_1X24 },
83 { "YUYV12_1X24", MEDIA_BUS_FMT_YUYV12_1X24 },
84 { "YVYU12_1X24", MEDIA_BUS_FMT_YVYU12_1X24 },
85 { "YUV10_1X30", MEDIA_BUS_FMT_YUV10_1X30 },
86 { "UYYVYY10_0_5X30", MEDIA_BUS_FMT_UYYVYY10_0_5X30 },
87 { "AYUV8_1X32", MEDIA_BUS_FMT_AYUV8_1X32 },
88 { "UYYVYY12_0_5X36", MEDIA_BUS_FMT_UYYVYY12_0_5X36 },
89 { "YUV12_1X36", MEDIA_BUS_FMT_YUV12_1X36 },
90 { "YUV16_1X48", MEDIA_BUS_FMT_YUV16_1X48 },
91 { "UYYVYY16_0_5X48", MEDIA_BUS_FMT_UYYVYY16_0_5X48 },
92 { "SBGGR8_1X8", MEDIA_BUS_FMT_SBGGR8_1X8 },
93 { "SGBRG8_1X8", MEDIA_BUS_FMT_SGBRG8_1X8 },
94 { "SGRBG8_1X8", MEDIA_BUS_FMT_SGRBG8_1X8 },
95 { "SRGGB8_1X8", MEDIA_BUS_FMT_SRGGB8_1X8 },
96 { "SBGGR10_ALAW8_1X8", MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8 },
97 { "SGBRG10_ALAW8_1X8", MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8 },
98 { "SGRBG10_ALAW8_1X8", MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8 },
99 { "SRGGB10_ALAW8_1X8", MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8 },
100 { "SBGGR10_DPCM8_1X8", MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8 },
101 { "SGBRG10_DPCM8_1X8", MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8 },
102 { "SGRBG10_DPCM8_1X8", MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8 },
103 { "SRGGB10_DPCM8_1X8", MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8 },
104 { "SBGGR10_2X8_PADHI_BE", MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE },
105 { "SBGGR10_2X8_PADHI_LE", MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE },
106 { "SBGGR10_2X8_PADLO_BE", MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE },
107 { "SBGGR10_2X8_PADLO_LE", MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE },
108 { "SBGGR10_1X10", MEDIA_BUS_FMT_SBGGR10_1X10 },
109 { "SGBRG10_1X10", MEDIA_BUS_FMT_SGBRG10_1X10 },
110 { "SGRBG10_1X10", MEDIA_BUS_FMT_SGRBG10_1X10 },
111 { "SRGGB10_1X10", MEDIA_BUS_FMT_SRGGB10_1X10 },
112 { "SBGGR12_1X12", MEDIA_BUS_FMT_SBGGR12_1X12 },
113 { "SGBRG12_1X12", MEDIA_BUS_FMT_SGBRG12_1X12 },
114 { "SGRBG12_1X12", MEDIA_BUS_FMT_SGRBG12_1X12 },
115 { "SRGGB12_1X12", MEDIA_BUS_FMT_SRGGB12_1X12 },
116 { "SBGGR14_1X14", MEDIA_BUS_FMT_SBGGR14_1X14 },
117 { "SGBRG14_1X14", MEDIA_BUS_FMT_SGBRG14_1X14 },
118 { "SGRBG14_1X14", MEDIA_BUS_FMT_SGRBG14_1X14 },
119 { "SRGGB14_1X14", MEDIA_BUS_FMT_SRGGB14_1X14 },
120 { "SBGGR16_1X16", MEDIA_BUS_FMT_SBGGR16_1X16 },
121 { "SGBRG16_1X16", MEDIA_BUS_FMT_SGBRG16_1X16 },
122 { "SGRBG16_1X16", MEDIA_BUS_FMT_SGRBG16_1X16 },
123 { "SRGGB16_1X16", MEDIA_BUS_FMT_SRGGB16_1X16 },
124 { "JPEG_1X8", MEDIA_BUS_FMT_JPEG_1X8 },
125 { "S5C_UYVY_JPEG_1X8", MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8 },
126 { "AHSV8888_1X32", MEDIA_BUS_FMT_AHSV8888_1X32 },
127 { "FIXED", MEDIA_BUS_FMT_FIXED },
128 { "Y8", MEDIA_BUS_FMT_Y8_1X8 },
129 { "Y10", MEDIA_BUS_FMT_Y10_1X10 },
130 { "Y12", MEDIA_BUS_FMT_Y12_1X12 },
131 { "YUYV", MEDIA_BUS_FMT_YUYV8_1X16 },
132 { "YUYV1_5X8", MEDIA_BUS_FMT_YUYV8_1_5X8 },
133 { "YUYV2X8", MEDIA_BUS_FMT_YUYV8_2X8 },
134 { "UYVY", MEDIA_BUS_FMT_UYVY8_1X16 },
135 { "UYVY1_5X8", MEDIA_BUS_FMT_UYVY8_1_5X8 },
136 { "UYVY2X8", MEDIA_BUS_FMT_UYVY8_2X8 },
137 { "VUY24", MEDIA_BUS_FMT_VUY8_1X24 },
138 { "SBGGR8", MEDIA_BUS_FMT_SBGGR8_1X8 },
139 { "SGBRG8", MEDIA_BUS_FMT_SGBRG8_1X8 },
140 { "SGRBG8", MEDIA_BUS_FMT_SGRBG8_1X8 },
141 { "SRGGB8", MEDIA_BUS_FMT_SRGGB8_1X8 },
142 { "SBGGR10", MEDIA_BUS_FMT_SBGGR10_1X10 },
143 { "SGBRG10", MEDIA_BUS_FMT_SGBRG10_1X10 },
144 { "SGRBG10", MEDIA_BUS_FMT_SGRBG10_1X10 },
145 { "SRGGB10", MEDIA_BUS_FMT_SRGGB10_1X10 },
146 { "SBGGR10_DPCM8", MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8 },
147 { "SGBRG10_DPCM8", MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8 },
148 { "SGRBG10_DPCM8", MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8 },
149 { "SRGGB10_DPCM8", MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8 },
150 { "SBGGR12", MEDIA_BUS_FMT_SBGGR12_1X12 },
151 { "SGBRG12", MEDIA_BUS_FMT_SGBRG12_1X12 },
152 { "SGRBG12", MEDIA_BUS_FMT_SGRBG12_1X12 },
153 { "SRGGB12", MEDIA_BUS_FMT_SRGGB12_1X12 },
154 { "AYUV32", MEDIA_BUS_FMT_AYUV8_1X32 },
155 { "RBG24", MEDIA_BUS_FMT_RBG888_1X24 },
156 { "RGB32", MEDIA_BUS_FMT_RGB888_1X32_PADHI },
157 { "ARGB32", MEDIA_BUS_FMT_ARGB8888_1X32 },
158
159 /* v4l2 fourcc code */
160 { "NV16", V4L2_PIX_FMT_NV16},
161 { "NV61", V4L2_PIX_FMT_NV61},
162 { "NV12", V4L2_PIX_FMT_NV12},
163 { "NV21", V4L2_PIX_FMT_NV21},
164 { "YUYV", V4L2_PIX_FMT_YUYV},
165 { "YVYU", V4L2_PIX_FMT_YVYU},
166 { "UYVY", V4L2_PIX_FMT_UYVY},
167 { "VYUY", V4L2_PIX_FMT_VYUY},
168 { "RGB3", V4L2_PIX_FMT_RGB24},
169 { "RGBP", V4L2_PIX_FMT_RGB565},
170 { "BGRH", V4L2_PIX_FMT_BGR666},
171 { "RGGB", V4L2_PIX_FMT_SRGGB8},
172 { "GRBG", V4L2_PIX_FMT_SGRBG8},
173 { "GBRG", V4L2_PIX_FMT_SGBRG8},
174 { "BA81", V4L2_PIX_FMT_SBGGR8},
175 { "RG10", V4L2_PIX_FMT_SRGGB10},
176 { "BA10", V4L2_PIX_FMT_SGRBG10},
177 { "GB10", V4L2_PIX_FMT_SGBRG10},
178 { "BG10", V4L2_PIX_FMT_SBGGR10},
179 { "RG12", V4L2_PIX_FMT_SRGGB12},
180 { "BA12", V4L2_PIX_FMT_SGRBG12},
181 { "GB12", V4L2_PIX_FMT_SGBRG12},
182 { "BG12", V4L2_PIX_FMT_SBGGR12},
183 { "BYR2", V4L2_PIX_FMT_SBGGR16},
184 { "Y16 ", V4L2_PIX_FMT_Y16},
185 };
186
rkcif_pixelcode_to_string(u32 mbus_code)187 static const char *rkcif_pixelcode_to_string(u32 mbus_code)
188 {
189 unsigned int i;
190
191 for (i = 0; i < ARRAY_SIZE(mbus_formats); ++i) {
192 if (mbus_formats[i].mbus_code == mbus_code)
193 return mbus_formats[i].name;
194 }
195
196 return "unknown";
197 }
198
rkcif_get_monitor_mode(enum rkcif_monitor_mode monitor_mode)199 static const char *rkcif_get_monitor_mode(enum rkcif_monitor_mode monitor_mode)
200 {
201 switch (monitor_mode) {
202 case RKCIF_MONITOR_MODE_IDLE:
203 return "idle";
204 case RKCIF_MONITOR_MODE_CONTINUE:
205 return "continue";
206 case RKCIF_MONITOR_MODE_TRIGGER:
207 return "trigger";
208 case RKCIF_MONITOR_MODE_HOTPLUG:
209 return "hotplug";
210 default:
211 return "unknown";
212 }
213 }
214
rkcif_show_mixed_info(struct rkcif_device * dev,struct seq_file * f)215 static void rkcif_show_mixed_info(struct rkcif_device *dev, struct seq_file *f)
216 {
217 enum rkcif_monitor_mode monitor_mode;
218
219 seq_printf(f, "Driver Version:v%02x.%02x.%02x\n",
220 RKCIF_DRIVER_VERSION >> 16,
221 (RKCIF_DRIVER_VERSION & 0xff00) >> 8,
222 RKCIF_DRIVER_VERSION & 0x00ff);
223 seq_printf(f, "Work Mode:%s\n",
224 dev->workmode == RKCIF_WORKMODE_ONEFRAME ? "one frame" :
225 dev->workmode == RKCIF_WORKMODE_PINGPONG ? "ping pong" : "line loop");
226
227 monitor_mode = dev->reset_watchdog_timer.monitor_mode;
228 seq_printf(f, "Monitor Mode:%s\n",
229 rkcif_get_monitor_mode(monitor_mode));
230 }
231
rkcif_show_clks(struct rkcif_device * dev,struct seq_file * f)232 static void rkcif_show_clks(struct rkcif_device *dev, struct seq_file *f)
233 {
234 int i;
235 struct rkcif_hw *hw = dev->hw_dev;
236
237 for (i = 0; i < hw->clk_size; i++) {
238 seq_printf(f, "%s:%ld\n",
239 hw->match_data->clks[i],
240 clk_get_rate(hw->clks[i]));
241 }
242 }
243
rkcif_show_format(struct rkcif_device * dev,struct seq_file * f)244 static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f)
245 {
246 struct rkcif_stream *stream = &dev->stream[0];
247 struct rkcif_pipeline *pipe = &dev->pipe;
248 struct rkcif_sensor_info *sensor = &dev->terminal_sensor;
249 struct v4l2_rect *rect = &sensor->raw_rect;
250 struct v4l2_subdev_frame_interval *interval = &sensor->fi;
251 struct v4l2_subdev_selection *sel = &sensor->selection;
252 u32 i, mbus_flags;
253 u64 fps, timestamp0, timestamp1;
254 unsigned long flags;
255 u32 time_val = 0;
256
257 if (atomic_read(&pipe->stream_cnt) < 1)
258 return;
259
260 if (sensor) {
261 seq_puts(f, "Input Info:\n");
262
263 seq_printf(f, "\tsrc subdev:%s\n", sensor->sd->name);
264 mbus_flags = sensor->mbus.flags;
265 if (sensor->mbus.type == V4L2_MBUS_PARALLEL ||
266 sensor->mbus.type == V4L2_MBUS_BT656) {
267 seq_printf(f, "\tinterface:%s\n",
268 sensor->mbus.type == V4L2_MBUS_PARALLEL ? "BT601" : "BT656/BT1120");
269 seq_printf(f, "\thref_pol:%s\n",
270 mbus_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH ? "high active" : "low active");
271 seq_printf(f, "\tvsync_pol:%s\n",
272 mbus_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH ? "high active" : "low active");
273 } else {
274 seq_printf(f, "\tinterface:%s\n",
275 sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ? "mipi csi2 dphy" :
276 sensor->mbus.type == V4L2_MBUS_CSI2_CPHY ? "mipi csi2 cphy" :
277 sensor->mbus.type == V4L2_MBUS_CCP2 ? "lvds" : "unknown");
278 seq_printf(f, "\tlanes:%d\n", sensor->lanes);
279 seq_puts(f, "\tvc channel:");
280 if (mbus_flags & V4L2_MBUS_CSI2_CHANNELS) {
281 for (i = 0; i < 4; i++) {
282 if ((mbus_flags >> (4 + i)) & 0x1)
283 seq_printf(f, " %d", i);
284 }
285 seq_puts(f, "\n");
286 } else {
287 seq_puts(f, "unknown\n");
288 }
289 }
290
291 seq_printf(f, "\thdr mode: %s\n",
292 dev->hdr.hdr_mode == NO_HDR ? "normal" :
293 dev->hdr.hdr_mode == HDR_X2 ? "hdr_x2" : "hdr_x3");
294
295 seq_printf(f, "\tformat:%s/%ux%u@%d\n",
296 rkcif_pixelcode_to_string(stream->cif_fmt_in->mbus_code),
297 rect->width, rect->height,
298 interval->interval.denominator / interval->interval.numerator);
299
300 seq_printf(f, "\tcrop.bounds:(%u, %u)/%ux%u\n",
301 sel->r.left, sel->r.top,
302 sel->r.width, sel->r.height);
303
304 spin_lock_irqsave(&stream->fps_lock, flags);
305 timestamp0 = stream->fps_stats.frm0_timestamp;
306 timestamp1 = stream->fps_stats.frm1_timestamp;
307 spin_unlock_irqrestore(&stream->fps_lock, flags);
308 fps = timestamp0 > timestamp1 ?
309 timestamp0 - timestamp1 : timestamp1 - timestamp0;
310 fps = div_u64(fps, 1000000);
311
312 seq_puts(f, "Output Info:\n");
313 seq_printf(f, "\tformat:%s/%ux%u(%u,%u)\n",
314 rkcif_pixelcode_to_string(stream->cif_fmt_out->fourcc),
315 dev->channels[0].width, dev->channels[0].height,
316 dev->channels[0].crop_st_x, dev->channels[0].crop_st_y);
317 seq_printf(f, "\tcompact:%s\n", stream->is_compact ? "enable" : "disabled");
318 seq_printf(f, "\tframe amount:%d\n", stream->frame_idx);
319 if (dev->inf_id == RKCIF_MIPI_LVDS) {
320 time_val = div_u64(stream->readout.early_time, 1000000);
321 seq_printf(f, "\tearly:%u ms\n", time_val);
322 if (dev->hdr.hdr_mode == NO_HDR) {
323 time_val = div_u64(stream->readout.readout_time, 1000000);
324 seq_printf(f, "\treadout:%u ms\n", time_val);
325 } else {
326 time_val = div_u64(stream->readout.readout_time, 1000000);
327 seq_printf(f, "\tsingle readout:%u ms\n", time_val);
328 time_val = div_u64(stream->readout.total_time, 1000000);
329 seq_printf(f, "\ttotal readout:%u ms\n", time_val);
330
331 }
332 }
333 seq_printf(f, "\trate:%llu ms\n", fps);
334 fps = div_u64(1000, fps);
335 seq_printf(f, "\tfps:%llu\n", fps);
336 seq_puts(f, "\tirq statistics:\n");
337 seq_printf(f, "\t\t\ttotal:%llu\n",
338 dev->irq_stats.all_frm_end_cnt + dev->irq_stats.all_err_cnt);
339 if (sensor->mbus.type == V4L2_MBUS_PARALLEL ||
340 sensor->mbus.type == V4L2_MBUS_BT656) {
341 seq_printf(f, "\t\t\tdvp bus err:%llu\n", dev->irq_stats.dvp_bus_err_cnt);
342 seq_printf(f, "\t\t\tdvp pix err:%llu\n", dev->irq_stats.dvp_pix_err_cnt);
343 seq_printf(f, "\t\t\tdvp line err:%llu\n", dev->irq_stats.dvp_line_err_cnt);
344 seq_printf(f, "\t\t\tdvp over flow:%llu\n", dev->irq_stats.dvp_overflow_cnt);
345 seq_printf(f, "\t\t\tdvp bandwidth lack:%llu\n", dev->irq_stats.dvp_bwidth_lack_cnt);
346 seq_printf(f, "\t\t\tdvp size err:%llu\n", dev->irq_stats.dvp_size_err_cnt);
347 } else {
348 seq_printf(f, "\t\t\tcsi over flow:%llu\n", dev->irq_stats.csi_overflow_cnt);
349 seq_printf(f, "\t\t\tcsi bandwidth lack:%llu\n", dev->irq_stats.csi_bwidth_lack_cnt);
350 seq_printf(f, "\t\t\tcsi size err:%llu\n", dev->irq_stats.csi_size_err_cnt);
351 }
352 seq_printf(f, "\t\t\tall err count:%llu\n", dev->irq_stats.all_err_cnt);
353 seq_printf(f, "\t\t\tframe dma end:%llu\n", dev->irq_stats.all_frm_end_cnt);
354 }
355 }
356
rkcif_proc_show(struct seq_file * f,void * v)357 static int rkcif_proc_show(struct seq_file *f, void *v)
358 {
359 struct rkcif_device *dev = f->private;
360
361 if (dev) {
362 rkcif_show_mixed_info(dev, f);
363 rkcif_show_clks(dev, f);
364 rkcif_show_format(dev, f);
365 } else {
366 seq_puts(f, "dev null\n");
367 }
368
369 return 0;
370 }
371
rkcif_proc_open(struct inode * inode,struct file * file)372 static int rkcif_proc_open(struct inode *inode, struct file *file)
373 {
374 struct rkcif_device *data = PDE_DATA(inode);
375
376 return single_open(file, rkcif_proc_show, data);
377 }
378
379 static const struct proc_ops rkcif_proc_fops = {
380 .proc_open = rkcif_proc_open,
381 .proc_release = single_release,
382 .proc_read = seq_read,
383 .proc_lseek = seq_lseek,
384 };
385
rkcif_proc_init(struct rkcif_device * dev)386 int rkcif_proc_init(struct rkcif_device *dev)
387 {
388
389 dev->proc_dir = proc_create_data(dev_name(dev->dev), 0444,
390 NULL, &rkcif_proc_fops,
391 dev);
392 if (!dev->proc_dir) {
393 dev_err(dev->dev, "create proc/%s failed!\n",
394 dev_name(dev->dev));
395 return -ENODEV;
396 }
397
398 return 0;
399 }
400
rkcif_proc_cleanup(struct rkcif_device * dev)401 void rkcif_proc_cleanup(struct rkcif_device *dev)
402 {
403 remove_proc_entry(dev_name(dev->dev), NULL);
404 }
405
406 #endif
407