kernel: bump 5.4 to 5.4.48
[oweals/openwrt.git] / target / linux / bcm27xx / patches-5.4 / 950-0251-drm-vc4-Probe-DPI-DSI-timings-from-the-firmware.patch
1 From e8f126acd6da4f7d2e0df3c735fccf9971d95254 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Tue, 21 May 2019 11:50:00 +0100
4 Subject: [PATCH] drm: vc4: Probe DPI/DSI timings from the firmware
5
6 For DPI and DSI displays query the firmware as to the configuration
7 and add it as the only mode for DRM.
8
9 In theory we can add plumbing for setting the DPI/DSI mode from
10 KMS, but this is not being added at present as the support frameworks
11 aren't present in the firmware.
12
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
14 ---
15  drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 64 ++++++++++++++++------
16  include/soc/bcm2835/raspberrypi-firmware.h |  1 +
17  2 files changed, 49 insertions(+), 16 deletions(-)
18
19 --- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
20 +++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
21 @@ -248,7 +248,6 @@ static inline struct vc4_crtc *to_vc4_cr
22  struct vc4_fkms_encoder {
23         struct drm_encoder base;
24         bool hdmi_monitor;
25 -       bool rgb_range_selectable;
26  };
27  
28  static inline struct vc4_fkms_encoder *
29 @@ -283,7 +282,7 @@ static u32 vc4_get_display_type(u32 disp
30                 /* The firmware display (DispmanX) IDs map to specific types in
31                  * a fixed manner.
32                  */
33 -               DRM_MODE_ENCODER_DSI,   /* MAIN_LCD */
34 +               DRM_MODE_ENCODER_DSI,   /* MAIN_LCD - DSI or DPI */
35                 DRM_MODE_ENCODER_DSI,   /* AUX_LCD */
36                 DRM_MODE_ENCODER_TMDS,  /* HDMI0 */
37                 DRM_MODE_ENCODER_TVDAC, /* VEC */
38 @@ -365,7 +364,6 @@ static void vc4_plane_atomic_update(stru
39                                         vc4_get_vc_image_fmt(drm_fmt->format);
40         struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
41         struct mailbox_set_plane *mb = &vc4_plane->mb;
42 -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
43         int num_planes = fb->format->num_planes;
44         struct drm_display_mode *mode = &state->crtc->mode;
45         unsigned int rotation = SUPPORTED_ROTATIONS;
46 @@ -987,11 +985,6 @@ static int vc4_fkms_connector_get_modes(
47  
48         vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
49  
50 -       if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
51 -               vc4_encoder->rgb_range_selectable =
52 -                       drm_rgb_quant_range_selectable(edid);
53 -       }
54 -
55         drm_connector_update_edid_property(connector, edid);
56         ret = drm_add_edid_modes(connector, edid);
57         kfree(edid);
58 @@ -999,7 +992,9 @@ static int vc4_fkms_connector_get_modes(
59         return ret;
60  }
61  
62 -/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
63 +/* This is the DSI panel resolution. Use this as a default should the firmware
64 + * not respond to our request for the timings.
65 + */
66  static const struct drm_display_mode lcd_mode = {
67         DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
68                  25979400 / 1000,
69 @@ -1010,15 +1005,52 @@ static const struct drm_display_mode lcd
70  
71  static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
72  {
73 -       //struct vc4_fkms_connector *fkms_connector =
74 -       //                              to_vc4_fkms_connector(connector);
75 -       //struct drm_encoder *encoder = fkms_connector->encoder;
76 -       //struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
77 +       struct vc4_fkms_connector *fkms_connector =
78 +                                       to_vc4_fkms_connector(connector);
79 +       struct vc4_dev *vc4 = fkms_connector->vc4_dev;
80         struct drm_display_mode *mode;
81 -       //int ret = 0;
82 +       struct mailbox_set_mode mb = {
83 +               .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
84 +                         sizeof(struct set_timings), 0},
85 +               .timings = { .display = fkms_connector->display_number },
86 +       };
87 +       struct drm_display_mode fw_mode;
88 +       int ret = 0;
89 +
90 +       ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
91 +       if (!ret) {
92 +               /* Equivalent to DRM_MODE macro. */
93 +               memset(&fw_mode, 0, sizeof(fw_mode));
94 +               strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
95 +               fw_mode.status = 0;
96 +               fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
97 +               fw_mode.clock = mb.timings.clock;
98 +               fw_mode.hdisplay = mb.timings.hdisplay;
99 +               fw_mode.hsync_start = mb.timings.hsync_start;
100 +               fw_mode.hsync_end = mb.timings.hsync_end;
101 +               fw_mode.htotal = mb.timings.htotal;
102 +               fw_mode.hskew = 0;
103 +               fw_mode.vdisplay = mb.timings.vdisplay;
104 +               fw_mode.vsync_start = mb.timings.vsync_start;
105 +               fw_mode.vsync_end = mb.timings.vsync_end;
106 +               fw_mode.vtotal = mb.timings.vtotal;
107 +               fw_mode.vscan = mb.timings.vscan;
108 +               if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
109 +                       fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
110 +               else
111 +                       fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
112 +               if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
113 +                       fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
114 +               else
115 +                       fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
116 +
117 +               mode = drm_mode_duplicate(connector->dev,
118 +                                         &fw_mode);
119 +       } else {
120 +               mode = drm_mode_duplicate(connector->dev,
121 +                                         &lcd_mode);
122 +       }
123  
124 -       mode = drm_mode_duplicate(connector->dev,
125 -                                 &lcd_mode);
126         if (!mode) {
127                 DRM_ERROR("Failed to create a new display mode\n");
128                 return -ENOMEM;
129 --- a/include/soc/bcm2835/raspberrypi-firmware.h
130 +++ b/include/soc/bcm2835/raspberrypi-firmware.h
131 @@ -150,6 +150,7 @@ enum rpi_firmware_property_tag {
132         RPI_FIRMWARE_VCHIQ_INIT =                             0x00048010,
133  
134         RPI_FIRMWARE_SET_PLANE =                              0x00048015,
135 +       RPI_FIRMWARE_GET_DISPLAY_TIMING =                     0x00040017,
136         RPI_FIRMWARE_SET_TIMING =                             0x00048017,
137  
138         RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,