aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0261-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0261-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.4/950-0261-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch134
1 files changed, 134 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0261-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch b/target/linux/bcm27xx/patches-5.4/950-0261-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch
new file mode 100644
index 0000000000..186a7c891f
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.4/950-0261-drm-vc4-fkms-to-query-the-VPU-for-HDMI-clock-limits.patch
@@ -0,0 +1,134 @@
+From 1a8e3d8e883b9f9b18dff052a9294d4354994992 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Thu, 30 May 2019 13:56:15 +0100
+Subject: [PATCH] drm/vc4: fkms to query the VPU for HDMI clock limits
+
+The VPU has configured clocks for 4k (or not) via config.txt,
+and will limit the choice of video modes based on that.
+Make fkms query it for these limits too to avoid selecting modes
+that can not be handled by the current clock setup.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/gpu/drm/vc4/vc4_drv.h | 1 +
+ drivers/gpu/drm/vc4/vc4_firmware_kms.c | 48 ++++++++++++++++++++++
+ include/soc/bcm2835/raspberrypi-firmware.h | 1 +
+ 3 files changed, 50 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_drv.h
++++ b/drivers/gpu/drm/vc4/vc4_drv.h
+@@ -81,6 +81,7 @@ struct vc4_dev {
+ struct vc4_dsi *dsi1;
+ struct vc4_vec *vec;
+ struct vc4_txp *txp;
++ struct vc4_fkms *fkms;
+
+ struct vc4_hang_state *hang_state;
+
+--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+@@ -32,6 +32,14 @@
+ #include "vc_image_types.h"
+ #include <soc/bcm2835/raspberrypi-firmware.h>
+
++struct get_display_cfg {
++ u32 max_pixel_clock[2]; //Max pixel clock for each display
++};
++
++struct vc4_fkms {
++ struct get_display_cfg cfg;
++};
++
+ #define PLANES_PER_CRTC 3
+
+ struct set_plane {
+@@ -795,6 +803,11 @@ static void vc4_crtc_enable(struct drm_c
+ static enum drm_mode_status
+ vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
+ {
++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++ struct vc4_dev *vc4 = to_vc4_dev(dev);
++ struct vc4_fkms *fkms = vc4->fkms;
++
+ /* Do not allow doublescan modes from user space */
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
+ DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
+@@ -802,6 +815,22 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
+ return MODE_NO_DBLESCAN;
+ }
+
++ /* Limit the pixel clock based on the HDMI clock limits from the
++ * firmware
++ */
++ switch (vc4_crtc->display_number) {
++ case 2: /* HDMI0 */
++ if (fkms->cfg.max_pixel_clock[0] &&
++ mode->clock > fkms->cfg.max_pixel_clock[0])
++ return MODE_CLOCK_HIGH;
++ break;
++ case 7: /* HDMI1 */
++ if (fkms->cfg.max_pixel_clock[1] &&
++ mode->clock > fkms->cfg.max_pixel_clock[1])
++ return MODE_CLOCK_HIGH;
++ break;
++ }
++
+ /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
+ * working.
+ */
+@@ -1295,11 +1324,16 @@ static int vc4_fkms_bind(struct device *
+ struct device_node *firmware_node;
+ struct vc4_crtc **crtc_list;
+ u32 num_displays, display_num;
++ struct vc4_fkms *fkms;
+ int ret;
+ u32 display_id;
+
+ vc4->firmware_kms = true;
+
++ fkms = devm_kzalloc(dev, sizeof(*fkms), GFP_KERNEL);
++ if (!fkms)
++ return -ENOMEM;
++
+ /* firmware kms doesn't have precise a scanoutpos implementation, so
+ * we can't do the precise vblank timestamp mode.
+ */
+@@ -1328,6 +1362,18 @@ static int vc4_fkms_bind(struct device *
+ ret = 0;
+ }
+
++ ret = rpi_firmware_property(vc4->firmware,
++ RPI_FIRMWARE_GET_DISPLAY_CFG,
++ &fkms->cfg, sizeof(fkms->cfg));
++
++ if (ret)
++ return -EINVAL;
++ /* The firmware works in Hz. This will be compared against kHz, so div
++ * 1000 now rather than multiple times later.
++ */
++ fkms->cfg.max_pixel_clock[0] /= 1000;
++ fkms->cfg.max_pixel_clock[1] /= 1000;
++
+ /* Allocate a list, with space for a NULL on the end */
+ crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
+ GFP_KERNEL);
+@@ -1369,6 +1415,8 @@ static int vc4_fkms_bind(struct device *
+ DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
+ }
+
++ vc4->fkms = fkms;
++
+ platform_set_drvdata(pdev, crtc_list);
+
+ return 0;
+--- a/include/soc/bcm2835/raspberrypi-firmware.h
++++ b/include/soc/bcm2835/raspberrypi-firmware.h
+@@ -152,6 +152,7 @@ enum rpi_firmware_property_tag {
+ RPI_FIRMWARE_SET_PLANE = 0x00048015,
+ RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017,
+ RPI_FIRMWARE_SET_TIMING = 0x00048017,
++ RPI_FIRMWARE_GET_DISPLAY_CFG = 0x00040018,
+
+ RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
+ RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,