openwrt/target/linux/bcm27xx/patches-5.4/950-0580-drm-vc4-hdmi-Add-a-set_timings-callback.patch
Álvaro Fernández Rojas f07e572f64 bcm27xx: import latest patches from the RPi foundation
bcm2708: boot tested on RPi B+ v1.2
bcm2709: boot tested on RPi 3B v1.2 and RPi 4B v1.1 4G
bcm2710: boot tested on RPi 3B v1.2
bcm2711: boot tested on RPi 4B v1.1 4G

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2021-02-18 23:42:32 +01:00

134 lines
4.7 KiB
Diff

From b9c57901c600e09b100942b637c6bb01e52b7326 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime@cerno.tech>
Date: Mon, 6 Jan 2020 13:43:27 +0100
Subject: [PATCH] drm/vc4: hdmi: Add a set_timings callback
Similarly to the previous patches, the timings setup in the HDMI controller
of the BCM2711 is slightly different, mostly because it supports higher
resolutions and thus needed more spaces for the various timings, resulting
in the register layout changing.
Let's add a callback for that as well.
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
drivers/gpu/drm/vc4/vc4_hdmi.c | 71 +++++++++++++++++++---------------
drivers/gpu/drm/vc4/vc4_hdmi.h | 4 ++
2 files changed, 44 insertions(+), 31 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -372,12 +372,9 @@ static void vc4_hdmi_csc_setup(struct vc
HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
}
-static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
+ struct drm_display_mode *mode)
{
- struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
- struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
- bool debug_dump_regs = false;
bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
@@ -395,6 +392,41 @@ static void vc4_hdmi_encoder_enable(stru
mode->crtc_vsync_end -
interlaced,
VC4_HDMI_VERTB_VBP));
+
+ HDMI_WRITE(HDMI_HORZA,
+ (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
+ (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
+ VC4_SET_FIELD(mode->hdisplay * pixel_rep,
+ VC4_HDMI_HORZA_HAP));
+
+ HDMI_WRITE(HDMI_HORZB,
+ VC4_SET_FIELD((mode->htotal -
+ mode->hsync_end) * pixel_rep,
+ VC4_HDMI_HORZB_HBP) |
+ VC4_SET_FIELD((mode->hsync_end -
+ mode->hsync_start) * pixel_rep,
+ VC4_HDMI_HORZB_HSP) |
+ VC4_SET_FIELD((mode->hsync_start -
+ mode->hdisplay) * pixel_rep,
+ VC4_HDMI_HORZB_HFP));
+
+ HDMI_WRITE(HDMI_VERTA0, verta);
+ HDMI_WRITE(HDMI_VERTA1, verta);
+
+ HDMI_WRITE(HDMI_VERTB0, vertb_even);
+ HDMI_WRITE(HDMI_VERTB1, vertb);
+
+ HDMI_WRITE(HDMI_VID_CTL,
+ (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+ (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
+}
+
+static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+ struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+ struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+ bool debug_dump_regs = false;
int ret;
ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
@@ -438,32 +470,8 @@ static void vc4_hdmi_encoder_enable(stru
VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
- HDMI_WRITE(HDMI_HORZA,
- (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
- (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
- VC4_SET_FIELD(mode->hdisplay * pixel_rep,
- VC4_HDMI_HORZA_HAP));
-
- HDMI_WRITE(HDMI_HORZB,
- VC4_SET_FIELD((mode->htotal -
- mode->hsync_end) * pixel_rep,
- VC4_HDMI_HORZB_HBP) |
- VC4_SET_FIELD((mode->hsync_end -
- mode->hsync_start) * pixel_rep,
- VC4_HDMI_HORZB_HSP) |
- VC4_SET_FIELD((mode->hsync_start -
- mode->hdisplay) * pixel_rep,
- VC4_HDMI_HORZB_HFP));
-
- HDMI_WRITE(HDMI_VERTA0, verta);
- HDMI_WRITE(HDMI_VERTA1, verta);
-
- HDMI_WRITE(HDMI_VERTB0, vertb_even);
- HDMI_WRITE(HDMI_VERTB1, vertb);
-
- HDMI_WRITE(HDMI_VID_CTL,
- (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
- (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
+ if (vc4_hdmi->variant->set_timings)
+ vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
if (vc4_encoder->hdmi_monitor &&
drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
@@ -1441,6 +1449,7 @@ static const struct vc4_hdmi_variant bcm
.init_resources = vc4_hdmi_init_resources,
.csc_setup = vc4_hdmi_csc_setup,
.reset = vc4_hdmi_reset,
+ .set_timings = vc4_hdmi_set_timings,
.phy_init = vc4_hdmi_phy_init,
.phy_disable = vc4_hdmi_phy_disable,
.phy_rng_enable = vc4_hdmi_phy_rng_enable,
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -44,6 +44,10 @@ struct vc4_hdmi_variant {
/* Callback to enable / disable the CSC */
void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable);
+ /* Callback to configure the video timings in the HDMI block */
+ void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
+ struct drm_display_mode *mode);
+
/* Callback to initialize the PHY according to the mode */
void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
struct drm_display_mode *mode);