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 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 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 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 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 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 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 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 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 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 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