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
|
From 9835bb0108ea7e895f4c35f6295dce243e58d13f Mon Sep 17 00:00:00 2001
From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Date: Thu, 15 Jul 2021 01:08:01 +0200
Subject: [PATCH] drm/vc4: Allow setting the TV norm via module
parameter
Similar to the ch7006 and nouveau drivers, introduce a "tv_mode" module
parameter that allow setting the TV norm by specifying vc4.tv_norm= on
the kernel command line.
If that is not specified, try inferring one of the most popular norms
(PAL or NTSC) from the video mode specified on the command line. On
Raspberry Pis, this causes the most common cases of the sdtv_mode
setting in config.txt to be respected.
Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
---
drivers/gpu/drm/vc4/vc4_vec.c | 72 ++++++++++++++++++++++++++++-------
1 file changed, 58 insertions(+), 14 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -66,7 +66,7 @@
#define VEC_CONFIG0_YCDELAY BIT(4)
#define VEC_CONFIG0_RAMPEN BIT(2)
#define VEC_CONFIG0_YCDIS BIT(2)
-#define VEC_CONFIG0_STD_MASK GENMASK(1, 0)
+#define VEC_CONFIG0_STD_MASK (VEC_CONFIG0_SECAM_STD | GENMASK(1, 0))
#define VEC_CONFIG0_NTSC_STD 0
#define VEC_CONFIG0_PAL_BDGHI_STD 1
#define VEC_CONFIG0_PAL_M_STD 2
@@ -185,6 +185,8 @@
#define VEC_DAC_MISC_DAC_RST_N BIT(0)
+static char *vc4_vec_tv_norm;
+
struct vc4_vec_variant {
u32 dac_config;
};
@@ -338,6 +340,44 @@ static const struct vc4_vec_tv_mode vc4_
},
};
+static const char * const tv_mode_names[] = {
+ [VC4_VEC_TV_MODE_NTSC] = "NTSC",
+ [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
+ [VC4_VEC_TV_MODE_NTSC_443] = "NTSC-443",
+ [VC4_VEC_TV_MODE_PAL] = "PAL",
+ [VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
+ [VC4_VEC_TV_MODE_PAL_N] = "PAL-N",
+ [VC4_VEC_TV_MODE_PAL60] = "PAL60",
+ [VC4_VEC_TV_MODE_SECAM] = "SECAM",
+};
+
+enum vc4_vec_tv_mode_id
+vc4_vec_get_default_mode(struct drm_connector *connector)
+{
+ int i;
+
+ if (vc4_vec_tv_norm) {
+ for (i = 0; i < ARRAY_SIZE(tv_mode_names); i++)
+ if (strcmp(vc4_vec_tv_norm, tv_mode_names[i]) == 0)
+ return (enum vc4_vec_tv_mode_id) i;
+ } else if (connector->cmdline_mode.specified &&
+ ((connector->cmdline_mode.refresh_specified &&
+ (connector->cmdline_mode.refresh == 25 ||
+ connector->cmdline_mode.refresh == 50)) ||
+ (!connector->cmdline_mode.refresh_specified &&
+ (connector->cmdline_mode.yres == 288 ||
+ connector->cmdline_mode.yres == 576)))) {
+ /*
+ * no explicitly specified TV norm; use PAL if a mode that
+ * looks like PAL has been specified on the command line
+ */
+ return VC4_VEC_TV_MODE_PAL;
+ }
+
+ /* in all other cases, default to NTSC */
+ return VC4_VEC_TV_MODE_NTSC;
+}
+
static enum drm_connector_status
vc4_vec_connector_detect(struct drm_connector *connector, bool force)
{
@@ -367,11 +407,19 @@ static int vc4_vec_connector_get_modes(s
return 1;
}
+static void vc4_vec_connector_reset(struct drm_connector *connector)
+{
+ drm_atomic_helper_connector_reset(connector);
+ /* preserve TV standard */
+ if (connector->state)
+ connector->state->tv.mode = vc4_vec_get_default_mode(connector);
+}
+
static const struct drm_connector_funcs vc4_vec_connector_funcs = {
.detect = vc4_vec_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = vc4_vec_connector_destroy,
- .reset = drm_atomic_helper_connector_reset,
+ .reset = vc4_vec_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
@@ -403,7 +451,7 @@ static struct drm_connector *vc4_vec_con
drm_object_attach_property(&connector->base,
dev->mode_config.tv_mode_property,
- VC4_VEC_TV_MODE_NTSC);
+ vc4_vec_get_default_mode(connector));
drm_connector_attach_encoder(connector, vec->encoder);
@@ -555,17 +603,6 @@ static const struct of_device_id vc4_vec
{ /* sentinel */ },
};
-static const char * const tv_mode_names[] = {
- [VC4_VEC_TV_MODE_NTSC] = "NTSC",
- [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
- [VC4_VEC_TV_MODE_NTSC_443] = "NTSC-443",
- [VC4_VEC_TV_MODE_PAL] = "PAL",
- [VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
- [VC4_VEC_TV_MODE_PAL_N] = "PAL-N",
- [VC4_VEC_TV_MODE_PAL60] = "PAL60",
- [VC4_VEC_TV_MODE_SECAM] = "SECAM",
-};
-
static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -674,3 +711,10 @@ struct platform_driver vc4_vec_driver =
.of_match_table = vc4_vec_dt_match,
},
};
+
+module_param_named(tv_norm, vc4_vec_tv_norm, charp, 0600);
+MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
+ "\t\tSupported: NTSC, NTSC-J, NTSC-443, PAL, PAL-M, PAL-N,\n"
+ "\t\t\tPAL60, SECAM.\n"
+ "\t\tDefault: PAL if a 50 Hz mode has been set via video=,\n"
+ "\t\t\tNTSC otherwise");
|