[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20221207-rpi-hvs-crtc-misc-v1-13-1f8e0770798b@cerno.tech>
Date: Wed, 07 Dec 2022 12:53:24 +0100
From: Maxime Ripard <maxime@...no.tech>
To: Emma Anholt <emma@...olt.net>, Maxime Ripard <mripard@...nel.org>,
David Airlie <airlied@...il.com>,
Daniel Vetter <daniel@...ll.ch>, Eric Anholt <eric@...olt.net>
Cc: dri-devel@...ts.freedesktop.org, linux-kernel@...r.kernel.org,
Dave Stevenson <dave.stevenson@...pberrypi.com>,
Mateusz Kwiatkowski <kfyatek+publicgit@...il.com>,
Maxime Ripard <maxime@...no.tech>
Subject: [PATCH 13/15] drm/vc4: crtc: Fix timings for VEC modes
From: Mateusz Kwiatkowski <kfyatek+publicgit@...il.com>
This commit fixes vertical timings of the VEC (composite output) modes
to accurately represent the 525-line ("NTSC") and 625-line ("PAL") ITU-R
standards.
Previous timings were actually defined as 502 and 601 lines, resulting
in non-standard 62.69 Hz and 52 Hz signals being generated,
respectively.
Changes to vc4_crtc.c have also been made, to make the PixelValve
vertical timings accurately correspond to the DRM modeline in interlaced
modes. The resulting VERTA/VERTB register values have been verified
against the reference values set by the Raspberry Pi firmware.
Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@...il.com>
Signed-off-by: Maxime Ripard <maxime@...no.tech>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 71 ++++++++++++++++++++++++++----------------
1 file changed, 44 insertions(+), 27 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 333529ed3a0d..91181cac01e4 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -326,8 +326,14 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
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;
+
+ u16 vert_bp = mode->crtc_vtotal - mode->crtc_vsync_end;
+ u16 vert_sync = mode->crtc_vsync_end - mode->crtc_vsync_start;
+ u16 vert_fp = mode->crtc_vsync_start - mode->crtc_vdisplay;
+
bool debug_dump_regs = false;
int idx;
@@ -355,49 +361,60 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc,
PV_HORZB_HACTIVE));
- CRTC_WRITE(PV_VERTA,
- VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end +
- interlace,
- PV_VERTA_VBP) |
- VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
- PV_VERTA_VSYNC));
- CRTC_WRITE(PV_VERTB,
- VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
- PV_VERTB_VFP) |
- VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
-
if (interlace) {
+ bool odd_field_first = false;
+ u32 field_delay = mode->htotal * pixel_rep / (2 * ppc);
+ u16 vert_bp_even = vert_bp;
+ u16 vert_fp_even = vert_fp;
+
+ if (is_vec) {
+ /* VEC (composite output) */
+ ++field_delay;
+ if (mode->htotal == 858) {
+ /* 525-line mode (NTSC or PAL-M) */
+ odd_field_first = true;
+ }
+ }
+
+ if (odd_field_first)
+ ++vert_fp_even;
+ else
+ ++vert_bp;
+
CRTC_WRITE(PV_VERTA_EVEN,
- VC4_SET_FIELD(mode->crtc_vtotal -
- mode->crtc_vsync_end,
- PV_VERTA_VBP) |
- VC4_SET_FIELD(mode->crtc_vsync_end -
- mode->crtc_vsync_start,
- PV_VERTA_VSYNC));
+ VC4_SET_FIELD(vert_bp_even, PV_VERTA_VBP) |
+ VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
CRTC_WRITE(PV_VERTB_EVEN,
- VC4_SET_FIELD(mode->crtc_vsync_start -
- mode->crtc_vdisplay,
- PV_VERTB_VFP) |
+ VC4_SET_FIELD(vert_fp_even, PV_VERTB_VFP) |
VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
- /* We set up first field even mode for HDMI. VEC's
- * NTSC mode would want first field odd instead, once
- * we support it (to do so, set ODD_FIRST and put the
- * delay in VSYNCD_EVEN instead).
+ /* We set up first field even mode for HDMI and VEC's PAL.
+ * For NTSC, we need first field odd.
*/
CRTC_WRITE(PV_V_CONTROL,
PV_VCONTROL_CONTINUOUS |
(is_dsi ? PV_VCONTROL_DSI : 0) |
PV_VCONTROL_INTERLACE |
- VC4_SET_FIELD(mode->htotal * pixel_rep / (2 * ppc),
- PV_VCONTROL_ODD_DELAY));
- CRTC_WRITE(PV_VSYNCD_EVEN, 0);
+ (odd_field_first
+ ? PV_VCONTROL_ODD_FIRST
+ : VC4_SET_FIELD(field_delay,
+ PV_VCONTROL_ODD_DELAY)));
+ CRTC_WRITE(PV_VSYNCD_EVEN,
+ (odd_field_first ? field_delay : 0));
} else {
CRTC_WRITE(PV_V_CONTROL,
PV_VCONTROL_CONTINUOUS |
(is_dsi ? PV_VCONTROL_DSI : 0));
+ CRTC_WRITE(PV_VSYNCD_EVEN, 0);
}
+ CRTC_WRITE(PV_VERTA,
+ VC4_SET_FIELD(vert_bp, PV_VERTA_VBP) |
+ VC4_SET_FIELD(vert_sync, PV_VERTA_VSYNC));
+ CRTC_WRITE(PV_VERTB,
+ VC4_SET_FIELD(vert_fp, PV_VERTB_VFP) |
+ VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE));
+
if (is_dsi)
CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
--
2.38.1
Powered by blists - more mailing lists