Commit 3650062e authored by Dave Stevenson's avatar Dave Stevenson Committed by Maxime Ripard

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: 83239891 ("drm/vc4: hdmi: Support the BCM2711 HDMI controllers")
Signed-off-by: default avatarDave Stevenson <dave.stevenson@raspberrypi.com>
Link: https://lore.kernel.org/r/20220613144800.326124-34-maxime@cerno.techSigned-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
parent fb10dc45
...@@ -317,7 +317,9 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode ...@@ -317,7 +317,9 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
struct drm_crtc_state *crtc_state = crtc->state; struct drm_crtc_state *crtc_state = crtc->state;
struct drm_display_mode *mode = &crtc_state->adjusted_mode; struct drm_display_mode *mode = &crtc_state->adjusted_mode;
bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; bool is_hdmi = vc4_encoder->type == VC4_ENCODER_TYPE_HDMI0 ||
vc4_encoder->type == VC4_ENCODER_TYPE_HDMI1;
u32 pixel_rep = ((mode->flags & DRM_MODE_FLAG_DBLCLK) && !is_hdmi) ? 2 : 1;
bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 || bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
vc4_encoder->type == VC4_ENCODER_TYPE_DSI1); vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1; bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1;
......
...@@ -79,6 +79,8 @@ ...@@ -79,6 +79,8 @@
#define VC5_HDMI_VERTB_VSPO_SHIFT 16 #define VC5_HDMI_VERTB_VSPO_SHIFT 16
#define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16) #define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16)
#define VC4_HDMI_MISC_CONTROL_PIXEL_REP_SHIFT 0
#define VC4_HDMI_MISC_CONTROL_PIXEL_REP_MASK VC4_MASK(3, 0)
#define VC5_HDMI_MISC_CONTROL_PIXEL_REP_SHIFT 0 #define VC5_HDMI_MISC_CONTROL_PIXEL_REP_SHIFT 0
#define VC5_HDMI_MISC_CONTROL_PIXEL_REP_MASK VC4_MASK(3, 0) #define VC5_HDMI_MISC_CONTROL_PIXEL_REP_MASK VC4_MASK(3, 0)
...@@ -992,6 +994,7 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, ...@@ -992,6 +994,7 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
mode->crtc_vsync_end, mode->crtc_vsync_end,
VC4_HDMI_VERTB_VBP)); VC4_HDMI_VERTB_VBP));
unsigned long flags; unsigned long flags;
u32 reg;
spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
...@@ -1018,6 +1021,11 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, ...@@ -1018,6 +1021,11 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB0, vertb_even);
HDMI_WRITE(HDMI_VERTB1, vertb); HDMI_WRITE(HDMI_VERTB1, vertb);
reg = HDMI_READ(HDMI_MISC_CONTROL);
reg &= ~VC4_HDMI_MISC_CONTROL_PIXEL_REP_MASK;
reg |= VC4_SET_FIELD(pixel_rep - 1, VC4_HDMI_MISC_CONTROL_PIXEL_REP);
HDMI_WRITE(HDMI_MISC_CONTROL, reg);
spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
} }
...@@ -1118,7 +1126,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, ...@@ -1118,7 +1126,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
reg = HDMI_READ(HDMI_MISC_CONTROL); reg = HDMI_READ(HDMI_MISC_CONTROL);
reg &= ~VC5_HDMI_MISC_CONTROL_PIXEL_REP_MASK; reg &= ~VC5_HDMI_MISC_CONTROL_PIXEL_REP_MASK;
reg |= VC4_SET_FIELD(0, VC5_HDMI_MISC_CONTROL_PIXEL_REP); reg |= VC4_SET_FIELD(pixel_rep - 1, VC5_HDMI_MISC_CONTROL_PIXEL_REP);
HDMI_WRITE(HDMI_MISC_CONTROL, reg); HDMI_WRITE(HDMI_MISC_CONTROL, reg);
HDMI_WRITE(HDMI_CLOCK_STOP, 0); HDMI_WRITE(HDMI_CLOCK_STOP, 0);
...@@ -1617,11 +1625,25 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, ...@@ -1617,11 +1625,25 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
unsigned long long tmds_bit_rate; unsigned long long tmds_bit_rate;
int ret; int ret;
if (vc4_hdmi->variant->unsupported_odd_h_timings && if (vc4_hdmi->variant->unsupported_odd_h_timings) {
!(mode->flags & DRM_MODE_FLAG_DBLCLK) && if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
((mode->hdisplay % 2) || (mode->hsync_start % 2) || /* Only try to fixup DBLCLK modes to get 480i and 576i
(mode->hsync_end % 2) || (mode->htotal % 2))) * working.
* A generic solution for all modes with odd horizontal
* timing values seems impossible based on trying to
* solve it for 1366x768 monitors.
*/
if ((mode->hsync_start - mode->hdisplay) & 1)
mode->hsync_start--;
if ((mode->hsync_end - mode->hsync_start) & 1)
mode->hsync_end--;
}
/* Now check whether we still have odd values remaining */
if ((mode->hdisplay % 2) || (mode->hsync_start % 2) ||
(mode->hsync_end % 2) || (mode->htotal % 2))
return -EINVAL; return -EINVAL;
}
/* /*
* The 1440p@60 pixel rate is in the same range than the first * The 1440p@60 pixel rate is in the same range than the first
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment