2020-09-03 08:10:50

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH v5 56/80] 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.

Tested-by: Chanwoo Choi <[email protected]>
Tested-by: Hoegeun Kwon <[email protected]>
Tested-by: Stefan Wahren <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/vc4/vc4_hdmi.c | 72 +++++++++++++++++++----------------
drivers/gpu/drm/vc4/vc4_hdmi.h | 4 ++-
2 files changed, 44 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 532618e02399..9e2bc6cb690e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -369,12 +369,9 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
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;
@@ -392,6 +389,41 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
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);
@@ -435,33 +467,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
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) {
@@ -1445,6 +1452,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
.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,
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index c8fd58548ea2..0c32dc46d289 100644
--- 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);
--
git-series 0.9.1


2020-09-04 15:51:52

by Dave Stevenson

[permalink] [raw]
Subject: Re: [PATCH v5 56/80] drm/vc4: hdmi: Add a set_timings callback

Hi Maxime

On Thu, 3 Sep 2020 at 09:03, Maxime Ripard <[email protected]> wrote:
>
> 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.
>
> Tested-by: Chanwoo Choi <[email protected]>
> Tested-by: Hoegeun Kwon <[email protected]>
> Tested-by: Stefan Wahren <[email protected]>
> Signed-off-by: Maxime Ripard <[email protected]>

Reviewed-by: Dave Stevenson <[email protected]>

> ---
> drivers/gpu/drm/vc4/vc4_hdmi.c | 72 +++++++++++++++++++----------------
> drivers/gpu/drm/vc4/vc4_hdmi.h | 4 ++-
> 2 files changed, 44 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 532618e02399..9e2bc6cb690e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -369,12 +369,9 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
> 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;
> @@ -392,6 +389,41 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> 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);
> @@ -435,33 +467,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> 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) {
> @@ -1445,6 +1452,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
> .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,
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index c8fd58548ea2..0c32dc46d289 100644
> --- 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);
> --
> git-series 0.9.1