Skip to content

Commit 3650062

Browse files
6by9mripard
authored andcommitted
drm/vc4: hdmi: Move pixel doubling from Pixelvalve to HDMI block
With the change to 2 pixels/clock, the pixel doubling in the PV results in doubling each pair of pixels, ie ABABCDCD instead of AABBCCDD. Move the pixel doubling to the HDMI block, however this means that DBLCLK modes now fall foul of requiring even values for all the horizontal timing parameters. As both 480i and 576i fail this, attempt to fix up DBLCLK modes that have odd timings values. Fixes: 8323989 ("drm/vc4: hdmi: Support the BCM2711 HDMI controllers") Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://lore.kernel.org/r/20220613144800.326124-34-maxime@cerno.tech Signed-off-by: Maxime Ripard <maxime@cerno.tech>
1 parent fb10dc4 commit 3650062

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

drivers/gpu/drm/vc4/vc4_crtc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,9 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
317317
struct drm_crtc_state *crtc_state = crtc->state;
318318
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
319319
bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
320-
u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
320+
bool is_hdmi = vc4_encoder->type == VC4_ENCODER_TYPE_HDMI0 ||
321+
vc4_encoder->type == VC4_ENCODER_TYPE_HDMI1;
322+
u32 pixel_rep = ((mode->flags & DRM_MODE_FLAG_DBLCLK) && !is_hdmi) ? 2 : 1;
321323
bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
322324
vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
323325
bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1;

drivers/gpu/drm/vc4/vc4_hdmi.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@
7979
#define VC5_HDMI_VERTB_VSPO_SHIFT 16
8080
#define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16)
8181

82+
#define VC4_HDMI_MISC_CONTROL_PIXEL_REP_SHIFT 0
83+
#define VC4_HDMI_MISC_CONTROL_PIXEL_REP_MASK VC4_MASK(3, 0)
8284
#define VC5_HDMI_MISC_CONTROL_PIXEL_REP_SHIFT 0
8385
#define VC5_HDMI_MISC_CONTROL_PIXEL_REP_MASK VC4_MASK(3, 0)
8486

@@ -992,6 +994,7 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
992994
mode->crtc_vsync_end,
993995
VC4_HDMI_VERTB_VBP));
994996
unsigned long flags;
997+
u32 reg;
995998

996999
spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
9971000

@@ -1018,6 +1021,11 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
10181021
HDMI_WRITE(HDMI_VERTB0, vertb_even);
10191022
HDMI_WRITE(HDMI_VERTB1, vertb);
10201023

1024+
reg = HDMI_READ(HDMI_MISC_CONTROL);
1025+
reg &= ~VC4_HDMI_MISC_CONTROL_PIXEL_REP_MASK;
1026+
reg |= VC4_SET_FIELD(pixel_rep - 1, VC4_HDMI_MISC_CONTROL_PIXEL_REP);
1027+
HDMI_WRITE(HDMI_MISC_CONTROL, reg);
1028+
10211029
spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
10221030
}
10231031

@@ -1118,7 +1126,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
11181126

11191127
reg = HDMI_READ(HDMI_MISC_CONTROL);
11201128
reg &= ~VC5_HDMI_MISC_CONTROL_PIXEL_REP_MASK;
1121-
reg |= VC4_SET_FIELD(0, VC5_HDMI_MISC_CONTROL_PIXEL_REP);
1129+
reg |= VC4_SET_FIELD(pixel_rep - 1, VC5_HDMI_MISC_CONTROL_PIXEL_REP);
11221130
HDMI_WRITE(HDMI_MISC_CONTROL, reg);
11231131

11241132
HDMI_WRITE(HDMI_CLOCK_STOP, 0);
@@ -1617,11 +1625,25 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
16171625
unsigned long long tmds_bit_rate;
16181626
int ret;
16191627

1620-
if (vc4_hdmi->variant->unsupported_odd_h_timings &&
1621-
!(mode->flags & DRM_MODE_FLAG_DBLCLK) &&
1622-
((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
1623-
(mode->hsync_end % 2) || (mode->htotal % 2)))
1624-
return -EINVAL;
1628+
if (vc4_hdmi->variant->unsupported_odd_h_timings) {
1629+
if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
1630+
/* Only try to fixup DBLCLK modes to get 480i and 576i
1631+
* working.
1632+
* A generic solution for all modes with odd horizontal
1633+
* timing values seems impossible based on trying to
1634+
* solve it for 1366x768 monitors.
1635+
*/
1636+
if ((mode->hsync_start - mode->hdisplay) & 1)
1637+
mode->hsync_start--;
1638+
if ((mode->hsync_end - mode->hsync_start) & 1)
1639+
mode->hsync_end--;
1640+
}
1641+
1642+
/* Now check whether we still have odd values remaining */
1643+
if ((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
1644+
(mode->hsync_end % 2) || (mode->htotal % 2))
1645+
return -EINVAL;
1646+
}
16251647

16261648
/*
16271649
* The 1440p@60 pixel rate is in the same range than the first

0 commit comments

Comments
 (0)