bcm27xx: update patches from RPi foundation
[oweals/openwrt.git] / target / linux / bcm27xx / patches-5.4 / 950-0563-drm-vc4-crtc-Assign-output-to-channel-automatically.patch
1 From 9efecb2ccd14a6d226ba2afa04f6e70b96026b3e Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Thu, 26 Dec 2019 17:53:18 +0100
4 Subject: [PATCH] drm/vc4: crtc: Assign output to channel automatically
5
6 The HVS found in the BCM2711 has 6 outputs and 3 FIFOs, with each output
7 being connected to a pixelvalve, and some muxing between the FIFOs and
8 outputs.
9
10 Any output cannot feed from any FIFO though, and they all have a bunch of
11 constraints.
12
13 In order to support this, let's store the possible FIFOs each output can be
14 assigned to in the vc4_crtc_data, and use that information at atomic_check
15 time to iterate over all the CRTCs enabled and assign them FIFOs.
16
17 The channel assigned is then set in the vc4_crtc_state so that the rest of
18 the driver can use it.
19
20 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
21 ---
22  drivers/gpu/drm/vc4/vc4_crtc.c |  37 +++++----
23  drivers/gpu/drm/vc4/vc4_drv.h  |   7 +-
24  drivers/gpu/drm/vc4/vc4_kms.c  | 146 +++++++++++++++++++++++++++++++--
25  drivers/gpu/drm/vc4/vc4_regs.h |  10 +++
26  4 files changed, 175 insertions(+), 25 deletions(-)
27
28 --- a/drivers/gpu/drm/vc4/vc4_crtc.c
29 +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
30 @@ -90,6 +90,7 @@ bool vc4_crtc_get_scanoutpos(struct drm_
31         struct vc4_dev *vc4 = to_vc4_dev(dev);
32         struct drm_crtc *crtc = drm_crtc_from_index(dev, crtc_id);
33         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
34 +       struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
35         unsigned int cob_size;
36         u32 val;
37         int fifo_lines;
38 @@ -106,7 +107,7 @@ bool vc4_crtc_get_scanoutpos(struct drm_
39          * Read vertical scanline which is currently composed for our
40          * pixelvalve by the HVS, and also the scaler status.
41          */
42 -       val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel));
43 +       val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel));
44  
45         /* Get optional system timestamp after query. */
46         if (etime)
47 @@ -126,7 +127,7 @@ bool vc4_crtc_get_scanoutpos(struct drm_
48                         *hpos += mode->crtc_htotal / 2;
49         }
50  
51 -       cob_size = vc4_crtc_get_cob_allocation(vc4_crtc, vc4_crtc->channel);
52 +       cob_size = vc4_crtc_get_cob_allocation(vc4_crtc, vc4_crtc_state->assigned_channel);
53         /* This is the offset we need for translating hvs -> pv scanout pos. */
54         fifo_lines = cob_size / mode->crtc_hdisplay;
55  
56 @@ -213,6 +214,7 @@ vc4_crtc_lut_load(struct drm_crtc *crtc)
57         struct drm_device *dev = crtc->dev;
58         struct vc4_dev *vc4 = to_vc4_dev(dev);
59         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
60 +       struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
61         u32 i;
62  
63         /* The LUT memory is laid out with each HVS channel in order,
64 @@ -221,7 +223,7 @@ vc4_crtc_lut_load(struct drm_crtc *crtc)
65          */
66         HVS_WRITE(SCALER_GAMADDR,
67                   SCALER_GAMADDR_AUTOINC |
68 -                 (vc4_crtc->channel * 3 * crtc->gamma_size));
69 +                 (vc4_crtc_state->assigned_channel * 3 * crtc->gamma_size));
70  
71         for (i = 0; i < crtc->gamma_size; i++)
72                 HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
73 @@ -394,7 +396,7 @@ static void vc4_crtc_mode_set_nofb(struc
74                 drm_print_regset32(&p, &vc4_crtc->regset);
75         }
76  
77 -       if (vc4_crtc->channel == 2) {
78 +       if (vc4_crtc->data->hvs_output == 2) {
79                 u32 dispctrl;
80                 u32 dsp3_mux;
81  
82 @@ -421,7 +423,7 @@ static void vc4_crtc_mode_set_nofb(struc
83         if (!vc4_state->feed_txp)
84                 vc4_crtc_config_pv(crtc);
85  
86 -       HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
87 +       HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
88                   SCALER_DISPBKGND_AUTOHS |
89                   SCALER_DISPBKGND_GAMMA |
90                   (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
91 @@ -453,7 +455,8 @@ static void vc4_crtc_atomic_disable(stru
92         struct drm_device *dev = crtc->dev;
93         struct vc4_dev *vc4 = to_vc4_dev(dev);
94         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
95 -       u32 chan = vc4_crtc->channel;
96 +       struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(old_state);
97 +       u32 chan = vc4_crtc_state->assigned_channel;
98         int ret;
99         require_hvs_enabled(dev);
100  
101 @@ -532,12 +535,12 @@ static void vc4_crtc_update_dlist(struct
102                         crtc->state->event = NULL;
103                 }
104  
105 -               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
106 +               HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
107                           vc4_state->mm.start);
108  
109                 spin_unlock_irqrestore(&dev->event_lock, flags);
110         } else {
111 -               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
112 +               HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
113                           vc4_state->mm.start);
114         }
115  }
116 @@ -586,7 +589,7 @@ static void vc4_crtc_atomic_enable(struc
117                             (vc4_state->feed_txp ?
118                                         SCALER5_DISPCTRLX_ONESHOT : 0);
119  
120 -       HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
121 +       HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
122  
123         /* When feeding the transposer block the pixelvalve is unneeded and
124          * should not be enabled.
125 @@ -702,7 +705,6 @@ static void vc4_crtc_atomic_flush(struct
126  {
127         struct drm_device *dev = crtc->dev;
128         struct vc4_dev *vc4 = to_vc4_dev(dev);
129 -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
130         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
131         struct drm_plane *plane;
132         struct vc4_plane_state *vc4_plane_state;
133 @@ -744,8 +746,8 @@ static void vc4_crtc_atomic_flush(struct
134                 /* This sets a black background color fill, as is the case
135                  * with other DRM drivers.
136                  */
137 -               HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
138 -                         HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) |
139 +               HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
140 +                         HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) |
141                           SCALER_DISPBKGND_FILL);
142  
143         /* Only update DISPLIST if the CRTC was already running and is not
144 @@ -759,7 +761,7 @@ static void vc4_crtc_atomic_flush(struct
145                 vc4_crtc_update_dlist(crtc);
146  
147         if (crtc->state->color_mgmt_changed) {
148 -               u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel));
149 +               u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel));
150  
151                 if (crtc->state->gamma_lut) {
152                         vc4_crtc_update_gamma_lut(crtc);
153 @@ -771,7 +773,7 @@ static void vc4_crtc_atomic_flush(struct
154                          */
155                         dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
156                 }
157 -               HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), dispbkgndx);
158 +               HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx);
159         }
160  
161         if (debug_dump_regs) {
162 @@ -802,7 +804,7 @@ static void vc4_crtc_handle_page_flip(st
163         struct drm_device *dev = crtc->dev;
164         struct vc4_dev *vc4 = to_vc4_dev(dev);
165         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
166 -       u32 chan = vc4_crtc->channel;
167 +       u32 chan = vc4_state->assigned_channel;
168         unsigned long flags;
169  
170         spin_lock_irqsave(&dev->event_lock, flags);
171 @@ -1002,6 +1004,7 @@ static struct drm_crtc_state *vc4_crtc_d
172         old_vc4_state = to_vc4_crtc_state(crtc->state);
173         vc4_state->feed_txp = old_vc4_state->feed_txp;
174         vc4_state->margins = old_vc4_state->margins;
175 +       vc4_state->assigned_channel = old_vc4_state->assigned_channel;
176  
177         __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
178         return &vc4_state->base;
179 @@ -1061,6 +1064,7 @@ static const struct drm_crtc_helper_func
180  };
181  
182  static const struct vc4_crtc_data bcm2835_pv0_data = {
183 +       .hvs_available_channels = BIT(0),
184         .hvs_output = 0,
185         .debugfs_name = "crtc0_regs",
186         .pixels_per_clock = 1,
187 @@ -1071,6 +1075,7 @@ static const struct vc4_crtc_data bcm283
188  };
189  
190  static const struct vc4_crtc_data bcm2835_pv1_data = {
191 +       .hvs_available_channels = BIT(2),
192         .hvs_output = 2,
193         .debugfs_name = "crtc1_regs",
194         .pixels_per_clock = 1,
195 @@ -1081,6 +1086,7 @@ static const struct vc4_crtc_data bcm283
196  };
197  
198  static const struct vc4_crtc_data bcm2835_pv2_data = {
199 +       .hvs_available_channels = BIT(1),
200         .hvs_output = 1,
201         .debugfs_name = "crtc2_regs",
202         .pixels_per_clock = 1,
203 @@ -1172,7 +1178,6 @@ static int vc4_crtc_bind(struct device *
204         drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
205                                   &vc4_crtc_funcs, NULL);
206         drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs);
207 -       vc4_crtc->channel = vc4_crtc->data->hvs_output;
208         drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
209         drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
210  
211 --- a/drivers/gpu/drm/vc4/vc4_drv.h
212 +++ b/drivers/gpu/drm/vc4/vc4_drv.h
213 @@ -452,6 +452,9 @@ to_vc4_encoder(struct drm_encoder *encod
214  }
215  
216  struct vc4_crtc_data {
217 +       /* Which channels of the HVS can the output source from */
218 +       unsigned int hvs_available_channels;
219 +
220         /* Which output of the HVS this pixelvalve sources from. */
221         int hvs_output;
222  
223 @@ -471,9 +474,6 @@ struct vc4_crtc {
224         /* Timestamp at start of vblank irq - unaffected by lock delays. */
225         ktime_t t_vblank;
226  
227 -       /* Which HVS channel we're using for our CRTC. */
228 -       int channel;
229 -
230         u8 lut_r[256];
231         u8 lut_g[256];
232         u8 lut_b[256];
233 @@ -495,6 +495,7 @@ struct vc4_crtc_state {
234         struct drm_mm_node mm;
235         bool feed_txp;
236         bool txp_armed;
237 +       unsigned int assigned_channel;
238  
239         struct {
240                 unsigned int left;
241 --- a/drivers/gpu/drm/vc4/vc4_kms.c
242 +++ b/drivers/gpu/drm/vc4/vc4_kms.c
243 @@ -11,6 +11,9 @@
244   * crtc, HDMI encoder).
245   */
246  
247 +#include <linux/bitfield.h>
248 +#include <linux/bitops.h>
249 +
250  #include <drm/drm_atomic.h>
251  #include <drm/drm_atomic_helper.h>
252  #include <drm/drm_crtc.h>
253 @@ -148,6 +151,72 @@ vc4_ctm_commit(struct vc4_dev *vc4, stru
254                   VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
255  }
256  
257 +static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4,
258 +                                    struct drm_atomic_state *state)
259 +{
260 +       struct drm_crtc_state *crtc_state;
261 +       struct drm_crtc *crtc;
262 +       unsigned char dsp2_mux = 0;
263 +       unsigned char dsp3_mux = 3;
264 +       unsigned char dsp4_mux = 3;
265 +       unsigned char dsp5_mux = 3;
266 +       unsigned int i;
267 +       u32 reg;
268 +
269 +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
270 +               struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
271 +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
272 +
273 +               if (!crtc_state->active)
274 +                       continue;
275 +
276 +               switch (vc4_crtc->data->hvs_output) {
277 +               case 2:
278 +                       dsp2_mux = (vc4_state->assigned_channel == 2) ? 1 : 0;
279 +                       break;
280 +
281 +               case 3:
282 +                       dsp3_mux = vc4_state->assigned_channel;
283 +                       break;
284 +
285 +               case 4:
286 +                       dsp4_mux = vc4_state->assigned_channel;
287 +                       break;
288 +
289 +               case 5:
290 +                       dsp5_mux = vc4_state->assigned_channel;
291 +                       break;
292 +
293 +               default:
294 +                       break;
295 +               }
296 +       }
297 +
298 +       reg = HVS_READ(SCALER_DISPECTRL);
299 +       if (FIELD_GET(SCALER_DISPECTRL_DSP2_MUX_MASK, reg) != dsp2_mux)
300 +               HVS_WRITE(SCALER_DISPECTRL,
301 +                         (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
302 +                         VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
303 +
304 +       reg = HVS_READ(SCALER_DISPCTRL);
305 +       if (FIELD_GET(SCALER_DISPCTRL_DSP3_MUX_MASK, reg) != dsp3_mux)
306 +               HVS_WRITE(SCALER_DISPCTRL,
307 +                         (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
308 +                         VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
309 +
310 +       reg = HVS_READ(SCALER_DISPEOLN);
311 +       if (FIELD_GET(SCALER_DISPEOLN_DSP4_MUX_MASK, reg) != dsp4_mux)
312 +               HVS_WRITE(SCALER_DISPEOLN,
313 +                         (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
314 +                         VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
315 +
316 +       reg = HVS_READ(SCALER_DISPDITHER);
317 +       if (FIELD_GET(SCALER_DISPDITHER_DSP5_MUX_MASK, reg) != dsp5_mux)
318 +               HVS_WRITE(SCALER_DISPDITHER,
319 +                         (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
320 +                         VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
321 +}
322 +
323  static void
324  vc4_atomic_complete_commit(struct drm_atomic_state *state)
325  {
326 @@ -157,11 +226,15 @@ vc4_atomic_complete_commit(struct drm_at
327         int i;
328  
329         for (i = 0; vc4->hvs && i < dev->mode_config.num_crtc; i++) {
330 -               if (!state->crtcs[i].ptr || !state->crtcs[i].commit)
331 +               struct __drm_crtcs_state *_state = &state->crtcs[i];
332 +               struct vc4_crtc_state *vc4_crtc_state;
333 +
334 +               if (!_state->ptr || !_state->commit)
335                         continue;
336  
337 -               vc4_crtc = to_vc4_crtc(state->crtcs[i].ptr);
338 -               vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
339 +               vc4_crtc = to_vc4_crtc(_state->ptr);
340 +               vc4_crtc_state = to_vc4_crtc_state(_state->state);
341 +               vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel);
342         }
343  
344         drm_atomic_helper_wait_for_fences(dev, state, false);
345 @@ -170,8 +243,10 @@ vc4_atomic_complete_commit(struct drm_at
346  
347         drm_atomic_helper_commit_modeset_disables(dev, state);
348  
349 -       if (!vc4->firmware_kms)
350 +       if (!vc4->firmware_kms) {
351                 vc4_ctm_commit(vc4, state);
352 +               vc4_hvs_pv_muxing_commit(vc4, state);
353 +       }
354  
355         drm_atomic_helper_commit_planes(dev, state, 0);
356  
357 @@ -380,8 +455,11 @@ vc4_ctm_atomic_check(struct drm_device *
358  
359                 /* CTM is being enabled or the matrix changed. */
360                 if (new_crtc_state->ctm) {
361 +                       struct vc4_crtc_state *vc4_crtc_state =
362 +                               to_vc4_crtc_state(new_crtc_state);
363 +
364                         /* fifo is 1-based since 0 disables CTM. */
365 -                       int fifo = to_vc4_crtc(crtc)->channel + 1;
366 +                       int fifo = vc4_crtc_state->assigned_channel + 1;
367  
368                         /* Check userland isn't trying to turn on CTM for more
369                          * than one CRTC at a time.
370 @@ -494,10 +572,66 @@ static const struct drm_private_state_fu
371         .atomic_destroy_state = vc4_load_tracker_destroy_state,
372  };
373  
374 +#define NUM_OUTPUTS  6
375 +#define NUM_CHANNELS 3
376 +
377  static int
378  vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
379  {
380 -       int ret;
381 +       unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
382 +       struct drm_crtc_state *crtc_state;
383 +       struct drm_crtc *crtc;
384 +       int i, ret;
385 +
386 +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
387 +               struct vc4_crtc_state *vc4_crtc_state =
388 +                       to_vc4_crtc_state(crtc_state);
389 +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
390 +               bool is_assigned = false;
391 +               unsigned int channel;
392 +
393 +               if (!crtc_state->active)
394 +                       continue;
395 +
396 +               /*
397 +                * The problem we have to solve here is that we have
398 +                * up to 7 encoders, connected to up to 6 CRTCs.
399 +                *
400 +                * Those CRTCs, depending on the instance, can be
401 +                * routed to 1, 2 or 3 HVS FIFOs, and we need to set
402 +                * the change the muxing between FIFOs and outputs in
403 +                * the HVS accordingly.
404 +                *
405 +                * It would be pretty hard to come up with an
406 +                * algorithm that would generically solve
407 +                * this. However, the current routing trees we support
408 +                * allow us to simplify a bit the problem.
409 +                *
410 +                * Indeed, with the current supported layouts, if we
411 +                * try to assign in the ascending crtc index order the
412 +                * FIFOs, we can't fall into the situation where an
413 +                * earlier CRTC that had multiple routes is assigned
414 +                * one that was the only option for a later CRTC.
415 +                *
416 +                * If the layout changes and doesn't give us that in
417 +                * the future, we will need to have something smarter,
418 +                * but it works so far.
419 +                */
420 +               for_each_set_bit(channel, &unassigned_channels,
421 +                                sizeof(unassigned_channels)) {
422 +
423 +                       if (!(BIT(channel) & vc4_crtc->data->hvs_available_channels))
424 +                               continue;
425 +
426 +                       vc4_crtc_state->assigned_channel = channel;
427 +                       unassigned_channels &= ~BIT(channel);
428 +                       is_assigned = true;
429 +                       break;
430 +               }
431 +
432 +               if (!is_assigned)
433 +                       return -EINVAL;
434 +       }
435  
436         ret = vc4_ctm_atomic_check(dev, state);
437         if (ret < 0)
438 --- a/drivers/gpu/drm/vc4/vc4_regs.h
439 +++ b/drivers/gpu/drm/vc4/vc4_regs.h
440 @@ -287,9 +287,19 @@
441  
442  #define SCALER_DISPID                           0x00000008
443  #define SCALER_DISPECTRL                        0x0000000c
444 +# define SCALER_DISPECTRL_DSP2_MUX_SHIFT       31
445 +# define SCALER_DISPECTRL_DSP2_MUX_MASK                VC4_MASK(31, 31)
446 +
447  #define SCALER_DISPPROF                         0x00000010
448 +
449  #define SCALER_DISPDITHER                       0x00000014
450 +# define SCALER_DISPDITHER_DSP5_MUX_SHIFT      30
451 +# define SCALER_DISPDITHER_DSP5_MUX_MASK       VC4_MASK(31, 30)
452 +
453  #define SCALER_DISPEOLN                         0x00000018
454 +# define SCALER_DISPEOLN_DSP4_MUX_SHIFT                30
455 +# define SCALER_DISPEOLN_DSP4_MUX_MASK         VC4_MASK(31, 30)
456 +
457  #define SCALER_DISPLIST0                        0x00000020
458  #define SCALER_DISPLIST1                        0x00000024
459  #define SCALER_DISPLIST2                        0x00000028