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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
|
From 485d11cfa7df2d2deb39c9b3455cebcb1a85cea2 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Thu, 25 Jul 2024 14:36:32 +0100
Subject: [PATCH 1199/1215] drm/vc4: Disable the 2pixel/clock odd timings
workaround for interlaced
Whilst BCM2712 does fix using odd horizontal timings, it doesn't
work with interlaced modes.
Drop the workaround for interlaced modes and revert to the same
behaviour as BCM2711.
https://github.com/raspberrypi/linux/issues/6281
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 20 +++++++++++++++++---
drivers/gpu/drm/vc4/vc4_drv.h | 2 ++
drivers/gpu/drm/vc4/vc4_hdmi.c | 8 +++++++-
drivers/gpu/drm/vc4/vc4_hdmi.h | 4 ++++
4 files changed, 30 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -378,7 +378,9 @@ static void vc4_crtc_config_pv(struct dr
bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1;
bool is_vec = vc4_encoder->type == VC4_ENCODER_TYPE_VEC;
u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
- u8 ppc = pv_data->pixels_per_clock;
+ u8 ppc = (mode->flags & DRM_MODE_FLAG_INTERLACE) ?
+ pv_data->pixels_per_clock_int :
+ pv_data->pixels_per_clock;
u16 vert_bp = mode->crtc_vtotal - mode->crtc_vsync_end;
u16 vert_sync = mode->crtc_vsync_end - mode->crtc_vsync_start;
@@ -443,7 +445,8 @@ static void vc4_crtc_config_pv(struct dr
*/
CRTC_WRITE(PV_V_CONTROL,
PV_VCONTROL_CONTINUOUS |
- (vc4->gen >= VC4_GEN_6 ? PV_VCONTROL_ODD_TIMING : 0) |
+ (vc4->gen >= VC4_GEN_6 && ppc == 1 ?
+ PV_VCONTROL_ODD_TIMING : 0) |
(is_dsi ? PV_VCONTROL_DSI : 0) |
PV_VCONTROL_INTERLACE |
(odd_field_first
@@ -455,7 +458,8 @@ static void vc4_crtc_config_pv(struct dr
} else {
CRTC_WRITE(PV_V_CONTROL,
PV_VCONTROL_CONTINUOUS |
- (vc4->gen >= VC4_GEN_6 ? PV_VCONTROL_ODD_TIMING : 0) |
+ (vc4->gen >= VC4_GEN_6 && ppc == 1 ?
+ PV_VCONTROL_ODD_TIMING : 0) |
(is_dsi ? PV_VCONTROL_DSI : 0));
CRTC_WRITE(PV_VSYNCD_EVEN, 0);
}
@@ -1223,6 +1227,7 @@ const struct vc4_pv_data bcm2835_pv0_dat
},
.fifo_depth = 64,
.pixels_per_clock = 1,
+ .pixels_per_clock_int = 1,
.encoder_types = {
[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_DPI,
@@ -1238,6 +1243,7 @@ const struct vc4_pv_data bcm2835_pv1_dat
},
.fifo_depth = 64,
.pixels_per_clock = 1,
+ .pixels_per_clock_int = 1,
.encoder_types = {
[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_SMI,
@@ -1253,6 +1259,7 @@ const struct vc4_pv_data bcm2835_pv2_dat
},
.fifo_depth = 64,
.pixels_per_clock = 1,
+ .pixels_per_clock_int = 1,
.encoder_types = {
[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI0,
[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
@@ -1268,6 +1275,7 @@ const struct vc4_pv_data bcm2711_pv0_dat
},
.fifo_depth = 64,
.pixels_per_clock = 1,
+ .pixels_per_clock_int = 1,
.encoder_types = {
[0] = VC4_ENCODER_TYPE_DSI0,
[1] = VC4_ENCODER_TYPE_DPI,
@@ -1283,6 +1291,7 @@ const struct vc4_pv_data bcm2711_pv1_dat
},
.fifo_depth = 64,
.pixels_per_clock = 1,
+ .pixels_per_clock_int = 1,
.encoder_types = {
[0] = VC4_ENCODER_TYPE_DSI1,
[1] = VC4_ENCODER_TYPE_SMI,
@@ -1298,6 +1307,7 @@ const struct vc4_pv_data bcm2711_pv2_dat
},
.fifo_depth = 256,
.pixels_per_clock = 2,
+ .pixels_per_clock_int = 2,
.encoder_types = {
[0] = VC4_ENCODER_TYPE_HDMI0,
},
@@ -1312,6 +1322,7 @@ const struct vc4_pv_data bcm2711_pv3_dat
},
.fifo_depth = 64,
.pixels_per_clock = 1,
+ .pixels_per_clock_int = 1,
.encoder_types = {
[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
},
@@ -1326,6 +1337,7 @@ const struct vc4_pv_data bcm2711_pv4_dat
},
.fifo_depth = 64,
.pixels_per_clock = 2,
+ .pixels_per_clock_int = 2,
.encoder_types = {
[0] = VC4_ENCODER_TYPE_HDMI1,
},
@@ -1339,6 +1351,7 @@ const struct vc4_pv_data bcm2712_pv0_dat
},
.fifo_depth = 64,
.pixels_per_clock = 1,
+ .pixels_per_clock_int = 2,
.encoder_types = {
[0] = VC4_ENCODER_TYPE_HDMI0,
},
@@ -1352,6 +1365,7 @@ const struct vc4_pv_data bcm2712_pv1_dat
},
.fifo_depth = 64,
.pixels_per_clock = 1,
+ .pixels_per_clock_int = 2,
.encoder_types = {
[0] = VC4_ENCODER_TYPE_HDMI1,
},
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -569,6 +569,8 @@ struct vc4_pv_data {
/* Number of pixels output per clock period */
u8 pixels_per_clock;
+ /* Number of pixels output per clock period when in an interlaced mode */
+ u8 pixels_per_clock_int;
enum vc4_encoder_type encoder_types[4];
};
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -2263,7 +2263,9 @@ static int vc4_hdmi_encoder_atomic_check
unsigned long long tmds_bit_rate;
int ret;
- if (vc4_hdmi->variant->unsupported_odd_h_timings) {
+ if (vc4_hdmi->variant->unsupported_odd_h_timings ||
+ (vc4_hdmi->variant->unsupported_int_odd_h_timings &&
+ (mode->flags & DRM_MODE_FLAG_INTERLACE))) {
if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
/* Only try to fixup DBLCLK modes to get 480i and 576i
* working.
@@ -3974,6 +3976,7 @@ static const struct vc4_hdmi_variant bcm
PHY_LANE_CK,
},
.unsupported_odd_h_timings = true,
+ .unsupported_int_odd_h_timings = true,
.external_irq_controller = true,
.init_resources = vc5_hdmi_init_resources,
@@ -4003,6 +4006,7 @@ static const struct vc4_hdmi_variant bcm
PHY_LANE_2,
},
.unsupported_odd_h_timings = true,
+ .unsupported_int_odd_h_timings = true,
.external_irq_controller = true,
.init_resources = vc5_hdmi_init_resources,
@@ -4032,6 +4036,7 @@ static const struct vc4_hdmi_variant bcm
PHY_LANE_CK,
},
.unsupported_odd_h_timings = false,
+ .unsupported_int_odd_h_timings = true,
.external_irq_controller = true,
.init_resources = vc5_hdmi_init_resources,
@@ -4059,6 +4064,7 @@ static const struct vc4_hdmi_variant bcm
PHY_LANE_CK,
},
.unsupported_odd_h_timings = false,
+ .unsupported_int_odd_h_timings = true,
.external_irq_controller = true,
.init_resources = vc5_hdmi_init_resources,
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -49,6 +49,10 @@ struct vc4_hdmi_variant {
/* The BCM2711 cannot deal with odd horizontal pixel timings */
bool unsupported_odd_h_timings;
+ /* The BCM2712 can handle odd horizontal pixel timings, but not in
+ * interlaced modes
+ */
+ bool unsupported_int_odd_h_timings;
/*
* The BCM2711 CEC/hotplug IRQ controller is shared between the
|