mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-25 08:21:14 +00:00
135 lines
4.2 KiB
Diff
135 lines
4.2 KiB
Diff
|
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,
|