summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_display_params.c
blob: 60fa0bbce77d34ac343da74a6624f58e258d18ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// SPDX-License-Identifier: MIT
/*
 * Copyright © 2023 Intel Corporation
 */

#include "intel_display_params.h"
#include "i915_drv.h"

#define intel_display_param_named(name, T, perm, desc) \
	module_param_named(name, intel_display_modparams.name, T, perm); \
	MODULE_PARM_DESC(name, desc)
#define intel_display_param_named_unsafe(name, T, perm, desc) \
	module_param_named_unsafe(name, intel_display_modparams.name, T, perm); \
	MODULE_PARM_DESC(name, desc)

static struct intel_display_params intel_display_modparams __read_mostly = {
#define MEMBER(T, member, value, ...) .member = (value),
	INTEL_DISPLAY_PARAMS_FOR_EACH(MEMBER)
#undef MEMBER
};
/*
 * Note: As a rule, keep module parameter sysfs permissions read-only
 * 0400. Runtime changes are only supported through i915 debugfs.
 *
 * For any exceptions requiring write access and runtime changes through module
 * parameter sysfs, prevent debugfs file creation by setting the parameter's
 * debugfs mode to 0.
 */

intel_display_param_named_unsafe(vbt_firmware, charp, 0400,
	"Load VBT from specified file under /lib/firmware");

intel_display_param_named_unsafe(lvds_channel_mode, int, 0400,
	 "Specify LVDS channel mode "
	 "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)");

intel_display_param_named_unsafe(panel_use_ssc, int, 0400,
	"Use Spread Spectrum Clock with panels [LVDS/eDP] "
	"(default: auto from VBT)");

intel_display_param_named_unsafe(vbt_sdvo_panel_type, int, 0400,
	"Override/Ignore selection of SDVO panel mode in the VBT "
	"(-2=ignore, -1=auto [default], index in VBT BIOS table)");

intel_display_param_named_unsafe(enable_dc, int, 0400,
	"Enable power-saving display C-states. "
	"(-1=auto [default]; 0=disable; 1=up to DC5; 2=up to DC6; "
	"3=up to DC5 with DC3CO; 4=up to DC6 with DC3CO)");

intel_display_param_named_unsafe(enable_fbc, int, 0400,
	"Enable frame buffer compression for power savings "
	"(default: -1 (use per-chip default))");

intel_display_param_named_unsafe(enable_psr, int, 0400,
	"Enable PSR "
	"(0=disabled, 1=enable up to PSR1, 2=enable up to PSR2) "
	"Default: -1 (use per-chip default)");

intel_display_param_named(psr_safest_params, bool, 0400,
	"Replace PSR VBT parameters by the safest and not optimal ones. This "
	"is helpful to detect if PSR issues are related to bad values set in "
	" VBT. (0=use VBT parameters, 1=use safest parameters)"
	"Default: 0");

intel_display_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400,
	"Enable PSR2 selective fetch "
	"(0=disabled, 1=enabled) "
	"Default: 1");

__maybe_unused
static void _param_print_bool(struct drm_printer *p, const char *driver_name,
			      const char *name, bool val)
{
	drm_printf(p, "%s.%s=%s\n", driver_name, name, str_yes_no(val));
}

__maybe_unused
static void _param_print_int(struct drm_printer *p, const char *driver_name,
			     const char *name, int val)
{
	drm_printf(p, "%s.%s=%d\n", driver_name, name, val);
}

__maybe_unused
static void _param_print_uint(struct drm_printer *p, const char *driver_name,
			      const char *name, unsigned int val)
{
	drm_printf(p, "%s.%s=%u\n", driver_name, name, val);
}

__maybe_unused
static void _param_print_ulong(struct drm_printer *p, const char *driver_name,
			       const char *name, unsigned long val)
{
	drm_printf(p, "%s.%s=%lu\n", driver_name, name, val);
}

__maybe_unused
static void _param_print_charp(struct drm_printer *p, const char *driver_name,
			       const char *name, const char *val)
{
	drm_printf(p, "%s.%s=%s\n", driver_name, name, val);
}

#define _param_print(p, driver_name, name, val)			\
	_Generic(val,						\
		 bool : _param_print_bool,			\
		 int : _param_print_int,			\
		 unsigned int : _param_print_uint,		\
		 unsigned long : _param_print_ulong,		\
		 char * : _param_print_charp)(p, driver_name, name, val)

/**
 * intel_display_params_dump - dump intel display modparams
 * @i915: i915 device
 * @p: the &drm_printer
 *
 * Pretty printer for i915 modparams.
 */
void intel_display_params_dump(struct drm_i915_private *i915, struct drm_printer *p)
{
#define PRINT(T, x, ...) _param_print(p, i915->drm.driver->name, #x, i915->display.params.x);
	INTEL_DISPLAY_PARAMS_FOR_EACH(PRINT);
#undef PRINT
}

__maybe_unused static void _param_dup_charp(char **valp)
{
	*valp = kstrdup(*valp ? *valp : "", GFP_ATOMIC);
}

__maybe_unused static void _param_nop(void *valp)
{
}

#define _param_dup(valp)				\
	_Generic(valp,					\
		 char ** : _param_dup_charp,		\
		 default : _param_nop)			\
		(valp)

void intel_display_params_copy(struct intel_display_params *dest)
{
	*dest = intel_display_modparams;
#define DUP(T, x, ...) _param_dup(&dest->x);
	INTEL_DISPLAY_PARAMS_FOR_EACH(DUP);
#undef DUP
}

__maybe_unused static void _param_free_charp(char **valp)
{
	kfree(*valp);
	*valp = NULL;
}

#define _param_free(valp)				\
	_Generic(valp,					\
		 char ** : _param_free_charp,		\
		 default : _param_nop)			\
		(valp)

/* free the allocated members, *not* the passed in params itself */
void intel_display_params_free(struct intel_display_params *params)
{
#define FREE(T, x, ...) _param_free(&params->x);
	INTEL_DISPLAY_PARAMS_FOR_EACH(FREE);
#undef FREE
}