[PATCH 8/8] media: chips-media: wave6: Improve debugging capabilities

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add debugfs entries and trace events to provide detailed
debugging information.
These enhancements help diagnose issues and improve debugging
capabilities for the Wave6 driver.

Signed-off-by: Nas Chung <nas.chung@xxxxxxxxxxxxxxx>
---
 .../platform/chips-media/wave6/wave6-trace.h  | 336 ++++++++++++++++++
 .../chips-media/wave6/wave6-vpu-dbg.c         | 230 ++++++++++++
 .../chips-media/wave6/wave6-vpu-dbg.h         |  22 ++
 3 files changed, 588 insertions(+)
 create mode 100644 drivers/media/platform/chips-media/wave6/wave6-trace.h
 create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
 create mode 100644 drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h

diff --git a/drivers/media/platform/chips-media/wave6/wave6-trace.h b/drivers/media/platform/chips-media/wave6/wave6-trace.h
new file mode 100644
index 000000000000..8ddba6926c60
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-trace.h
@@ -0,0 +1,336 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave6 series multi-standard codec IP - wave6 driver tracer
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM wave6
+
+#if !defined(__WAVE6_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
+#define __WAVE6_TRACE_H__
+
+#include <linux/tracepoint.h>
+#include <media/videobuf2-v4l2.h>
+
+DECLARE_EVENT_CLASS(register_access,
+	TP_PROTO(struct device *dev, u32 addr, u32 value),
+	TP_ARGS(dev, addr, value),
+	TP_STRUCT__entry(
+		__string(name, dev_name(dev))
+		__field(u32, addr)
+		__field(u32, value)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(dev));
+		__entry->addr = addr;
+		__entry->value = value;
+	),
+	TP_printk("%s:0x%03x 0x%08x", __get_str(name), __entry->addr, __entry->value)
+);
+
+DEFINE_EVENT(register_access, writel,
+	TP_PROTO(struct device *dev, u32 addr, u32 value),
+	TP_ARGS(dev, addr, value));
+DEFINE_EVENT(register_access, readl,
+	TP_PROTO(struct device *dev, u32 addr, u32 value),
+	TP_ARGS(dev, addr, value));
+
+TRACE_EVENT(send_command,
+	TP_PROTO(struct vpu_device *vpu_dev, u32 id, u32 std, u32 cmd),
+	TP_ARGS(vpu_dev, id, std, cmd),
+	TP_STRUCT__entry(
+		__string(name, dev_name(vpu_dev->dev))
+		__field(u32, id)
+		__field(u32, std)
+		__field(u32, cmd)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(vpu_dev->dev));
+		__entry->id = id;
+		__entry->std = std;
+		__entry->cmd = cmd;
+	),
+	TP_printk("%s: inst id %d, std 0x%x, cmd 0x%x",
+		  __get_str(name), __entry->id, __entry->std, __entry->cmd)
+);
+
+TRACE_EVENT(irq,
+	TP_PROTO(struct vpu_device *vpu_dev, u32 irq),
+	TP_ARGS(vpu_dev, irq),
+	TP_STRUCT__entry(
+		__string(name, dev_name(vpu_dev->dev))
+		__field(u32, irq)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(vpu_dev->dev));
+		__entry->irq = irq;
+	),
+	TP_printk("%s: irq 0x%x", __get_str(name), __entry->irq)
+);
+
+TRACE_EVENT(set_state,
+	TP_PROTO(struct vpu_instance *inst, u32 state),
+	TP_ARGS(inst, state),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__string(cur_state, wave6_vpu_instance_state_name(inst->state))
+		__string(nxt_state, wave6_vpu_instance_state_name(state))
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__assign_str(cur_state, wave6_vpu_instance_state_name(inst->state));
+		__assign_str(nxt_state, wave6_vpu_instance_state_name(state));
+	),
+	TP_printk("%s: inst[%d] set state %s -> %s",
+		  __get_str(name), __entry->id, __get_str(cur_state), __get_str(nxt_state))
+);
+
+DECLARE_EVENT_CLASS(inst_internal,
+	TP_PROTO(struct vpu_instance *inst, u32 type),
+	TP_ARGS(inst, type),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__string(type, V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture")
+		__field(u32, pixelformat)
+		__field(u32, width)
+		__field(u32, height)
+		__field(u32, buf_cnt_src)
+		__field(u32, buf_cnt_dst)
+		__field(u32, processed_cnt)
+		__field(u32, error_cnt)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__assign_str(type, V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture");
+		__entry->pixelformat = V4L2_TYPE_IS_OUTPUT(type) ? inst->src_fmt.pixelformat :
+								   inst->dst_fmt.pixelformat;
+		__entry->width = V4L2_TYPE_IS_OUTPUT(type) ? inst->src_fmt.width :
+							     inst->dst_fmt.width;
+		__entry->height = V4L2_TYPE_IS_OUTPUT(type) ? inst->src_fmt.height :
+							      inst->dst_fmt.height;
+		__entry->buf_cnt_src = inst->queued_src_buf_num;
+		__entry->buf_cnt_dst = inst->queued_dst_buf_num;
+		__entry->processed_cnt = inst->processed_buf_num;
+		__entry->error_cnt = inst->error_buf_num;
+	),
+	TP_printk("%s: inst[%d] %s %c%c%c%c %dx%d, input %d, %d, process %d, error %d",
+		  __get_str(name), __entry->id, __get_str(type),
+		  __entry->pixelformat,
+		  __entry->pixelformat >> 8,
+		  __entry->pixelformat >> 16,
+		  __entry->pixelformat >> 24,
+		  __entry->width, __entry->height,
+		  __entry->buf_cnt_src, __entry->buf_cnt_dst,
+		  __entry->processed_cnt, __entry->error_cnt)
+);
+
+DEFINE_EVENT(inst_internal, start_streaming,
+	TP_PROTO(struct vpu_instance *inst, u32 type),
+	TP_ARGS(inst, type));
+
+DEFINE_EVENT(inst_internal, stop_streaming,
+	TP_PROTO(struct vpu_instance *inst, u32 type),
+	TP_ARGS(inst, type));
+
+TRACE_EVENT(dec_pic,
+	TP_PROTO(struct vpu_instance *inst, u32 srcidx, u32 size),
+	TP_ARGS(inst, srcidx, size),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__field(u32, srcidx)
+		__field(u32, start)
+		__field(u32, size)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__entry->srcidx = srcidx;
+		__entry->start = inst->codec_info->dec_info.stream_rd_ptr;
+		__entry->size = size;
+	),
+	TP_printk("%s: inst[%d] src[%2d] %8x, %d",
+		  __get_str(name), __entry->id, __entry->srcidx, __entry->start, __entry->size)
+);
+
+TRACE_EVENT(source_change,
+	TP_PROTO(struct vpu_instance *inst, struct dec_initial_info *info),
+	TP_ARGS(inst, info),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__field(u32, width)
+		__field(u32, height)
+		__field(u32, profile)
+		__field(u32, level)
+		__field(u32, tier)
+		__field(u32, min_fb_cnt)
+		__field(u32, disp_delay)
+		__field(u32, quantization)
+		__field(u32, colorspace)
+		__field(u32, xfer_func)
+		__field(u32, ycbcr_enc)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__entry->width = info->pic_width,
+		__entry->height = info->pic_height,
+		__entry->profile = info->profile,
+		__entry->level = info->level;
+		__entry->tier = info->tier;
+		__entry->min_fb_cnt = info->min_frame_buffer_count;
+		__entry->disp_delay = info->frame_buf_delay;
+		__entry->quantization = inst->quantization;
+		__entry->colorspace = inst->colorspace;
+		__entry->xfer_func = inst->xfer_func;
+		__entry->ycbcr_enc = inst->ycbcr_enc;
+	),
+	TP_printk("%s: inst[%d] %dx%d profile %d, %d, %d min_fb %d, delay %d, color %d,%d,%d,%d",
+		  __get_str(name), __entry->id,
+		  __entry->width, __entry->height,
+		  __entry->profile, __entry->level, __entry->tier,
+		  __entry->min_fb_cnt, __entry->disp_delay,
+		  __entry->quantization,
+		  __entry->colorspace, __entry->xfer_func, __entry->ycbcr_enc)
+);
+
+TRACE_EVENT(dec_done,
+	TP_PROTO(struct vpu_instance *inst, struct dec_output_info *info),
+	TP_ARGS(inst, info),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__field(u32, dec_flag)
+		__field(u32, dec_poc)
+		__field(u32, disp_flag)
+		__field(u32, disp_cnt)
+		__field(u32, rel_cnt)
+		__field(u32, src_ch)
+		__field(u32, eos)
+		__field(u32, error)
+		__field(u32, warn)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__entry->dec_flag = info->frame_decoded;
+		__entry->dec_poc = info->decoded_poc;
+		__entry->disp_flag = info->frame_display;
+		__entry->disp_cnt = info->disp_frame_num;
+		__entry->rel_cnt = info->release_disp_frame_num;
+		__entry->src_ch = info->notification_flags & DEC_NOTI_FLAG_SEQ_CHANGE;
+		__entry->eos = info->stream_end;
+		__entry->error = info->error_reason;
+		__entry->warn = info->warn_info;
+	),
+	TP_printk("%s: inst[%d] dec %d %d; disp %d(%d); rel %d, src_ch %d, eos %d, error 0x%x 0x%x",
+		  __get_str(name), __entry->id,
+		  __entry->dec_flag, __entry->dec_poc,
+		  __entry->disp_flag, __entry->disp_cnt,
+		  __entry->rel_cnt,
+		  __entry->src_ch, __entry->eos,
+		  __entry->error, __entry->warn)
+);
+
+TRACE_EVENT(enc_pic,
+	TP_PROTO(struct vpu_instance *inst, struct enc_param *param),
+	TP_ARGS(inst, param),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__field(u32, srcidx)
+		__field(u32, buf_y)
+		__field(u32, buf_cb)
+		__field(u32, buf_cr)
+		__field(u32, stride)
+		__field(u32, buf_strm)
+		__field(u32, size_strm)
+		__field(u32, force_type_enable)
+		__field(u32, force_type)
+		__field(u32, end_flag)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__entry->srcidx = param->src_idx;
+		__entry->buf_y = param->source_frame->buf_y;
+		__entry->buf_cb = param->source_frame->buf_cb;
+		__entry->buf_cr = param->source_frame->buf_cr;
+		__entry->stride = param->source_frame->stride;
+		__entry->buf_strm = param->pic_stream_buffer_addr;
+		__entry->size_strm = param->pic_stream_buffer_size;
+		__entry->force_type_enable = param->force_pic_type_enable;
+		__entry->force_type = param->force_pic_type;
+		__entry->end_flag = param->src_end;
+	),
+	TP_printk("%s: inst[%d] src[%2d] %8x %8x %8x (%d); dst %8x(%d); force type %d(%d), end %d",
+		  __get_str(name), __entry->id, __entry->srcidx,
+		  __entry->buf_y, __entry->buf_cb, __entry->buf_cr, __entry->stride,
+		  __entry->buf_strm, __entry->size_strm,
+		  __entry->force_type_enable, __entry->force_type,
+		  __entry->end_flag)
+);
+
+TRACE_EVENT(enc_done,
+	TP_PROTO(struct vpu_instance *inst, struct enc_output_info *info),
+	TP_ARGS(inst, info),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__field(u32, srcidx)
+		__field(u32, frmidx)
+		__field(u32, size)
+		__field(u32, type)
+		__field(u32, avg_qp)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__entry->srcidx = info->enc_src_idx;
+		__entry->frmidx = info->recon_frame_index;
+		__entry->size = info->bitstream_size;
+		__entry->type = info->pic_type;
+		__entry->avg_qp = info->avg_ctu_qp;
+	),
+	TP_printk("%s: inst[%d] src %d, frame %d, size %d, type %d, qp %d, eos %d",
+		  __get_str(name), __entry->id,
+		  __entry->srcidx, __entry->frmidx,
+		  __entry->size, __entry->type, __entry->avg_qp,
+		  __entry->frmidx == RECON_IDX_FLAG_ENC_END)
+);
+
+TRACE_EVENT(s_ctrl,
+	TP_PROTO(struct vpu_instance *inst, struct v4l2_ctrl *ctrl),
+	TP_ARGS(inst, ctrl),
+	TP_STRUCT__entry(
+		__string(name, dev_name(inst->dev->dev))
+		__field(u32, id)
+		__string(ctrl_name, ctrl->name)
+		__field(u32, val)
+	),
+	TP_fast_assign(
+		__assign_str(name, dev_name(inst->dev->dev));
+		__entry->id = inst->id;
+		__assign_str(ctrl_name, ctrl->name);
+		__entry->val = ctrl->val;
+	),
+	TP_printk("%s: inst[%d] %s = %d",
+		  __get_str(name), __entry->id, __get_str(ctrl_name), __entry->val)
+);
+
+#endif /* __WAVE6_TRACE_H__ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE wave6-trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
new file mode 100644
index 000000000000..40fe75c08eeb
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave6 series multi-standard codec IP - debug interface
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#include <linux/types.h>
+#include <linux/debugfs.h>
+#include "wave6-vpu.h"
+#include "wave6-vpu-dbg.h"
+
+static int wave6_vpu_dbg_instance(struct seq_file *s, void *data)
+{
+	struct vpu_instance *inst = s->private;
+	struct vpu_performance_info *perf = &inst->performance;
+	struct vb2_queue *vq;
+	char str[128];
+	int num;
+	s64 tmp;
+	s64 fps;
+
+	if (!inst->v4l2_fh.m2m_ctx)
+		return 0;
+
+	num = scnprintf(str, sizeof(str), "[%s]\n",
+			inst->type == VPU_INST_TYPE_DEC ? "Decoder" : "Encoder");
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str), "%s : product 0x%x, fw_ver %d.%d.%d(r%d), hw_ver 0x%x\n",
+			dev_name(inst->dev->dev), inst->dev->product_code,
+			(inst->dev->fw_version >> 24) & 0xFF,
+			(inst->dev->fw_version >> 16) & 0xFF,
+			(inst->dev->fw_version >> 0) & 0xFFFF,
+			inst->dev->fw_revision, inst->dev->hw_version);
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str), "state = %s, pause request %d\n",
+			wave6_vpu_instance_state_name(inst->state),
+			inst->dev->pause_request);
+	if (seq_write(s, str, num))
+		return 0;
+
+	vq = v4l2_m2m_get_src_vq(inst->v4l2_fh.m2m_ctx);
+	num = scnprintf(str, sizeof(str),
+			"output (%2d, %2d): fmt = %c%c%c%c %d x %d, %d;\n",
+			vb2_is_streaming(vq),
+			vb2_get_num_buffers(vq),
+			inst->src_fmt.pixelformat,
+			inst->src_fmt.pixelformat >> 8,
+			inst->src_fmt.pixelformat >> 16,
+			inst->src_fmt.pixelformat >> 24,
+			inst->src_fmt.width,
+			inst->src_fmt.height,
+			vq->last_buffer_dequeued);
+	if (seq_write(s, str, num))
+		return 0;
+
+	vq = v4l2_m2m_get_dst_vq(inst->v4l2_fh.m2m_ctx);
+	num = scnprintf(str, sizeof(str),
+			"capture(%2d, %2d): fmt = %c%c%c%c %d x %d, %d;\n",
+			vb2_is_streaming(vq),
+			vb2_get_num_buffers(vq),
+			inst->dst_fmt.pixelformat,
+			inst->dst_fmt.pixelformat >> 8,
+			inst->dst_fmt.pixelformat >> 16,
+			inst->dst_fmt.pixelformat >> 24,
+			inst->dst_fmt.width,
+			inst->dst_fmt.height,
+			vq->last_buffer_dequeued);
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str),
+			"capture queued %d, consumed %d, used %d\n",
+			v4l2_m2m_num_dst_bufs_ready(inst->v4l2_fh.m2m_ctx),
+			wave6_vpu_get_consumed_fb_num(inst),
+			wave6_vpu_get_used_fb_num(inst));
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str), "crop: (%d, %d) %d x %d\n",
+			inst->crop.left,
+			inst->crop.top,
+			inst->crop.width,
+			inst->crop.height);
+	if (seq_write(s, str, num))
+		return 0;
+
+	if (inst->scaler_info.enable) {
+		num = scnprintf(str, sizeof(str), "scale: %d x %d\n",
+				inst->scaler_info.width, inst->scaler_info.height);
+		if (seq_write(s, str, num))
+			return 0;
+	}
+
+	num = scnprintf(str, sizeof(str),
+			"queued src %d, dst %d, process %d, sequence %d, error %d, drain %d:%d\n",
+			inst->queued_src_buf_num,
+			inst->queued_dst_buf_num,
+			inst->processed_buf_num,
+			inst->sequence,
+			inst->error_buf_num,
+			inst->v4l2_fh.m2m_ctx->out_q_ctx.buffered,
+			inst->eos);
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str), "fps");
+	if (seq_write(s, str, num))
+		return 0;
+	tmp = MSEC_PER_SEC * inst->processed_buf_num;
+	if (perf->ts_last > perf->ts_first + NSEC_PER_MSEC) {
+		fps = DIV_ROUND_CLOSEST(tmp, (perf->ts_last - perf->ts_first) / NSEC_PER_MSEC);
+		num = scnprintf(str, sizeof(str), " actual: %lld;", fps);
+		if (seq_write(s, str, num))
+			return 0;
+	}
+	if (perf->total_sw_time) {
+		fps = DIV_ROUND_CLOSEST(tmp, perf->total_sw_time / NSEC_PER_MSEC);
+		num = scnprintf(str, sizeof(str), " sw: %lld;", fps);
+		if (seq_write(s, str, num))
+			return 0;
+	}
+	if (perf->total_hw_time) {
+		fps = DIV_ROUND_CLOSEST(tmp, perf->total_hw_time / NSEC_PER_MSEC);
+		num = scnprintf(str, sizeof(str), " hw: %lld", fps);
+		if (seq_write(s, str, num))
+			return 0;
+	}
+	num = scnprintf(str, sizeof(str), "\n");
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str),
+			"latency(ms) first: %llu.%06llu, max %llu.%06llu\n",
+			perf->latency_first / NSEC_PER_MSEC,
+			perf->latency_first % NSEC_PER_MSEC,
+			perf->latency_max / NSEC_PER_MSEC,
+			perf->latency_max % NSEC_PER_MSEC);
+	if (seq_write(s, str, num))
+		return 0;
+
+	num = scnprintf(str, sizeof(str),
+			"process frame time(ms) min: %llu.%06llu, max %llu.%06llu\n",
+			perf->min_process_time / NSEC_PER_MSEC,
+			perf->min_process_time % NSEC_PER_MSEC,
+			perf->max_process_time / NSEC_PER_MSEC,
+			perf->max_process_time % NSEC_PER_MSEC);
+	if (seq_write(s, str, num))
+		return 0;
+
+	if (inst->type == VPU_INST_TYPE_DEC) {
+		num = scnprintf(str, sizeof(str), "%s order\n",
+				inst->disp_mode == DISP_MODE_DISP_ORDER ? "display" : "decode");
+		if (seq_write(s, str, num))
+			return 0;
+	} else {
+		struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+		struct enc_codec_param *param = &p_enc_info->open_param.codec_param;
+
+		num = scnprintf(str, sizeof(str), "profile %d, level %d, tier %d\n",
+				param->profile, param->level, param->tier);
+		if (seq_write(s, str, num))
+			return 0;
+
+		num = scnprintf(str, sizeof(str), "frame_rate %d, idr_period %d, intra_period %d\n",
+				param->frame_rate, param->idr_period, param->intra_period);
+		if (seq_write(s, str, num))
+			return 0;
+
+		num = scnprintf(str, sizeof(str), "rc %d, mode %d, bitrate %d\n",
+				param->en_rate_control,
+				param->rc_mode,
+				param->bitrate);
+		if (seq_write(s, str, num))
+			return 0;
+
+		num = scnprintf(str, sizeof(str),
+				"qp %d, i_qp [%d, %d], p_qp [%d, %d], b_qp [%d, %d]\n",
+				param->qp,
+				param->min_qp_i, param->max_qp_i,
+				param->min_qp_p, param->max_qp_p,
+				param->min_qp_b, param->max_qp_b);
+		if (seq_write(s, str, num))
+			return 0;
+	}
+
+	return 0;
+}
+
+static int wave6_vpu_dbg_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, wave6_vpu_dbg_instance, inode->i_private);
+}
+
+static const struct file_operations wave6_vpu_dbg_fops = {
+	.owner = THIS_MODULE,
+	.open = wave6_vpu_dbg_open,
+	.release = single_release,
+	.read = seq_read,
+};
+
+int wave6_vpu_create_dbgfs_file(struct vpu_instance *inst)
+{
+	char name[64];
+
+	if (!inst || !inst->dev || IS_ERR_OR_NULL(inst->dev->debugfs))
+		return -EINVAL;
+
+	scnprintf(name, sizeof(name), "instance.%d", inst->id);
+	inst->debugfs = debugfs_create_file((const char *)name,
+					    VERIFY_OCTAL_PERMISSIONS(0444),
+					    inst->dev->debugfs,
+					    inst,
+					    &wave6_vpu_dbg_fops);
+
+	return 0;
+}
+
+void wave6_vpu_remove_dbgfs_file(struct vpu_instance *inst)
+{
+	if (!inst || !inst->debugfs)
+		return;
+
+	debugfs_remove(inst->debugfs);
+	inst->debugfs = NULL;
+}
diff --git a/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h
new file mode 100644
index 000000000000..fd7da1670925
--- /dev/null
+++ b/drivers/media/platform/chips-media/wave6/wave6-vpu-dbg.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave6 series multi-standard codec IP - debug interface
+ *
+ * Copyright (C) 2025 CHIPS&MEDIA INC
+ */
+
+#ifndef __WAVE6_VPU_DBG_H__
+#define __WAVE6_VPU_DBG_H__
+
+unsigned int wave6_vpu_debug(void);
+
+#define dprintk(dev, fmt, arg...)					\
+	do {								\
+		if (wave6_vpu_debug())					\
+			dev_info(dev, "%s: " fmt, __func__, ## arg);	\
+	} while (0)
+
+int wave6_vpu_create_dbgfs_file(struct vpu_instance *inst);
+void wave6_vpu_remove_dbgfs_file(struct vpu_instance *inst);
+
+#endif /* __WAVE6_VPU_DBG_H__ */
-- 
2.31.1





[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux