1 From 77ae227664bc2460a5341be765044d0b8fb184ac Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Tue, 4 Jun 2019 12:14:30 +0100
4 Subject: [PATCH] drm: vc4: Add status of which display is updated
7 Previously multiple displays were slaved off the same SMI
8 interrupt, triggered by HVS channel 1 (HDMI0).
9 This doesn't work if you only have a DPI or DSI screen (HVS channel
10 0), and gives slightly erroneous results with dual HDMI as the
11 events for HDMI1 are incorrect.
13 Use SMIDSW0 and SMIDSW1 registers to denote which display has
15 Handling should be backwards compatible with older firmware.
17 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
19 drivers/gpu/drm/vc4/vc4_firmware_kms.c | 41 ++++++++++++++++++++++----
20 1 file changed, 36 insertions(+), 5 deletions(-)
22 --- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
23 +++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
24 @@ -230,8 +230,13 @@ static const struct vc_image_format *vc4
25 * hardware, which has only this one register.
30 #define SMICS_INTERRUPTS (BIT(9) | BIT(10) | BIT(11))
32 +/* Flag to denote that the firmware is giving multiple display callbacks */
33 +#define SMI_NEW 0xabcd0000
35 #define vc4_crtc vc4_kms_crtc
36 #define to_vc4_crtc to_vc4_kms_crtc
38 @@ -884,16 +889,42 @@ static irqreturn_t vc4_crtc_irq_handler(
40 u32 stat = readl(crtc_list[0]->regs + SMICS);
41 irqreturn_t ret = IRQ_NONE;
44 if (stat & SMICS_INTERRUPTS) {
45 writel(0, crtc_list[0]->regs + SMICS);
47 - for (i = 0; crtc_list[i]; i++) {
48 - if (crtc_list[i]->vblank_enabled)
49 - drm_crtc_handle_vblank(&crtc_list[i]->base);
50 - vc4_crtc_handle_page_flip(crtc_list[i]);
52 + chan = readl(crtc_list[0]->regs + SMIDSW0);
54 + if ((chan & 0xFFFF0000) != SMI_NEW) {
55 + /* Older firmware. Treat the one interrupt as vblank/
56 + * complete for all crtcs.
58 + for (i = 0; crtc_list[i]; i++) {
59 + if (crtc_list[i]->vblank_enabled)
60 + drm_crtc_handle_vblank(&crtc_list[i]->base);
61 + vc4_crtc_handle_page_flip(crtc_list[i]);
65 + writel(SMI_NEW, crtc_list[0]->regs + SMIDSW0);
66 + if (crtc_list[0]->vblank_enabled)
67 + drm_crtc_handle_vblank(&crtc_list[0]->base);
68 + vc4_crtc_handle_page_flip(crtc_list[0]);
71 + /* Check for the secondary display too */
72 + chan = readl(crtc_list[0]->regs + SMIDSW1);
75 + writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
76 + if (crtc_list[1]->vblank_enabled)
77 + drm_crtc_handle_vblank(&crtc_list[1]->base);
78 + vc4_crtc_handle_page_flip(crtc_list[1]);