e55856fc452fa45049dda2f6de151233ecf224fe
[openwrt/staging/linusw.git] /
1 From 272ac64c598d83c4025393398b431db0a4656a74 Mon Sep 17 00:00:00 2001
2 From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
3 Date: Tue, 23 Jan 2024 18:45:51 +0000
4 Subject: [PATCH 0874/1085] drm: rp1: Use tv_mode from the command line and fix
5 for Linux 6.6
6
7 Use the standard enum drm_connector_tv_mode instead of a private
8 enum and switch from the legacy to the standard tv_mode property.
9
10 Remove the module parameter "tv_norm". Instead, get tv_mode from
11 the command line and make this the connector's default TV mode.
12
13 Don't restrict the choice of modes based on tv_mode, but interpret
14 nonstandard combinations as NTSC or PAL, depending on resolution.
15 Thus the default tv_mode=NTSC effectively means "Auto".
16
17 Tweak the advertised horizontal timings for 625/50 to match Rec.601
18
19 Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
20 ---
21 drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c | 134 ++++++++---------------
22 drivers/gpu/drm/rp1/rp1-vec/rp1_vec.h | 24 ++--
23 drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c | 15 +--
24 3 files changed, 63 insertions(+), 110 deletions(-)
25
26 --- a/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c
27 +++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c
28 @@ -48,52 +48,6 @@
29
30 #include "rp1_vec.h"
31
32 -/*
33 - * Default TV standard parameter; it may be overridden by the OF
34 - * property "tv_norm" (which should be one of the strings below).
35 - *
36 - * The default (empty string) supports various 60Hz and 50Hz modes,
37 - * and will automatically select NTSC[-M] or PAL[-BDGHIKL]; the two
38 - * "fake" 60Hz standards NTSC-443 and PAL60 also support 50Hz PAL.
39 - * Other values will restrict the set of video modes offered.
40 - *
41 - * Finally, the DRM connector property "mode" (which is an integer)
42 - * can be used to override this value, but it does not prevent the
43 - * selection of an inapplicable video mode.
44 - */
45 -
46 -static char *rp1vec_tv_norm_str;
47 -module_param_named(tv_norm, rp1vec_tv_norm_str, charp, 0600);
48 -MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
49 - "\t\tSupported: NTSC, NTSC-J, NTSC-443, PAL, PAL-M, PAL-N,\n"
50 - "\t\t\tPAL60.\n"
51 - "\t\tDefault: empty string: infer PAL for a 50 Hz mode,\n"
52 - "\t\t\tNTSC otherwise");
53 -
54 -const char * const rp1vec_tvstd_names[] = {
55 - [RP1VEC_TVSTD_NTSC] = "NTSC",
56 - [RP1VEC_TVSTD_NTSC_J] = "NTSC-J",
57 - [RP1VEC_TVSTD_NTSC_443] = "NTSC-443",
58 - [RP1VEC_TVSTD_PAL] = "PAL",
59 - [RP1VEC_TVSTD_PAL_M] = "PAL-M",
60 - [RP1VEC_TVSTD_PAL_N] = "PAL-N",
61 - [RP1VEC_TVSTD_PAL60] = "PAL60",
62 - [RP1VEC_TVSTD_DEFAULT] = "",
63 -};
64 -
65 -static int rp1vec_parse_tv_norm(const char *str)
66 -{
67 - int i;
68 -
69 - if (str && *str) {
70 - for (i = 0; i < ARRAY_SIZE(rp1vec_tvstd_names); ++i) {
71 - if (strcasecmp(str, rp1vec_tvstd_names[i]) == 0)
72 - return i;
73 - }
74 - }
75 - return RP1VEC_TVSTD_DEFAULT;
76 -}
77 -
78 static void rp1vec_pipe_update(struct drm_simple_display_pipe *pipe,
79 struct drm_plane_state *old_state)
80 {
81 @@ -143,7 +97,7 @@ static void rp1vec_pipe_update(struct dr
82
83 static void rp1vec_pipe_enable(struct drm_simple_display_pipe *pipe,
84 struct drm_crtc_state *crtc_state,
85 - struct drm_plane_state *plane_state)
86 + struct drm_plane_state *plane_state)
87 {
88 struct rp1_vec *vec = pipe->crtc.dev->dev_private;
89
90 @@ -219,48 +173,64 @@ static const struct drm_display_mode rp1
91 },
92 { /* Full size 625/50i with Rec.601 pixel rate */
93 DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500,
94 - 720, 720 + 20, 720 + 20 + 64, 864, 0,
95 + 720, 720 + 12, 720 + 12 + 64, 864, 0,
96 576, 576 + 5, 576 + 5 + 5, 625, 0,
97 DRM_MODE_FLAG_INTERLACE)
98 },
99 { /* Cropped and squashed, for square(ish) pixels */
100 DRM_MODE("704x512i", DRM_MODE_TYPE_DRIVER, 15429,
101 - 704, 704 + 80, 704 + 80 + 72, 987, 0,
102 + 704, 704 + 72, 704 + 72 + 72, 987, 0,
103 512, 512 + 37, 512 + 37 + 5, 625, 0,
104 DRM_MODE_FLAG_INTERLACE)
105 }
106 };
107
108 +/*
109 + * Advertise standard and preferred video modes.
110 + *
111 + * From each interlaced mode in the table above, derive a progressive one.
112 + *
113 + * This driver always supports all 50Hz and 60Hz video modes, regardless
114 + * of connector's tv_mode; nonstandard combinations generally default
115 + * to PAL[-BDGHIKL] or NTSC[-M] depending on resolution and field-rate
116 + * (except that "PAL" with 525/60 will be implemented as "PAL60").
117 + * However, the preferred mode will depend on the default TV mode.
118 + */
119 +
120 static int rp1vec_connector_get_modes(struct drm_connector *connector)
121 {
122 - struct rp1_vec *vec = container_of(connector, struct rp1_vec, connector);
123 - bool ok525 = RP1VEC_TVSTD_SUPPORT_525(vec->tv_norm);
124 - bool ok625 = RP1VEC_TVSTD_SUPPORT_625(vec->tv_norm);
125 + u64 val;
126 int i, prog, n = 0;
127 + bool prefer625 = false;
128 +
129 + if (!drm_object_property_get_default_value(&connector->base,
130 + connector->dev->mode_config.tv_mode_property,
131 + &val))
132 + prefer625 = (val == DRM_MODE_TV_MODE_PAL ||
133 + val == DRM_MODE_TV_MODE_PAL_N ||
134 + val == DRM_MODE_TV_MODE_SECAM);
135
136 for (i = 0; i < ARRAY_SIZE(rp1vec_modes); i++) {
137 - if ((rp1vec_modes[i].vtotal == 625) ? ok625 : ok525) {
138 - for (prog = 0; prog < 2; prog++) {
139 - struct drm_display_mode *mode =
140 - drm_mode_duplicate(connector->dev,
141 - &rp1vec_modes[i]);
142 -
143 - if (prog) {
144 - mode->flags &= ~DRM_MODE_FLAG_INTERLACE;
145 - mode->vdisplay >>= 1;
146 - mode->vsync_start >>= 1;
147 - mode->vsync_end >>= 1;
148 - mode->vtotal >>= 1;
149 - }
150 -
151 - if (mode->hdisplay == 704 &&
152 - mode->vtotal == ((ok525) ? 525 : 625))
153 - mode->type |= DRM_MODE_TYPE_PREFERRED;
154 -
155 - drm_mode_set_name(mode);
156 - drm_mode_probed_add(connector, mode);
157 - n++;
158 + for (prog = 0; prog < 2; prog++) {
159 + struct drm_display_mode *mode =
160 + drm_mode_duplicate(connector->dev,
161 + &rp1vec_modes[i]);
162 +
163 + if (prog) {
164 + mode->flags &= ~DRM_MODE_FLAG_INTERLACE;
165 + mode->vdisplay >>= 1;
166 + mode->vsync_start >>= 1;
167 + mode->vsync_end >>= 1;
168 + mode->vtotal >>= 1;
169 }
170 +
171 + if (mode->hdisplay == 704 &&
172 + mode->vtotal == (prefer625 ? 625 : 525))
173 + mode->type |= DRM_MODE_TYPE_PREFERRED;
174 +
175 + drm_mode_set_name(mode);
176 + drm_mode_probed_add(connector, mode);
177 + n++;
178 }
179 }
180
181 @@ -269,11 +239,8 @@ static int rp1vec_connector_get_modes(st
182
183 static void rp1vec_connector_reset(struct drm_connector *connector)
184 {
185 - struct rp1_vec *vec = container_of(connector, struct rp1_vec, connector);
186 -
187 drm_atomic_helper_connector_reset(connector);
188 - if (connector->state)
189 - connector->state->tv.mode = vec->tv_norm;
190 + drm_atomic_helper_connector_tv_reset(connector);
191 }
192
193 static int rp1vec_connector_atomic_check(struct drm_connector *conn,
194 @@ -396,7 +363,6 @@ static int rp1vec_platform_probe(struct
195 struct device *dev = &pdev->dev;
196 struct drm_device *drm;
197 struct rp1_vec *vec;
198 - const char *str;
199 int i, ret;
200
201 dev_info(dev, __func__);
202 @@ -419,10 +385,6 @@ static int rp1vec_platform_probe(struct
203 drm->dev_private = vec;
204 platform_set_drvdata(pdev, drm);
205
206 - str = rp1vec_tv_norm_str;
207 - of_property_read_string(dev->of_node, "tv_norm", &str);
208 - vec->tv_norm = rp1vec_parse_tv_norm(str);
209 -
210 for (i = 0; i < RP1VEC_NUM_HW_BLOCKS; i++) {
211 vec->hw_base[i] =
212 devm_ioremap_resource(dev,
213 @@ -463,9 +425,7 @@ static int rp1vec_platform_probe(struct
214 drm->mode_config.funcs = &rp1vec_mode_funcs;
215 drm_vblank_init(drm, 1);
216
217 - ret = drm_mode_create_tv_properties_legacy(drm,
218 - ARRAY_SIZE(rp1vec_tvstd_names),
219 - rp1vec_tvstd_names);
220 + ret = drm_mode_create_tv_properties(drm, RP1VEC_SUPPORTED_TV_MODES);
221 if (ret)
222 goto err_free_drm;
223
224 @@ -479,7 +439,9 @@ static int rp1vec_platform_probe(struct
225
226 drm_object_attach_property(&vec->connector.base,
227 drm->mode_config.tv_mode_property,
228 - vec->tv_norm);
229 + (vec->connector.cmdline_mode.tv_mode_specified) ?
230 + vec->connector.cmdline_mode.tv_mode :
231 + DRM_MODE_TV_MODE_NTSC);
232
233 ret = drm_simple_display_pipe_init(drm,
234 &vec->pipe,
235 --- a/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.h
236 +++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.h
237 @@ -20,20 +20,13 @@
238 #define RP1VEC_HW_BLOCK_CFG 1
239 #define RP1VEC_NUM_HW_BLOCKS 2
240
241 -enum {
242 - RP1VEC_TVSTD_NTSC = 0, /* +525 => NTSC 625 => PAL */
243 - RP1VEC_TVSTD_NTSC_J, /* +525 => NTSC-J 625 => PAL */
244 - RP1VEC_TVSTD_NTSC_443, /* +525 => NTSC-443 +625 => PAL */
245 - RP1VEC_TVSTD_PAL, /* 525 => NTSC +625 => PAL */
246 - RP1VEC_TVSTD_PAL_M, /* +525 => PAL-M 625 => PAL */
247 - RP1VEC_TVSTD_PAL_N, /* 525 => NTSC +625 => PAL-N */
248 - RP1VEC_TVSTD_PAL60, /* +525 => PAL60 +625 => PAL */
249 - RP1VEC_TVSTD_DEFAULT, /* +525 => NTSC +625 => PAL */
250 -};
251 -
252 -/* Which standards support which modes? Those marked with + above */
253 -#define RP1VEC_TVSTD_SUPPORT_525(n) ((0xD7 >> (n)) & 1)
254 -#define RP1VEC_TVSTD_SUPPORT_625(n) ((0xEC >> (n)) & 1)
255 +#define RP1VEC_SUPPORTED_TV_MODES \
256 + (BIT(DRM_MODE_TV_MODE_NTSC) | \
257 + BIT(DRM_MODE_TV_MODE_NTSC_443) | \
258 + BIT(DRM_MODE_TV_MODE_NTSC_J) | \
259 + BIT(DRM_MODE_TV_MODE_PAL) | \
260 + BIT(DRM_MODE_TV_MODE_PAL_M) | \
261 + BIT(DRM_MODE_TV_MODE_PAL_N))
262
263 /* ---------------------------------------------------------------------- */
264
265 @@ -52,13 +45,10 @@ struct rp1_vec {
266 /* Block (VCC, CFG) base addresses, and current state */
267 void __iomem *hw_base[RP1VEC_NUM_HW_BLOCKS];
268 u32 cur_fmt;
269 - int tv_norm;
270 bool vec_running, pipe_enabled;
271 struct completion finished;
272 };
273
274 -extern const char * const rp1vec_tvstd_names[];
275 -
276 /* ---------------------------------------------------------------------- */
277 /* Functions to control the VEC/DMA block */
278
279 --- a/drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c
280 +++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c
281 @@ -337,16 +337,17 @@ void rp1vec_hw_setup(struct rp1_vec *vec
282 mode_ilaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
283 if (mode->vtotal >= 272 * (1 + mode_ilaced))
284 mode_family = 1;
285 + else if (tvstd == DRM_MODE_TV_MODE_PAL_M || tvstd == DRM_MODE_TV_MODE_PAL)
286 + mode_family = 2;
287 else
288 - mode_family = (tvstd == RP1VEC_TVSTD_PAL_M || tvstd == RP1VEC_TVSTD_PAL60) ? 2 : 0;
289 + mode_family = 0;
290 mode_narrow = (mode->clock >= 14336);
291 hwm = &rp1vec_hwmodes[mode_family][mode_ilaced][mode_narrow];
292 dev_info(&vec->pdev->dev,
293 - "%s: in_fmt=\'%c%c%c%c\' mode=%dx%d%s [%d%d%d] tvstd=%d (%s)",
294 + "%s: in_fmt=\'%c%c%c%c\' mode=%dx%d%s [%d%d%d] tvstd=%d",
295 __func__, in_format, in_format >> 8, in_format >> 16, in_format >> 24,
296 mode->hdisplay, mode->vdisplay, (mode_ilaced) ? "i" : "",
297 - mode_family, mode_ilaced, mode_narrow,
298 - tvstd, rp1vec_tvstd_names[tvstd]);
299 + mode_family, mode_ilaced, mode_narrow, tvstd);
300
301 w = mode->hdisplay;
302 h = mode->vdisplay >> mode_ilaced;
303 @@ -405,7 +406,7 @@ void rp1vec_hw_setup(struct rp1_vec *vec
304 }
305
306 /* Apply modifications */
307 - if (tvstd == RP1VEC_TVSTD_NTSC_J && mode_family == 0) {
308 + if (tvstd == DRM_MODE_TV_MODE_NTSC_J && mode_family == 0) {
309 /* Reduce pedestal (not quite to zero, for FIR overshoot); increase gain */
310 VEC_WRITE(VEC_DAC_BC,
311 BITS(VEC_DAC_BC_S11_PEDESTAL, 10) |
312 @@ -414,14 +415,14 @@ void rp1vec_hw_setup(struct rp1_vec *vec
313 BITS(VEC_DAC_C8_U16_SCALE_LUMA, 0x9400) |
314 (hwm->back_end_regs[(0xC8 - 0x80) / 4] &
315 ~VEC_DAC_C8_U16_SCALE_LUMA_BITS));
316 - } else if ((tvstd == RP1VEC_TVSTD_NTSC_443 || tvstd == RP1VEC_TVSTD_PAL60) &&
317 + } else if ((tvstd == DRM_MODE_TV_MODE_NTSC_443 || tvstd == DRM_MODE_TV_MODE_PAL) &&
318 mode_family != 1) {
319 /* Change colour carrier frequency to 4433618.75 Hz; disable hard sync */
320 VEC_WRITE(VEC_DAC_D4, 0xcc48c1d1);
321 VEC_WRITE(VEC_DAC_D8, 0x0a8262b2);
322 VEC_WRITE(VEC_DAC_EC,
323 hwm->back_end_regs[(0xEC - 0x80) / 4] & ~VEC_DAC_EC_SEQ_EN_BITS);
324 - } else if (tvstd == RP1VEC_TVSTD_PAL_N && mode_family == 1) {
325 + } else if (tvstd == DRM_MODE_TV_MODE_PAL_N && mode_family == 1) {
326 /* Change colour carrier frequency to 3582056.25 Hz */
327 VEC_WRITE(VEC_DAC_D4, 0x9ce075f7);
328 VEC_WRITE(VEC_DAC_D8, 0x087da511);