ba08f6fa37ae4c3e937145da227f9e62a35f16bd
[openwrt/staging/linusw.git] /
1 From 2a153d97f5ea9086f309a0abef57dfe0b7a46e96 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] 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 | 72 ++++++++++++++++++++++++++++-------
19 1 file changed, 58 insertions(+), 14 deletions(-)
20
21 --- a/drivers/gpu/drm/vc4/vc4_vec.c
22 +++ b/drivers/gpu/drm/vc4/vc4_vec.c
23 @@ -66,7 +66,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 @@ -185,6 +185,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 @@ -344,6 +346,44 @@ static const struct vc4_vec_tv_mode vc4_
42 },
43 };
44
45 +static const char * const tv_mode_names[] = {
46 + [VC4_VEC_TV_MODE_NTSC] = "NTSC",
47 + [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
48 + [VC4_VEC_TV_MODE_NTSC_443] = "NTSC-443",
49 + [VC4_VEC_TV_MODE_PAL] = "PAL",
50 + [VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
51 + [VC4_VEC_TV_MODE_PAL_N] = "PAL-N",
52 + [VC4_VEC_TV_MODE_PAL60] = "PAL60",
53 + [VC4_VEC_TV_MODE_SECAM] = "SECAM",
54 +};
55 +
56 +enum vc4_vec_tv_mode_id
57 +vc4_vec_get_default_mode(struct drm_connector *connector)
58 +{
59 + int i;
60 +
61 + if (vc4_vec_tv_norm) {
62 + for (i = 0; i < ARRAY_SIZE(tv_mode_names); i++)
63 + if (strcmp(vc4_vec_tv_norm, tv_mode_names[i]) == 0)
64 + return (enum vc4_vec_tv_mode_id) i;
65 + } else if (connector->cmdline_mode.specified &&
66 + ((connector->cmdline_mode.refresh_specified &&
67 + (connector->cmdline_mode.refresh == 25 ||
68 + connector->cmdline_mode.refresh == 50)) ||
69 + (!connector->cmdline_mode.refresh_specified &&
70 + (connector->cmdline_mode.yres == 288 ||
71 + connector->cmdline_mode.yres == 576)))) {
72 + /*
73 + * no explicitly specified TV norm; use PAL if a mode that
74 + * looks like PAL has been specified on the command line
75 + */
76 + return VC4_VEC_TV_MODE_PAL;
77 + }
78 +
79 + /* in all other cases, default to NTSC */
80 + return VC4_VEC_TV_MODE_NTSC;
81 +}
82 +
83 static enum drm_connector_status
84 vc4_vec_connector_detect(struct drm_connector *connector, bool force)
85 {
86 @@ -373,11 +413,19 @@ static int vc4_vec_connector_get_modes(s
87 return 1;
88 }
89
90 +static void vc4_vec_connector_reset(struct drm_connector *connector)
91 +{
92 + drm_atomic_helper_connector_reset(connector);
93 + /* preserve TV standard */
94 + if (connector->state)
95 + connector->state->tv.mode = vc4_vec_get_default_mode(connector);
96 +}
97 +
98 static const struct drm_connector_funcs vc4_vec_connector_funcs = {
99 .detect = vc4_vec_connector_detect,
100 .fill_modes = drm_helper_probe_single_connector_modes,
101 .destroy = vc4_vec_connector_destroy,
102 - .reset = drm_atomic_helper_connector_reset,
103 + .reset = vc4_vec_connector_reset,
104 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
105 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
106 };
107 @@ -409,7 +457,7 @@ static struct drm_connector *vc4_vec_con
108
109 drm_object_attach_property(&connector->base,
110 dev->mode_config.tv_mode_property,
111 - VC4_VEC_TV_MODE_NTSC);
112 + vc4_vec_get_default_mode(connector));
113
114 drm_connector_attach_encoder(connector, vec->encoder);
115
116 @@ -561,17 +609,6 @@ static const struct of_device_id vc4_vec
117 { /* sentinel */ },
118 };
119
120 -static const char * const tv_mode_names[] = {
121 - [VC4_VEC_TV_MODE_NTSC] = "NTSC",
122 - [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
123 - [VC4_VEC_TV_MODE_NTSC_443] = "NTSC-443",
124 - [VC4_VEC_TV_MODE_PAL] = "PAL",
125 - [VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
126 - [VC4_VEC_TV_MODE_PAL_N] = "PAL-N",
127 - [VC4_VEC_TV_MODE_PAL60] = "PAL60",
128 - [VC4_VEC_TV_MODE_SECAM] = "SECAM",
129 -};
130 -
131 static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
132 {
133 struct platform_device *pdev = to_platform_device(dev);
134 @@ -680,3 +717,10 @@ struct platform_driver vc4_vec_driver =
135 .of_match_table = vc4_vec_dt_match,
136 },
137 };
138 +
139 +module_param_named(tv_norm, vc4_vec_tv_norm, charp, 0600);
140 +MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
141 + "\t\tSupported: NTSC, NTSC-J, NTSC-443, PAL, PAL-M, PAL-N,\n"
142 + "\t\t\tPAL60, SECAM.\n"
143 + "\t\tDefault: PAL if a 50 Hz mode has been set via video=,\n"
144 + "\t\t\tNTSC otherwise");