b2fa8c8f570fd0040597f23560a7de742cf02105
[openwrt/staging/pepe2k.git] /
1 From 4fac21e3a4d37667a86c762064dad5f76c42c235 Mon Sep 17 00:00:00 2001
2 From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
3 Date: Thu, 15 Jul 2021 01:08:01 +0200
4 Subject: [PATCH 0006/1085] drm/vc4: Allow setting the TV norm via module
5 parameter
6
7 Similar to the ch7006 and nouveau drivers, introduce a "tv_mode" module
8 parameter that allow setting the TV norm by specifying vc4.tv_norm= on
9 the kernel command line.
10
11 If that is not specified, try inferring one of the most popular norms
12 (PAL or NTSC) from the video mode specified on the command line. On
13 Raspberry Pis, this causes the most common cases of the sdtv_mode
14 setting in config.txt to be respected.
15
16 Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
17 ---
18 drivers/gpu/drm/vc4/vc4_vec.c | 108 +++++++++++++++++++++++++---------
19 1 file changed, 81 insertions(+), 27 deletions(-)
20
21 --- a/drivers/gpu/drm/vc4/vc4_vec.c
22 +++ b/drivers/gpu/drm/vc4/vc4_vec.c
23 @@ -67,7 +67,7 @@
24 #define VEC_CONFIG0_YCDELAY BIT(4)
25 #define VEC_CONFIG0_RAMPEN BIT(2)
26 #define VEC_CONFIG0_YCDIS BIT(2)
27 -#define VEC_CONFIG0_STD_MASK GENMASK(1, 0)
28 +#define VEC_CONFIG0_STD_MASK (VEC_CONFIG0_SECAM_STD | GENMASK(1, 0))
29 #define VEC_CONFIG0_NTSC_STD 0
30 #define VEC_CONFIG0_PAL_BDGHI_STD 1
31 #define VEC_CONFIG0_PAL_M_STD 2
32 @@ -186,6 +186,8 @@
33 #define VEC_DAC_MISC_DAC_RST_N BIT(0)
34
35
36 +static char *vc4_vec_tv_norm;
37 +
38 struct vc4_vec_variant {
39 u32 dac_config;
40 };
41 @@ -353,6 +355,33 @@ static const struct drm_prop_enum_list l
42 { VC4_VEC_TV_MODE_SECAM, "SECAM", },
43 };
44
45 +enum drm_connector_tv_mode
46 +vc4_vec_get_default_mode(struct drm_connector *connector)
47 +{
48 + if (vc4_vec_tv_norm) {
49 + int ret;
50 +
51 + ret = drm_get_tv_mode_from_name(vc4_vec_tv_norm, strlen(vc4_vec_tv_norm));
52 + if (ret >= 0)
53 + return ret;
54 + } else if (connector->cmdline_mode.specified &&
55 + ((connector->cmdline_mode.refresh_specified &&
56 + (connector->cmdline_mode.refresh == 25 ||
57 + connector->cmdline_mode.refresh == 50)) ||
58 + (!connector->cmdline_mode.refresh_specified &&
59 + (connector->cmdline_mode.yres == 288 ||
60 + connector->cmdline_mode.yres == 576)))) {
61 + /*
62 + * no explicitly specified TV norm; use PAL if a mode that
63 + * looks like PAL has been specified on the command line
64 + */
65 + return DRM_MODE_TV_MODE_PAL;
66 + }
67 +
68 + /* in all other cases, default to NTSC */
69 + return DRM_MODE_TV_MODE_NTSC;
70 +}
71 +
72 static enum drm_connector_status
73 vc4_vec_connector_detect(struct drm_connector *connector, bool force)
74 {
75 @@ -363,6 +392,10 @@ static void vc4_vec_connector_reset(stru
76 {
77 drm_atomic_helper_connector_reset(connector);
78 drm_atomic_helper_connector_tv_reset(connector);
79 +
80 + /* preserve TV standard */
81 + if (connector->state)
82 + connector->state->tv.mode = vc4_vec_get_default_mode(connector);
83 }
84
85 static int
86 @@ -414,48 +447,52 @@ vc4_vec_connector_set_property(struct dr
87 }
88
89 static int
90 -vc4_vec_connector_get_property(struct drm_connector *connector,
91 - const struct drm_connector_state *state,
92 - struct drm_property *property,
93 - uint64_t *val)
94 +vc4_vec_generic_tv_mode_to_legacy(enum drm_connector_tv_mode tv_mode)
95 {
96 - struct vc4_vec *vec = connector_to_vc4_vec(connector);
97 -
98 - if (property != vec->legacy_tv_mode_property)
99 - return -EINVAL;
100 -
101 - switch (state->tv.mode) {
102 + switch (tv_mode) {
103 case DRM_MODE_TV_MODE_NTSC:
104 - *val = VC4_VEC_TV_MODE_NTSC;
105 - break;
106 + return VC4_VEC_TV_MODE_NTSC;
107
108 case DRM_MODE_TV_MODE_NTSC_443:
109 - *val = VC4_VEC_TV_MODE_NTSC_443;
110 - break;
111 + return VC4_VEC_TV_MODE_NTSC_443;
112
113 case DRM_MODE_TV_MODE_NTSC_J:
114 - *val = VC4_VEC_TV_MODE_NTSC_J;
115 - break;
116 + return VC4_VEC_TV_MODE_NTSC_J;
117
118 case DRM_MODE_TV_MODE_PAL:
119 - *val = VC4_VEC_TV_MODE_PAL;
120 - break;
121 + return VC4_VEC_TV_MODE_PAL;
122
123 case DRM_MODE_TV_MODE_PAL_M:
124 - *val = VC4_VEC_TV_MODE_PAL_M;
125 - break;
126 + return VC4_VEC_TV_MODE_PAL_M;
127
128 case DRM_MODE_TV_MODE_PAL_N:
129 - *val = VC4_VEC_TV_MODE_PAL_N;
130 - break;
131 + return VC4_VEC_TV_MODE_PAL_N;
132
133 case DRM_MODE_TV_MODE_SECAM:
134 - *val = VC4_VEC_TV_MODE_SECAM;
135 - break;
136 + return VC4_VEC_TV_MODE_SECAM;
137
138 default:
139 return -EINVAL;
140 }
141 +}
142 +
143 +static int
144 +vc4_vec_connector_get_property(struct drm_connector *connector,
145 + const struct drm_connector_state *state,
146 + struct drm_property *property,
147 + uint64_t *val)
148 +{
149 + struct vc4_vec *vec = connector_to_vc4_vec(connector);
150 + enum vc4_vec_tv_mode_id legacy_mode;
151 +
152 + if (property != vec->legacy_tv_mode_property)
153 + return -EINVAL;
154 +
155 + legacy_mode = vc4_vec_generic_tv_mode_to_legacy(state->tv.mode);
156 + if (legacy_mode < 0)
157 + return legacy_mode;
158 +
159 + *val = legacy_mode;
160
161 return 0;
162 }
163 @@ -478,6 +515,8 @@ static const struct drm_connector_helper
164 static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
165 {
166 struct drm_connector *connector = &vec->connector;
167 + enum vc4_vec_tv_mode_id legacy_default_mode;
168 + enum drm_connector_tv_mode default_mode;
169 struct drm_property *prop;
170 int ret;
171
172 @@ -490,9 +529,17 @@ static int vc4_vec_connector_init(struct
173
174 drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
175
176 + default_mode = vc4_vec_get_default_mode(connector);
177 + if (default_mode < 0)
178 + return default_mode;
179 +
180 drm_object_attach_property(&connector->base,
181 dev->mode_config.tv_mode_property,
182 - DRM_MODE_TV_MODE_NTSC);
183 + default_mode);
184 +
185 + legacy_default_mode = vc4_vec_generic_tv_mode_to_legacy(default_mode);
186 + if (legacy_default_mode < 0)
187 + return legacy_default_mode;
188
189 prop = drm_property_create_enum(dev, 0, "mode",
190 legacy_tv_mode_names,
191 @@ -501,7 +548,7 @@ static int vc4_vec_connector_init(struct
192 return -ENOMEM;
193 vec->legacy_tv_mode_property = prop;
194
195 - drm_object_attach_property(&connector->base, prop, VC4_VEC_TV_MODE_NTSC);
196 + drm_object_attach_property(&connector->base, prop, legacy_default_mode);
197
198 drm_connector_attach_encoder(connector, &vec->encoder.base);
199
200 @@ -825,3 +872,10 @@ struct platform_driver vc4_vec_driver =
201 .of_match_table = vc4_vec_dt_match,
202 },
203 };
204 +
205 +module_param_named(tv_norm, vc4_vec_tv_norm, charp, 0600);
206 +MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
207 + "\t\tSupported: NTSC, NTSC-J, NTSC-443, PAL, PAL-M, PAL-N,\n"
208 + "\t\t\tPAL60, SECAM.\n"
209 + "\t\tDefault: PAL if a 50 Hz mode has been set via video=,\n"
210 + "\t\t\tNTSC otherwise");