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>
struct vc4_dsi *dsi1;
struct vc4_vec *vec;
struct vc4_txp *txp;
struct vc4_dsi *dsi1;
struct vc4_vec *vec;
struct vc4_txp *txp;
struct vc4_hang_state *hang_state;
struct vc4_hang_state *hang_state;
#include "vc_image_types.h"
#include <soc/bcm2835/raspberrypi-firmware.h>
#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 {
#define PLANES_PER_CRTC 3
struct set_plane {
static enum drm_mode_status
vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
{
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",
/* Do not allow doublescan modes from user space */
if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
return MODE_NO_DBLESCAN;
}
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.
*/
/* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
* working.
*/
struct device_node *firmware_node;
struct vc4_crtc **crtc_list;
u32 num_displays, display_num;
struct device_node *firmware_node;
struct vc4_crtc **crtc_list;
u32 num_displays, display_num;
int ret;
u32 display_id;
vc4->firmware_kms = true;
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.
*/
/* firmware kms doesn't have precise a scanoutpos implementation, so
* we can't do the precise vblank timestamp mode.
*/
+ 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);
/* Allocate a list, with space for a NULL on the end */
crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
GFP_KERNEL);
DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
}
DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
}
platform_set_drvdata(pdev, crtc_list);
return 0;
platform_set_drvdata(pdev, crtc_list);
return 0;
RPI_FIRMWARE_SET_PLANE = 0x00048015,
RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017,
RPI_FIRMWARE_SET_TIMING = 0x00048017,
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,
RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,