178 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2023 Intel Corporation4 */5 6#include <linux/debugfs.h>7#include <linux/kernel.h>8 9#include <drm/drm_drv.h>10 11#include "intel_display_debugfs_params.h"12#include "i915_drv.h"13#include "intel_display_params.h"14 15/* int param */16static int intel_display_param_int_show(struct seq_file *m, void *data)17{18 int *value = m->private;19 20 seq_printf(m, "%d\n", *value);21 22 return 0;23}24 25static int intel_display_param_int_open(struct inode *inode, struct file *file)26{27 return single_open(file, intel_display_param_int_show, inode->i_private);28}29 30static ssize_t intel_display_param_int_write(struct file *file,31 const char __user *ubuf, size_t len,32 loff_t *offp)33{34 struct seq_file *m = file->private_data;35 int *value = m->private;36 int ret;37 38 ret = kstrtoint_from_user(ubuf, len, 0, value);39 if (ret) {40 /* support boolean values too */41 bool b;42 43 ret = kstrtobool_from_user(ubuf, len, &b);44 if (!ret)45 *value = b;46 }47 48 return ret ?: len;49}50 51static const struct file_operations intel_display_param_int_fops = {52 .owner = THIS_MODULE,53 .open = intel_display_param_int_open,54 .read = seq_read,55 .write = intel_display_param_int_write,56 .llseek = default_llseek,57 .release = single_release,58};59 60static const struct file_operations intel_display_param_int_fops_ro = {61 .owner = THIS_MODULE,62 .open = intel_display_param_int_open,63 .read = seq_read,64 .llseek = default_llseek,65 .release = single_release,66};67 68/* unsigned int param */69static int intel_display_param_uint_show(struct seq_file *m, void *data)70{71 unsigned int *value = m->private;72 73 seq_printf(m, "%u\n", *value);74 75 return 0;76}77 78static int intel_display_param_uint_open(struct inode *inode, struct file *file)79{80 return single_open(file, intel_display_param_uint_show, inode->i_private);81}82 83static ssize_t intel_display_param_uint_write(struct file *file,84 const char __user *ubuf, size_t len,85 loff_t *offp)86{87 struct seq_file *m = file->private_data;88 unsigned int *value = m->private;89 int ret;90 91 ret = kstrtouint_from_user(ubuf, len, 0, value);92 if (ret) {93 /* support boolean values too */94 bool b;95 96 ret = kstrtobool_from_user(ubuf, len, &b);97 if (!ret)98 *value = b;99 }100 101 return ret ?: len;102}103 104static const struct file_operations intel_display_param_uint_fops = {105 .owner = THIS_MODULE,106 .open = intel_display_param_uint_open,107 .read = seq_read,108 .write = intel_display_param_uint_write,109 .llseek = default_llseek,110 .release = single_release,111};112 113static const struct file_operations intel_display_param_uint_fops_ro = {114 .owner = THIS_MODULE,115 .open = intel_display_param_uint_open,116 .read = seq_read,117 .llseek = default_llseek,118 .release = single_release,119};120 121#define RO(mode) (((mode) & 0222) == 0)122 123__maybe_unused static struct dentry *124intel_display_debugfs_create_int(const char *name, umode_t mode,125 struct dentry *parent, int *value)126{127 return debugfs_create_file_unsafe(name, mode, parent, value,128 RO(mode) ? &intel_display_param_int_fops_ro :129 &intel_display_param_int_fops);130}131 132__maybe_unused static struct dentry *133intel_display_debugfs_create_uint(const char *name, umode_t mode,134 struct dentry *parent, unsigned int *value)135{136 return debugfs_create_file_unsafe(name, mode, parent, value,137 RO(mode) ? &intel_display_param_uint_fops_ro :138 &intel_display_param_uint_fops);139}140 141#define _intel_display_param_create_file(parent, name, mode, valp) \142 do { \143 if (mode) \144 _Generic(valp, \145 bool * : debugfs_create_bool, \146 int * : intel_display_debugfs_create_int, \147 unsigned int * : intel_display_debugfs_create_uint, \148 unsigned long * : debugfs_create_ulong, \149 char ** : debugfs_create_str) \150 (name, mode, parent, valp); \151 } while (0)152 153/* add a subdirectory with files for each intel display param */154void intel_display_debugfs_params(struct intel_display *display)155{156 struct drm_minor *minor = display->drm->primary;157 struct dentry *dir;158 char dirname[16];159 160 snprintf(dirname, sizeof(dirname), "%s_params", display->drm->driver->name);161 dir = debugfs_lookup(dirname, minor->debugfs_root);162 if (!dir)163 dir = debugfs_create_dir(dirname, minor->debugfs_root);164 if (IS_ERR(dir))165 return;166 167 /*168 * Note: We could create files for params needing special handling169 * here. Set mode in params to 0 to skip the generic create file, or170 * just let the generic create file fail silently with -EEXIST.171 */172 173#define REGISTER(T, x, unused, mode, ...) _intel_display_param_create_file( \174 dir, #x, mode, &display->params.x);175 INTEL_DISPLAY_PARAMS_FOR_EACH(REGISTER);176#undef REGISTER177}178