lkml.org 
[lkml]   [2022]   [Dec]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 13/15] drm/vc4: crtc: Fix timings for VEC modes
    From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.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@gmail.com>
    Signed-off-by: Maxime Ripard <maxime@cerno.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

    \
     
     \ /
      Last update: 2022-12-07 12:57    [W:4.179 / U:0.164 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site