bcm27xx: switch to 5.15
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.10 / 950-0699-drm-vc4-Fix-timings-for-VEC-modes.patch
1 From 023e20cf561dc49897997f55e88b7d336eb5cee9 Mon Sep 17 00:00:00 2001
2 From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
3 Date: Thu, 15 Jul 2021 01:07:30 +0200
4 Subject: [PATCH] drm/vc4: Fix timings for VEC modes
5
6 This commit fixes vertical timings of the VEC (composite output) modes
7 to accurately represent the 525-line ("NTSC") and 625-line ("PAL") ITU-R
8 standards.
9
10 Previous timings were actually defined as 502 and 601 lines, resulting
11 in non-standard 62.69 Hz and 52 Hz signals being generated,
12 respectively.
13
14 Changes to vc4_crtc.c have also been made, to make the PixelValve
15 vertical timings accurately correspond to the DRM modeline in interlaced
16 modes. The resulting VERTA/VERTB register values have been verified
17 against the reference values set by the Raspberry Pi firmware.
18
19 Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
20 ---
21 drivers/gpu/drm/vc4/vc4_crtc.c | 70 +++++++++++++++++++++-------------
22 drivers/gpu/drm/vc4/vc4_vec.c | 4 +-
23 2 files changed, 45 insertions(+), 29 deletions(-)
24
25 --- a/drivers/gpu/drm/vc4/vc4_crtc.c
26 +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
27 @@ -316,8 +316,14 @@ static void vc4_crtc_config_pv(struct dr
28 bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
29 vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
30 bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1;
31 + bool is_vec = vc4_encoder->type == VC4_ENCODER_TYPE_VEC;
32 u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
33 u8 ppc = pv_data->pixels_per_clock;
34 +
35 + u16 vert_bp = mode->crtc_vtotal - mode->crtc_vsync_end;
36 + u16 vert_sync = mode->crtc_vsync_end - mode->crtc_vsync_start;
37 + u16 vert_fp = mode->crtc_vsync_start - mode->crtc_vdisplay;
38 +
39 bool debug_dump_regs = false;
40
41 if (debug_dump_regs) {
42 @@ -341,49 +347,59 @@ static void vc4_crtc_config_pv(struct dr
43 VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc,
44 PV_HORZB_HACTIVE));
45
46 - CRTC_WRITE(PV_VERTA,
47 - VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end +
48 - interlace,
49 - PV_VERTA_VBP) |
50 - VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
51 - PV_VERTA_VSYNC));
52 - CRTC_WRITE(PV_VERTB,
53 - VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
54 - PV_VERTB_VFP) |
55 - VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
56 -
57 if (interlace) {
58 + bool odd_field_first = false;
59 + u32 field_delay = mode->htotal * pixel_rep / (2 * ppc);
60 + u16 vert_bp_even = vert_bp;
61 + u16 vert_fp_even = vert_fp;
62 +
63 + if (is_vec) {
64 + /* VEC (composite output) */
65 + ++field_delay;
66 + if (mode->htotal == 858) {
67 + /* 525-line mode (NTSC or PAL-M) */
68 + odd_field_first = true;
69 + }
70 + }
71 +
72 + if (odd_field_first)
73 + ++vert_fp_even;
74 + else
75 + ++vert_bp;
76 +
77 CRTC_WRITE(PV_VERTA_EVEN,
78 - VC4_SET_FIELD(mode->crtc_vtotal -
79 - mode->crtc_vsync_end,
80 - PV_VERTA_VBP) |
81 - VC4_SET_FIELD(mode->crtc_vsync_end -
82 - mode->crtc_vsync_start,
83 - PV_VERTA_VSYNC));
84 + VC4_SET_FIELD(vert_bp_even, PV_VERTA_VBP) |
85 + VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
86 CRTC_WRITE(PV_VERTB_EVEN,
87 - VC4_SET_FIELD(mode->crtc_vsync_start -
88 - mode->crtc_vdisplay,
89 - PV_VERTB_VFP) |
90 + VC4_SET_FIELD(vert_fp_even, PV_VERTB_VFP) |
91 VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
92
93 - /* We set up first field even mode for HDMI. VEC's
94 - * NTSC mode would want first field odd instead, once
95 - * we support it (to do so, set ODD_FIRST and put the
96 - * delay in VSYNCD_EVEN instead).
97 + /* We set up first field even mode for HDMI and VEC's PAL.
98 + * For NTSC, we need first field odd.
99 */
100 CRTC_WRITE(PV_V_CONTROL,
101 PV_VCONTROL_CONTINUOUS |
102 (is_dsi ? PV_VCONTROL_DSI : 0) |
103 PV_VCONTROL_INTERLACE |
104 - VC4_SET_FIELD(mode->htotal * pixel_rep / (2 * ppc),
105 - PV_VCONTROL_ODD_DELAY));
106 - CRTC_WRITE(PV_VSYNCD_EVEN, 0);
107 + (odd_field_first
108 + ? PV_VCONTROL_ODD_FIRST
109 + : VC4_SET_FIELD(field_delay,
110 + PV_VCONTROL_ODD_DELAY)));
111 + CRTC_WRITE(PV_VSYNCD_EVEN,
112 + (odd_field_first ? field_delay : 0));
113 } else {
114 CRTC_WRITE(PV_V_CONTROL,
115 PV_VCONTROL_CONTINUOUS |
116 (is_dsi ? PV_VCONTROL_DSI : 0));
117 }
118
119 + CRTC_WRITE(PV_VERTA,
120 + VC4_SET_FIELD(vert_bp, PV_VERTA_VBP) |
121 + VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
122 + CRTC_WRITE(PV_VERTB,
123 + VC4_SET_FIELD(vert_fp, PV_VERTB_VFP) |
124 + VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
125 +
126 if (is_dsi)
127 CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
128
129 --- a/drivers/gpu/drm/vc4/vc4_vec.c
130 +++ b/drivers/gpu/drm/vc4/vc4_vec.c
131 @@ -262,7 +262,7 @@ static void vc4_vec_ntsc_j_mode_set(stru
132 static const struct drm_display_mode ntsc_mode = {
133 DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
134 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
135 - 480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0,
136 + 480, 480 + 7, 480 + 7 + 6, 525, 0,
137 DRM_MODE_FLAG_INTERLACE)
138 };
139
140 @@ -284,7 +284,7 @@ static void vc4_vec_pal_m_mode_set(struc
141 static const struct drm_display_mode pal_mode = {
142 DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
143 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
144 - 576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0,
145 + 576, 576 + 4, 576 + 4 + 6, 625, 0,
146 DRM_MODE_FLAG_INTERLACE)
147 };
148