Linux Audio

Check our new training course

Loading...
  1// SPDX-License-Identifier: GPL-2.0-only OR MIT
  2/* Copyright (c) 2023 Imagination Technologies Ltd. */
  3
  4#include "pvr_params.h"
  5
  6#include <linux/cache.h>
  7#include <linux/moduleparam.h>
  8
  9static struct pvr_device_params pvr_device_param_defaults __read_mostly = {
 10#define X(type_, name_, value_, desc_, ...) .name_ = (value_),
 11	PVR_DEVICE_PARAMS
 12#undef X
 13};
 14
 15#define PVR_DEVICE_PARAM_NAMED(name_, type_, desc_) \
 16	module_param_named(name_, pvr_device_param_defaults.name_, type_, \
 17			   0400);                                         \
 18	MODULE_PARM_DESC(name_, desc_);
 19
 20/*
 21 * This list of defines must contain every type specified in "pvr_params.h" as
 22 * ``PVR_PARAM_TYPE_*_C``.
 23 */
 24#define PVR_PARAM_TYPE_X32_MODPARAM uint
 25
 26#define X(type_, name_, value_, desc_, ...) \
 27	PVR_DEVICE_PARAM_NAMED(name_, PVR_PARAM_TYPE_##type_##_MODPARAM, desc_);
 28PVR_DEVICE_PARAMS
 29#undef X
 30
 31int
 32pvr_device_params_init(struct pvr_device_params *params)
 33{
 34	/*
 35	 * If heap-allocated parameters are added in the future (e.g.
 36	 * modparam's charp type), they must be handled specially here (via
 37	 * kstrdup() in the case of charp). Since that's not necessary yet,
 38	 * a straight copy will do for now. This change will also require a
 39	 * pvr_device_params_fini() function to free any heap-allocated copies.
 40	 */
 41
 42	*params = pvr_device_param_defaults;
 43
 44	return 0;
 45}
 46
 47#if defined(CONFIG_DEBUG_FS)
 48#include "pvr_device.h"
 49
 50#include <linux/dcache.h>
 51#include <linux/debugfs.h>
 52#include <linux/export.h>
 53#include <linux/fs.h>
 54#include <linux/stddef.h>
 55
 56/*
 57 * This list of defines must contain every type specified in "pvr_params.h" as
 58 * ``PVR_PARAM_TYPE_*_C``.
 59 */
 60#define PVR_PARAM_TYPE_X32_FMT "0x%08llx"
 61
 62#define X_SET(name_, mode_) X_SET_##mode_(name_)
 63#define X_SET_DEF(name_, update_, mode_) X_SET_DEF_##mode_(name_, update_)
 64
 65#define X_SET_RO(name_) NULL
 66#define X_SET_RW(name_) __pvr_device_param_##name_##set
 67
 68#define X_SET_DEF_RO(name_, update_)
 69#define X_SET_DEF_RW(name_, update_)                                    \
 70	static int                                                      \
 71	X_SET_RW(name_)(void *data, u64 val)                            \
 72	{                                                               \
 73		struct pvr_device *pvr_dev = data;                      \
 74		/* This is not just (update_) to suppress -Waddress. */ \
 75		if ((void *)(update_) != NULL)                          \
 76			(update_)(pvr_dev, pvr_dev->params.name_, val); \
 77		pvr_dev->params.name_ = val;                            \
 78		return 0;                                               \
 79	}
 80
 81#define X(type_, name_, value_, desc_, mode_, update_)                     \
 82	static int                                                         \
 83	__pvr_device_param_##name_##_get(void *data, u64 *val)             \
 84	{                                                                  \
 85		struct pvr_device *pvr_dev = data;                         \
 86		*val = pvr_dev->params.name_;                              \
 87		return 0;                                                  \
 88	}                                                                  \
 89	X_SET_DEF(name_, update_, mode_)                                   \
 90	static int                                                         \
 91	__pvr_device_param_##name_##_open(struct inode *inode,             \
 92					  struct file *file)               \
 93	{                                                                  \
 94		__simple_attr_check_format(PVR_PARAM_TYPE_##type_##_FMT,   \
 95					   0ull);                          \
 96		return simple_attr_open(inode, file,                       \
 97					__pvr_device_param_##name_##_get,  \
 98					X_SET(name_, mode_),               \
 99					PVR_PARAM_TYPE_##type_##_FMT);     \
100	}
101PVR_DEVICE_PARAMS
102#undef X
103
104#undef X_SET
105#undef X_SET_RO
106#undef X_SET_RW
107#undef X_SET_DEF
108#undef X_SET_DEF_RO
109#undef X_SET_DEF_RW
110
111static struct {
112#define X(type_, name_, value_, desc_, mode_, update_) \
113	const struct file_operations name_;
114	PVR_DEVICE_PARAMS
115#undef X
116} pvr_device_param_debugfs_fops = {
117#define X(type_, name_, value_, desc_, mode_, update_)     \
118	.name_ = {                                         \
119		.owner = THIS_MODULE,                      \
120		.open = __pvr_device_param_##name_##_open, \
121		.release = simple_attr_release,            \
122		.read = simple_attr_read,                  \
123		.write = simple_attr_write,                \
124		.llseek = generic_file_llseek,             \
125	},
126	PVR_DEVICE_PARAMS
127#undef X
128};
129
130void
131pvr_params_debugfs_init(struct pvr_device *pvr_dev, struct dentry *dir)
132{
133#define X_MODE(mode_) X_MODE_##mode_
134#define X_MODE_RO 0400
135#define X_MODE_RW 0600
136
137#define X(type_, name_, value_, desc_, mode_, update_)             \
138	debugfs_create_file(#name_, X_MODE(mode_), dir, pvr_dev,   \
139			    &pvr_device_param_debugfs_fops.name_);
140	PVR_DEVICE_PARAMS
141#undef X
142
143#undef X_MODE
144#undef X_MODE_RO
145#undef X_MODE_RW
146}
147#endif