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