| From aa791f2cb6777e8ca99102009b631afdeea1c59d Mon Sep 17 00:00:00 2001 |
| From: Dave Stevenson <dave.stevenson@raspberrypi.com> |
| Date: Fri, 3 Jul 2020 16:06:55 +0100 |
| Subject: [PATCH] drm/vc4: FKMS Block modes with odd horizontal |
| timing values on Pi4 |
| |
| Pi4 HDMI pipeline is 2 pixels/clock and can not produce timings |
| that have odd values for active pixels, front porch, sync width, |
| or back porch. |
| Detect these modes and block them within fkms. |
| |
| Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> |
| --- |
| drivers/gpu/drm/vc4/vc4_firmware_kms.c | 21 +++++++++++++++++++++ |
| 1 file changed, 21 insertions(+) |
| |
| --- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c |
| +++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c |
| @@ -44,6 +44,7 @@ struct get_display_cfg { |
| |
| struct vc4_fkms { |
| struct get_display_cfg cfg; |
| + bool bcm2711; |
| }; |
| |
| #define PLANES_PER_CRTC 3 |
| @@ -1097,6 +1098,17 @@ vc4_crtc_mode_valid(struct drm_crtc *crt |
| break; |
| } |
| |
| + /* Pi4 can't generate odd horizontal timings on HDMI, so reject modes |
| + * that would set them. |
| + */ |
| + if (fkms->bcm2711 && |
| + (vc4_crtc->display_number == 2 || vc4_crtc->display_number == 7) && |
| + ((mode->hdisplay | /* active */ |
| + (mode->hsync_start - mode->hdisplay) | /* front porch */ |
| + (mode->hsync_end - mode->hsync_start) | /* sync pulse */ |
| + (mode->htotal - mode->hsync_end)) & 1)) /* back porch */ |
| + return MODE_H_ILLEGAL; |
| + |
| return MODE_OK; |
| } |
| |
| @@ -1282,6 +1294,8 @@ static const struct drm_crtc_helper_func |
| |
| static const struct of_device_id vc4_firmware_kms_dt_match[] = { |
| { .compatible = "raspberrypi,rpi-firmware-kms" }, |
| + { .compatible = "raspberrypi,rpi-firmware-kms-2711", |
| + .data = (void *)1 }, |
| {} |
| }; |
| |
| @@ -1815,6 +1829,7 @@ static int vc4_fkms_bind(struct device * |
| struct drm_device *drm = dev_get_drvdata(master); |
| struct vc4_dev *vc4 = to_vc4_dev(drm); |
| struct device_node *firmware_node; |
| + const struct of_device_id *match; |
| struct vc4_crtc **crtc_list; |
| u32 num_displays, display_num; |
| struct vc4_fkms *fkms; |
| @@ -1827,6 +1842,12 @@ static int vc4_fkms_bind(struct device * |
| if (!fkms) |
| return -ENOMEM; |
| |
| + match = of_match_device(vc4_firmware_kms_dt_match, dev); |
| + if (!match) |
| + return -ENODEV; |
| + if (match->data) |
| + fkms->bcm2711 = true; |
| + |
| /* firmware kms doesn't have precise a scanoutpos implementation, so |
| * we can't do the precise vblank timestamp mode. |
| */ |