7f917bdd45048addde0a92ec29364dffef9cc2fd
[oweals/openwrt.git] /
1 From 23e6a2c2d33050255c76a499ea080e5279d6edfc Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Thu, 30 May 2019 13:56:15 +0100
4 Subject: [PATCH] drm/vc4: fkms to query the VPU for HDMI clock limits
5
6 The VPU has configured clocks for 4k (or not) via config.txt,
7 and will limit the choice of video modes based on that.
8 Make fkms query it for these limits too to avoid selecting modes
9 that can not be handled by the current clock setup.
10
11 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
12 ---
13  drivers/gpu/drm/vc4/vc4_drv.h              |  1 +
14  drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 48 ++++++++++++++++++++++
15  include/soc/bcm2835/raspberrypi-firmware.h |  1 +
16  3 files changed, 50 insertions(+)
17
18 --- a/drivers/gpu/drm/vc4/vc4_drv.h
19 +++ b/drivers/gpu/drm/vc4/vc4_drv.h
20 @@ -77,6 +77,7 @@ struct vc4_dev {
21         struct vc4_dsi *dsi1;
22         struct vc4_vec *vec;
23         struct vc4_txp *txp;
24 +       struct vc4_fkms *fkms;
25  
26         struct vc4_hang_state *hang_state;
27  
28 --- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
29 +++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
30 @@ -29,6 +29,14 @@
31  #include "vc_image_types.h"
32  #include <soc/bcm2835/raspberrypi-firmware.h>
33  
34 +struct get_display_cfg {
35 +       u32  max_pixel_clock[2];  //Max pixel clock for each display
36 +};
37 +
38 +struct vc4_fkms {
39 +       struct get_display_cfg cfg;
40 +};
41 +
42  #define PLANES_PER_CRTC                3
43  
44  struct set_plane {
45 @@ -794,6 +802,11 @@ static void vc4_crtc_enable(struct drm_c
46  static enum drm_mode_status
47  vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
48  {
49 +       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
50 +       struct drm_device *dev = crtc->dev;
51 +       struct vc4_dev *vc4 = to_vc4_dev(dev);
52 +       struct vc4_fkms *fkms = vc4->fkms;
53 +
54         /* Do not allow doublescan modes from user space */
55         if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
56                 DRM_DEBUG_KMS("[CRTC:%d] Doublescan mode rejected.\n",
57 @@ -801,6 +814,22 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
58                 return MODE_NO_DBLESCAN;
59         }
60  
61 +       /* Limit the pixel clock based on the HDMI clock limits from the
62 +        * firmware
63 +        */
64 +       switch (vc4_crtc->display_number) {
65 +       case 2: /* HDMI0 */
66 +               if (fkms->cfg.max_pixel_clock[0] &&
67 +                   mode->clock > fkms->cfg.max_pixel_clock[0])
68 +                       return MODE_CLOCK_HIGH;
69 +               break;
70 +       case 7: /* HDMI1 */
71 +               if (fkms->cfg.max_pixel_clock[1] &&
72 +                   mode->clock > fkms->cfg.max_pixel_clock[1])
73 +                       return MODE_CLOCK_HIGH;
74 +               break;
75 +       }
76 +
77         /* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
78          * working.
79          */
80 @@ -1301,11 +1330,16 @@ static int vc4_fkms_bind(struct device *
81         struct device_node *firmware_node;
82         struct vc4_crtc **crtc_list;
83         u32 num_displays, display_num;
84 +       struct vc4_fkms *fkms;
85         int ret;
86         u32 display_id;
87  
88         vc4->firmware_kms = true;
89  
90 +       fkms = devm_kzalloc(dev, sizeof(*fkms), GFP_KERNEL);
91 +       if (!fkms)
92 +               return -ENOMEM;
93 +
94         /* firmware kms doesn't have precise a scanoutpos implementation, so
95          * we can't do the precise vblank timestamp mode.
96          */
97 @@ -1334,6 +1368,18 @@ static int vc4_fkms_bind(struct device *
98                 ret = 0;
99         }
100  
101 +       ret = rpi_firmware_property(vc4->firmware,
102 +                                   RPI_FIRMWARE_GET_DISPLAY_CFG,
103 +                                   &fkms->cfg, sizeof(fkms->cfg));
104 +
105 +       if (ret)
106 +               return -EINVAL;
107 +       /* The firmware works in Hz. This will be compared against kHz, so div
108 +        * 1000 now rather than multiple times later.
109 +        */
110 +       fkms->cfg.max_pixel_clock[0] /= 1000;
111 +       fkms->cfg.max_pixel_clock[1] /= 1000;
112 +
113         /* Allocate a list, with space for a NULL on the end */
114         crtc_list = devm_kzalloc(dev, sizeof(crtc_list) * (num_displays + 1),
115                                  GFP_KERNEL);
116 @@ -1375,6 +1421,8 @@ static int vc4_fkms_bind(struct device *
117                 DRM_WARN("No displays found. Consider forcing hotplug if HDMI is attached\n");
118         }
119  
120 +       vc4->fkms = fkms;
121 +
122         platform_set_drvdata(pdev, crtc_list);
123  
124         return 0;
125 --- a/include/soc/bcm2835/raspberrypi-firmware.h
126 +++ b/include/soc/bcm2835/raspberrypi-firmware.h
127 @@ -153,6 +153,7 @@ enum rpi_firmware_property_tag {
128         RPI_FIRMWARE_SET_PLANE =                              0x00048015,
129         RPI_FIRMWARE_GET_DISPLAY_TIMING =                     0x00040017,
130         RPI_FIRMWARE_SET_TIMING =                             0x00048017,
131 +       RPI_FIRMWARE_GET_DISPLAY_CFG =                        0x00040018,
132  
133         RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
134         RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,