1*0934d375SYunfei Dong // SPDX-License-Identifier: GPL-2.0
2*0934d375SYunfei Dong /*
3*0934d375SYunfei Dong  * Copyright (c) 2023 MediaTek Inc.
4*0934d375SYunfei Dong  * Author: Yunfei Dong <yunfei.dong@mediatek.com>
5*0934d375SYunfei Dong  */
6*0934d375SYunfei Dong 
7*0934d375SYunfei Dong #include <linux/debugfs.h>
8*0934d375SYunfei Dong 
9*0934d375SYunfei Dong #include "mtk_vcodec_dbgfs.h"
10*0934d375SYunfei Dong #include "../decoder/mtk_vcodec_dec_drv.h"
11*0934d375SYunfei Dong #include "../encoder/mtk_vcodec_enc_drv.h"
12*0934d375SYunfei Dong #include "mtk_vcodec_util.h"
13*0934d375SYunfei Dong 
mtk_vdec_dbgfs_get_format_type(struct mtk_vcodec_dec_ctx * ctx,char * buf,int * used,int total)14*0934d375SYunfei Dong static void mtk_vdec_dbgfs_get_format_type(struct mtk_vcodec_dec_ctx *ctx, char *buf,
15*0934d375SYunfei Dong 					   int *used, int total)
16*0934d375SYunfei Dong {
17*0934d375SYunfei Dong 	int curr_len;
18*0934d375SYunfei Dong 
19*0934d375SYunfei Dong 	switch (ctx->current_codec) {
20*0934d375SYunfei Dong 	case V4L2_PIX_FMT_H264_SLICE:
21*0934d375SYunfei Dong 		curr_len = snprintf(buf + *used, total - *used,
22*0934d375SYunfei Dong 				    "\toutput format: h264 slice\n");
23*0934d375SYunfei Dong 		break;
24*0934d375SYunfei Dong 	case V4L2_PIX_FMT_VP8_FRAME:
25*0934d375SYunfei Dong 		curr_len = snprintf(buf + *used, total - *used,
26*0934d375SYunfei Dong 				    "\toutput format: vp8 slice\n");
27*0934d375SYunfei Dong 		break;
28*0934d375SYunfei Dong 	case V4L2_PIX_FMT_VP9_FRAME:
29*0934d375SYunfei Dong 		curr_len = snprintf(buf + *used, total - *used,
30*0934d375SYunfei Dong 				    "\toutput format: vp9 slice\n");
31*0934d375SYunfei Dong 		break;
32*0934d375SYunfei Dong 	default:
33*0934d375SYunfei Dong 		curr_len = snprintf(buf + *used, total - *used,
34*0934d375SYunfei Dong 				    "\tunsupported output format: 0x%x\n",
35*0934d375SYunfei Dong 				    ctx->current_codec);
36*0934d375SYunfei Dong 	}
37*0934d375SYunfei Dong 	*used += curr_len;
38*0934d375SYunfei Dong 
39*0934d375SYunfei Dong 	switch (ctx->capture_fourcc) {
40*0934d375SYunfei Dong 	case V4L2_PIX_FMT_MM21:
41*0934d375SYunfei Dong 		curr_len = snprintf(buf + *used, total - *used,
42*0934d375SYunfei Dong 				    "\tcapture format: MM21\n");
43*0934d375SYunfei Dong 		break;
44*0934d375SYunfei Dong 	case V4L2_PIX_FMT_MT21C:
45*0934d375SYunfei Dong 		curr_len = snprintf(buf + *used, total - *used,
46*0934d375SYunfei Dong 				    "\tcapture format: MT21C\n");
47*0934d375SYunfei Dong 		break;
48*0934d375SYunfei Dong 	default:
49*0934d375SYunfei Dong 		curr_len = snprintf(buf + *used, total - *used,
50*0934d375SYunfei Dong 				    "\tunsupported capture format: 0x%x\n",
51*0934d375SYunfei Dong 				    ctx->capture_fourcc);
52*0934d375SYunfei Dong 	}
53*0934d375SYunfei Dong 	*used += curr_len;
54*0934d375SYunfei Dong }
55*0934d375SYunfei Dong 
mtk_vdec_dbgfs_get_help(char * buf,int * used,int total)56*0934d375SYunfei Dong static void mtk_vdec_dbgfs_get_help(char *buf, int *used, int total)
57*0934d375SYunfei Dong {
58*0934d375SYunfei Dong 	int curr_len;
59*0934d375SYunfei Dong 
60*0934d375SYunfei Dong 	curr_len = snprintf(buf + *used, total - *used,
61*0934d375SYunfei Dong 			    "help: (1: echo -'info' > vdec 2: cat vdec)\n");
62*0934d375SYunfei Dong 	*used += curr_len;
63*0934d375SYunfei Dong 
64*0934d375SYunfei Dong 	curr_len = snprintf(buf + *used, total - *used,
65*0934d375SYunfei Dong 			    "\t-picinfo: get resolution\n");
66*0934d375SYunfei Dong 	*used += curr_len;
67*0934d375SYunfei Dong 
68*0934d375SYunfei Dong 	curr_len = snprintf(buf + *used, total - *used,
69*0934d375SYunfei Dong 			    "\t-format: get output & capture queue format\n");
70*0934d375SYunfei Dong 	*used += curr_len;
71*0934d375SYunfei Dong }
72*0934d375SYunfei Dong 
mtk_vdec_dbgfs_write(struct file * filp,const char __user * ubuf,size_t count,loff_t * ppos)73*0934d375SYunfei Dong static ssize_t mtk_vdec_dbgfs_write(struct file *filp, const char __user *ubuf,
74*0934d375SYunfei Dong 				    size_t count, loff_t *ppos)
75*0934d375SYunfei Dong {
76*0934d375SYunfei Dong 	struct mtk_vcodec_dec_dev *vcodec_dev = filp->private_data;
77*0934d375SYunfei Dong 	struct mtk_vcodec_dbgfs *dbgfs = &vcodec_dev->dbgfs;
78*0934d375SYunfei Dong 
79*0934d375SYunfei Dong 	mutex_lock(&dbgfs->dbgfs_lock);
80*0934d375SYunfei Dong 	dbgfs->buf_size = simple_write_to_buffer(dbgfs->dbgfs_buf, sizeof(dbgfs->dbgfs_buf),
81*0934d375SYunfei Dong 						 ppos, ubuf, count);
82*0934d375SYunfei Dong 	mutex_unlock(&dbgfs->dbgfs_lock);
83*0934d375SYunfei Dong 	if (dbgfs->buf_size > 0)
84*0934d375SYunfei Dong 		return count;
85*0934d375SYunfei Dong 
86*0934d375SYunfei Dong 	return dbgfs->buf_size;
87*0934d375SYunfei Dong }
88*0934d375SYunfei Dong 
mtk_vdec_dbgfs_read(struct file * filp,char __user * ubuf,size_t count,loff_t * ppos)89*0934d375SYunfei Dong static ssize_t mtk_vdec_dbgfs_read(struct file *filp, char __user *ubuf,
90*0934d375SYunfei Dong 				   size_t count, loff_t *ppos)
91*0934d375SYunfei Dong {
92*0934d375SYunfei Dong 	struct mtk_vcodec_dec_dev *vcodec_dev = filp->private_data;
93*0934d375SYunfei Dong 	struct mtk_vcodec_dbgfs *dbgfs = &vcodec_dev->dbgfs;
94*0934d375SYunfei Dong 	struct mtk_vcodec_dbgfs_inst *dbgfs_inst;
95*0934d375SYunfei Dong 	struct mtk_vcodec_dec_ctx *ctx;
96*0934d375SYunfei Dong 	int total_len = 200 * (dbgfs->inst_count == 0 ? 1 : dbgfs->inst_count);
97*0934d375SYunfei Dong 	int used_len = 0, curr_len, ret;
98*0934d375SYunfei Dong 	bool dbgfs_index[MTK_VDEC_DBGFS_MAX] = {0};
99*0934d375SYunfei Dong 	char *buf = kmalloc(total_len, GFP_KERNEL);
100*0934d375SYunfei Dong 
101*0934d375SYunfei Dong 	if (!buf)
102*0934d375SYunfei Dong 		return -ENOMEM;
103*0934d375SYunfei Dong 
104*0934d375SYunfei Dong 	if (strstr(dbgfs->dbgfs_buf, "-help") || dbgfs->buf_size == 1) {
105*0934d375SYunfei Dong 		mtk_vdec_dbgfs_get_help(buf, &used_len, total_len);
106*0934d375SYunfei Dong 		goto read_buffer;
107*0934d375SYunfei Dong 	}
108*0934d375SYunfei Dong 
109*0934d375SYunfei Dong 	if (strstr(dbgfs->dbgfs_buf, "-picinfo"))
110*0934d375SYunfei Dong 		dbgfs_index[MTK_VDEC_DBGFS_PICINFO] = true;
111*0934d375SYunfei Dong 
112*0934d375SYunfei Dong 	if (strstr(dbgfs->dbgfs_buf, "-format"))
113*0934d375SYunfei Dong 		dbgfs_index[MTK_VDEC_DBGFS_FORMAT] = true;
114*0934d375SYunfei Dong 
115*0934d375SYunfei Dong 	mutex_lock(&dbgfs->dbgfs_lock);
116*0934d375SYunfei Dong 	list_for_each_entry(dbgfs_inst, &dbgfs->dbgfs_head, node) {
117*0934d375SYunfei Dong 		ctx = dbgfs_inst->vcodec_ctx;
118*0934d375SYunfei Dong 
119*0934d375SYunfei Dong 		curr_len = snprintf(buf + used_len, total_len - used_len,
120*0934d375SYunfei Dong 				    "inst[%d]:\n ", ctx->id);
121*0934d375SYunfei Dong 		used_len += curr_len;
122*0934d375SYunfei Dong 
123*0934d375SYunfei Dong 		if (dbgfs_index[MTK_VDEC_DBGFS_PICINFO]) {
124*0934d375SYunfei Dong 			curr_len = snprintf(buf + used_len, total_len - used_len,
125*0934d375SYunfei Dong 					    "\treal(%dx%d)=>align(%dx%d)\n",
126*0934d375SYunfei Dong 					    ctx->picinfo.pic_w, ctx->picinfo.pic_h,
127*0934d375SYunfei Dong 					    ctx->picinfo.buf_w, ctx->picinfo.buf_h);
128*0934d375SYunfei Dong 			used_len += curr_len;
129*0934d375SYunfei Dong 		}
130*0934d375SYunfei Dong 
131*0934d375SYunfei Dong 		if (dbgfs_index[MTK_VDEC_DBGFS_FORMAT])
132*0934d375SYunfei Dong 			mtk_vdec_dbgfs_get_format_type(ctx, buf, &used_len, total_len);
133*0934d375SYunfei Dong 	}
134*0934d375SYunfei Dong 	mutex_unlock(&dbgfs->dbgfs_lock);
135*0934d375SYunfei Dong read_buffer:
136*0934d375SYunfei Dong 	ret = simple_read_from_buffer(ubuf, count, ppos, buf, used_len);
137*0934d375SYunfei Dong 	kfree(buf);
138*0934d375SYunfei Dong 	return ret;
139*0934d375SYunfei Dong }
140*0934d375SYunfei Dong 
141*0934d375SYunfei Dong static const struct file_operations vdec_fops = {
142*0934d375SYunfei Dong 	.open = simple_open,
143*0934d375SYunfei Dong 	.write = mtk_vdec_dbgfs_write,
144*0934d375SYunfei Dong 	.read = mtk_vdec_dbgfs_read,
145*0934d375SYunfei Dong };
146*0934d375SYunfei Dong 
mtk_vcodec_dbgfs_create(struct mtk_vcodec_dec_ctx * ctx)147*0934d375SYunfei Dong void mtk_vcodec_dbgfs_create(struct mtk_vcodec_dec_ctx *ctx)
148*0934d375SYunfei Dong {
149*0934d375SYunfei Dong 	struct mtk_vcodec_dbgfs_inst *dbgfs_inst;
150*0934d375SYunfei Dong 	struct mtk_vcodec_dec_dev *vcodec_dev = ctx->dev;
151*0934d375SYunfei Dong 
152*0934d375SYunfei Dong 	dbgfs_inst = kzalloc(sizeof(*dbgfs_inst), GFP_KERNEL);
153*0934d375SYunfei Dong 	if (!dbgfs_inst)
154*0934d375SYunfei Dong 		return;
155*0934d375SYunfei Dong 
156*0934d375SYunfei Dong 	list_add_tail(&dbgfs_inst->node, &vcodec_dev->dbgfs.dbgfs_head);
157*0934d375SYunfei Dong 
158*0934d375SYunfei Dong 	vcodec_dev->dbgfs.inst_count++;
159*0934d375SYunfei Dong 
160*0934d375SYunfei Dong 	dbgfs_inst->inst_id = ctx->id;
161*0934d375SYunfei Dong 	dbgfs_inst->vcodec_ctx = ctx;
162*0934d375SYunfei Dong }
163*0934d375SYunfei Dong EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_create);
164*0934d375SYunfei Dong 
mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dec_dev * vcodec_dev,int ctx_id)165*0934d375SYunfei Dong void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dec_dev *vcodec_dev, int ctx_id)
166*0934d375SYunfei Dong {
167*0934d375SYunfei Dong 	struct mtk_vcodec_dbgfs_inst *dbgfs_inst;
168*0934d375SYunfei Dong 
169*0934d375SYunfei Dong 	list_for_each_entry(dbgfs_inst, &vcodec_dev->dbgfs.dbgfs_head, node) {
170*0934d375SYunfei Dong 		if (dbgfs_inst->inst_id == ctx_id) {
171*0934d375SYunfei Dong 			vcodec_dev->dbgfs.inst_count--;
172*0934d375SYunfei Dong 			list_del(&dbgfs_inst->node);
173*0934d375SYunfei Dong 			kfree(dbgfs_inst);
174*0934d375SYunfei Dong 			return;
175*0934d375SYunfei Dong 		}
176*0934d375SYunfei Dong 	}
177*0934d375SYunfei Dong }
178*0934d375SYunfei Dong EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_remove);
179*0934d375SYunfei Dong 
mtk_vcodec_dbgfs_vdec_init(struct mtk_vcodec_dec_dev * vcodec_dev)180*0934d375SYunfei Dong static void mtk_vcodec_dbgfs_vdec_init(struct mtk_vcodec_dec_dev *vcodec_dev)
181*0934d375SYunfei Dong {
182*0934d375SYunfei Dong 	struct dentry *vcodec_root;
183*0934d375SYunfei Dong 
184*0934d375SYunfei Dong 	vcodec_dev->dbgfs.vcodec_root = debugfs_create_dir("vcodec-dec", NULL);
185*0934d375SYunfei Dong 	if (IS_ERR(vcodec_dev->dbgfs.vcodec_root))
186*0934d375SYunfei Dong 		dev_err(&vcodec_dev->plat_dev->dev, "create vcodec dir err:%ld\n",
187*0934d375SYunfei Dong 			PTR_ERR(vcodec_dev->dbgfs.vcodec_root));
188*0934d375SYunfei Dong 
189*0934d375SYunfei Dong 	vcodec_root = vcodec_dev->dbgfs.vcodec_root;
190*0934d375SYunfei Dong 	debugfs_create_x32("mtk_v4l2_dbg_level", 0644, vcodec_root, &mtk_v4l2_dbg_level);
191*0934d375SYunfei Dong 	debugfs_create_x32("mtk_vcodec_dbg", 0644, vcodec_root, &mtk_vcodec_dbg);
192*0934d375SYunfei Dong 
193*0934d375SYunfei Dong 	vcodec_dev->dbgfs.inst_count = 0;
194*0934d375SYunfei Dong 	INIT_LIST_HEAD(&vcodec_dev->dbgfs.dbgfs_head);
195*0934d375SYunfei Dong 	debugfs_create_file("vdec", 0200, vcodec_root, vcodec_dev, &vdec_fops);
196*0934d375SYunfei Dong 	mutex_init(&vcodec_dev->dbgfs.dbgfs_lock);
197*0934d375SYunfei Dong }
198*0934d375SYunfei Dong 
mtk_vcodec_dbgfs_venc_init(struct mtk_vcodec_enc_dev * vcodec_dev)199*0934d375SYunfei Dong static void mtk_vcodec_dbgfs_venc_init(struct mtk_vcodec_enc_dev *vcodec_dev)
200*0934d375SYunfei Dong {
201*0934d375SYunfei Dong 	struct dentry *vcodec_root;
202*0934d375SYunfei Dong 
203*0934d375SYunfei Dong 	vcodec_dev->dbgfs.vcodec_root = debugfs_create_dir("vcodec-enc", NULL);
204*0934d375SYunfei Dong 	if (IS_ERR(vcodec_dev->dbgfs.vcodec_root))
205*0934d375SYunfei Dong 		dev_err(&vcodec_dev->plat_dev->dev, "create venc dir err:%d\n",
206*0934d375SYunfei Dong 			IS_ERR(vcodec_dev->dbgfs.vcodec_root));
207*0934d375SYunfei Dong 
208*0934d375SYunfei Dong 	vcodec_root = vcodec_dev->dbgfs.vcodec_root;
209*0934d375SYunfei Dong 	debugfs_create_x32("mtk_v4l2_dbg_level", 0644, vcodec_root, &mtk_v4l2_dbg_level);
210*0934d375SYunfei Dong 	debugfs_create_x32("mtk_vcodec_dbg", 0644, vcodec_root, &mtk_vcodec_dbg);
211*0934d375SYunfei Dong 
212*0934d375SYunfei Dong 	vcodec_dev->dbgfs.inst_count = 0;
213*0934d375SYunfei Dong }
214*0934d375SYunfei Dong 
mtk_vcodec_dbgfs_init(void * vcodec_dev,bool is_encode)215*0934d375SYunfei Dong void mtk_vcodec_dbgfs_init(void *vcodec_dev, bool is_encode)
216*0934d375SYunfei Dong {
217*0934d375SYunfei Dong 	if (is_encode)
218*0934d375SYunfei Dong 		mtk_vcodec_dbgfs_venc_init(vcodec_dev);
219*0934d375SYunfei Dong 	else
220*0934d375SYunfei Dong 		mtk_vcodec_dbgfs_vdec_init(vcodec_dev);
221*0934d375SYunfei Dong }
222*0934d375SYunfei Dong EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_init);
223*0934d375SYunfei Dong 
mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dbgfs * dbgfs)224*0934d375SYunfei Dong void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dbgfs *dbgfs)
225*0934d375SYunfei Dong {
226*0934d375SYunfei Dong 	debugfs_remove_recursive(dbgfs->vcodec_root);
227*0934d375SYunfei Dong }
228*0934d375SYunfei Dong EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_deinit);
229*0934d375SYunfei Dong 
230*0934d375SYunfei Dong MODULE_LICENSE("GPL v2");
231*0934d375SYunfei Dong MODULE_DESCRIPTION("Mediatek video codec driver");
232