drm/vc4: crtc: Add support for BCM2712 PixelValves
authorMaxime Ripard <maxime@cerno.tech>
Fri, 17 Feb 2023 14:33:23 +0000 (15:33 +0100)
committerDom Cobley <popcornmix@gmail.com>
Mon, 19 Feb 2024 11:34:58 +0000 (11:34 +0000)
The PixelValves found on the BCM2712 are similar to the ones found in
the previous generation.

Compared to BCM2711, the pixelvalves only drive one HDMI controller each
and HDMI1 PixelValve has a FIFO long enough to support 4k at 60Hz.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_drv.h
drivers/gpu/drm/vc4/vc4_regs.h

index 181409c..ee30f2c 100644 (file)
@@ -240,6 +240,11 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
        const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc);
        const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
        struct vc4_dev *vc4 = to_vc4_dev(vc4_crtc->base.dev);
+
+       /*
+        * NOTE: Could we use register 0x68 (PV_HW_CFG1) to get the FIFO
+        * size?
+        */
        u32 fifo_len_bytes = pv_data->fifo_depth;
 
        /*
@@ -394,6 +399,12 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
 
        vc4_crtc_pixelvalve_reset(crtc);
 
+       /*
+        * NOTE: The BCM2712 has a H_OTE (Horizontal Odd Timing Enable)
+        * bit that, when set, will allow to specify the timings in
+        * pixels instead of cycles, thus allowing to specify odd
+        * timings.
+        */
        CRTC_WRITE(PV_HORZA,
                   VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc,
                                 PV_HORZA_HBP) |
@@ -463,11 +474,17 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
        if (is_dsi)
                CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
-       if (vc4->gen == VC4_GEN_5)
+       if (vc4->gen >= VC4_GEN_5)
                CRTC_WRITE(PV_MUX_CFG,
                           VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP,
                                         PV_MUX_CFG_RGB_PIXEL_MUX_MODE));
 
+       if (vc4->gen >= VC4_GEN_6)
+               CRTC_WRITE(PV_PIPE_INIT_CTRL,
+                          VC4_SET_FIELD(1, PV_PIPE_INIT_CTRL_PV_INIT_WIDTH) |
+                          VC4_SET_FIELD(1, PV_PIPE_INIT_CTRL_PV_INIT_IDLE) |
+                          PV_PIPE_INIT_CTRL_PV_INIT_EN);
+
        CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR |
                   vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
                   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
@@ -566,7 +583,11 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
        if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
                                      "brcm,bcm2711-pixelvalve2") ||
              of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
-                                     "brcm,bcm2711-pixelvalve4")))
+                                     "brcm,bcm2711-pixelvalve4") ||
+             of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
+                                     "brcm,bcm2712-pixelvalve0") ||
+             of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
+                                     "brcm,bcm2712-pixelvalve1")))
                return 0;
 
        if (!(CRTC_READ(PV_CONTROL) & PV_CONTROL_EN))
@@ -1302,6 +1323,32 @@ const struct vc4_pv_data bcm2711_pv4_data = {
        },
 };
 
+const struct vc4_pv_data bcm2712_pv0_data = {
+       .base = {
+               .debugfs_name = "crtc0_regs",
+               .hvs_available_channels = BIT(0),
+               .hvs_output = 0,
+       },
+       .fifo_depth = 64,
+       .pixels_per_clock = 2,
+       .encoder_types = {
+               [0] = VC4_ENCODER_TYPE_HDMI0,
+       },
+};
+
+const struct vc4_pv_data bcm2712_pv1_data = {
+       .base = {
+               .debugfs_name = "crtc1_regs",
+               .hvs_available_channels = BIT(1),
+               .hvs_output = 1,
+       },
+       .fifo_depth = 64,
+       .pixels_per_clock = 2,
+       .encoder_types = {
+               [0] = VC4_ENCODER_TYPE_HDMI1,
+       },
+};
+
 static const struct of_device_id vc4_crtc_dt_match[] = {
        { .compatible = "brcm,bcm2835-pixelvalve0", .data = &bcm2835_pv0_data },
        { .compatible = "brcm,bcm2835-pixelvalve1", .data = &bcm2835_pv1_data },
@@ -1311,6 +1358,8 @@ static const struct of_device_id vc4_crtc_dt_match[] = {
        { .compatible = "brcm,bcm2711-pixelvalve2", .data = &bcm2711_pv2_data },
        { .compatible = "brcm,bcm2711-pixelvalve3", .data = &bcm2711_pv3_data },
        { .compatible = "brcm,bcm2711-pixelvalve4", .data = &bcm2711_pv4_data },
+       { .compatible = "brcm,bcm2712-pixelvalve0", .data = &bcm2712_pv0_data },
+       { .compatible = "brcm,bcm2712-pixelvalve1", .data = &bcm2712_pv1_data },
        {}
 };
 
index 21b68a0..607c24c 100644 (file)
@@ -568,6 +568,8 @@ extern const struct vc4_pv_data bcm2711_pv1_data;
 extern const struct vc4_pv_data bcm2711_pv2_data;
 extern const struct vc4_pv_data bcm2711_pv3_data;
 extern const struct vc4_pv_data bcm2711_pv4_data;
+extern const struct vc4_pv_data bcm2712_pv0_data;
+extern const struct vc4_pv_data bcm2712_pv1_data;
 
 struct vc4_crtc {
        struct drm_crtc base;
index 66d7a81..f73d579 100644 (file)
 # define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_SHIFT   2
 # define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP 8
 
+#define PV_PIPE_INIT_CTRL                      0x94
+# define PV_PIPE_INIT_CTRL_PV_INIT_WIDTH_MASK  VC4_MASK(11, 8)
+# define PV_PIPE_INIT_CTRL_PV_INIT_IDLE_MASK   VC4_MASK(7, 4)
+# define PV_PIPE_INIT_CTRL_PV_INIT_EN          BIT(0)
+
 #define SCALER_CHANNELS_COUNT                  3
 
 #define SCALER_DISPCTRL                         0x00000000