bcm27xx: 6.1: add kernel patches
[openwrt/staging/nbd.git] / target / linux / bcm27xx / patches-6.1 / 950-0006-drm-vc4-Fix-timings-for-VEC-modes.patch
1 From 607f72974246d1495059932286b3d5307c1645a5 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 1 file changed, 43 insertions(+), 27 deletions(-)
23
24 --- a/drivers/gpu/drm/vc4/vc4_crtc.c
25 +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
26 @@ -326,8 +326,14 @@ static void vc4_crtc_config_pv(struct dr
27 bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
28 vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
29 bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1;
30 + bool is_vec = vc4_encoder->type == VC4_ENCODER_TYPE_VEC;
31 u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
32 u8 ppc = pv_data->pixels_per_clock;
33 +
34 + u16 vert_bp = mode->crtc_vtotal - mode->crtc_vsync_end;
35 + u16 vert_sync = mode->crtc_vsync_end - mode->crtc_vsync_start;
36 + u16 vert_fp = mode->crtc_vsync_start - mode->crtc_vdisplay;
37 +
38 bool debug_dump_regs = false;
39 int idx;
40
41 @@ -355,49 +361,59 @@ static void vc4_crtc_config_pv(struct dr
42 VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc,
43 PV_HORZB_HACTIVE));
44
45 - CRTC_WRITE(PV_VERTA,
46 - VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end +
47 - interlace,
48 - PV_VERTA_VBP) |
49 - VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
50 - PV_VERTA_VSYNC));
51 - CRTC_WRITE(PV_VERTB,
52 - VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
53 - PV_VERTB_VFP) |
54 - VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
55 -
56 if (interlace) {
57 + bool odd_field_first = false;
58 + u32 field_delay = mode->htotal * pixel_rep / (2 * ppc);
59 + u16 vert_bp_even = vert_bp;
60 + u16 vert_fp_even = vert_fp;
61 +
62 + if (is_vec) {
63 + /* VEC (composite output) */
64 + ++field_delay;
65 + if (mode->htotal == 858) {
66 + /* 525-line mode (NTSC or PAL-M) */
67 + odd_field_first = true;
68 + }
69 + }
70 +
71 + if (odd_field_first)
72 + ++vert_fp_even;
73 + else
74 + ++vert_bp;
75 +
76 CRTC_WRITE(PV_VERTA_EVEN,
77 - VC4_SET_FIELD(mode->crtc_vtotal -
78 - mode->crtc_vsync_end,
79 - PV_VERTA_VBP) |
80 - VC4_SET_FIELD(mode->crtc_vsync_end -
81 - mode->crtc_vsync_start,
82 - PV_VERTA_VSYNC));
83 + VC4_SET_FIELD(vert_bp_even, PV_VERTA_VBP) |
84 + VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
85 CRTC_WRITE(PV_VERTB_EVEN,
86 - VC4_SET_FIELD(mode->crtc_vsync_start -
87 - mode->crtc_vdisplay,
88 - PV_VERTB_VFP) |
89 + VC4_SET_FIELD(vert_fp_even, PV_VERTB_VFP) |
90 VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
91
92 - /* We set up first field even mode for HDMI. VEC's
93 - * NTSC mode would want first field odd instead, once
94 - * we support it (to do so, set ODD_FIRST and put the
95 - * delay in VSYNCD_EVEN instead).
96 + /* We set up first field even mode for HDMI and VEC's PAL.
97 + * For NTSC, we need first field odd.
98 */
99 CRTC_WRITE(PV_V_CONTROL,
100 PV_VCONTROL_CONTINUOUS |
101 (is_dsi ? PV_VCONTROL_DSI : 0) |
102 PV_VCONTROL_INTERLACE |
103 - VC4_SET_FIELD(mode->htotal * pixel_rep / (2 * ppc),
104 - PV_VCONTROL_ODD_DELAY));
105 - CRTC_WRITE(PV_VSYNCD_EVEN, 0);
106 + (odd_field_first
107 + ? PV_VCONTROL_ODD_FIRST
108 + : VC4_SET_FIELD(field_delay,
109 + PV_VCONTROL_ODD_DELAY)));
110 + CRTC_WRITE(PV_VSYNCD_EVEN,
111 + (odd_field_first ? field_delay : 0));
112 } else {
113 CRTC_WRITE(PV_V_CONTROL,
114 PV_VCONTROL_CONTINUOUS |
115 (is_dsi ? PV_VCONTROL_DSI : 0));
116 }
117
118 + CRTC_WRITE(PV_VERTA,
119 + VC4_SET_FIELD(vert_bp, PV_VERTA_VBP) |
120 + VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
121 + CRTC_WRITE(PV_VERTB,
122 + VC4_SET_FIELD(vert_fp, PV_VERTB_VFP) |
123 + VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
124 +
125 if (is_dsi)
126 CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
127