forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/drivers/gpu/drm/sun4i/sun4i_backend.c
....@@ -1,29 +1,28 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2015 Free Electrons
34 * Copyright (C) 2015 NextThing Co
45 *
56 * Maxime Ripard <maxime.ripard@free-electrons.com>
6
- *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public License as
9
- * published by the Free Software Foundation; either version 2 of
10
- * the License, or (at your option) any later version.
117 */
12
-
13
-#include <drm/drmP.h>
14
-#include <drm/drm_atomic.h>
15
-#include <drm/drm_atomic_helper.h>
16
-#include <drm/drm_crtc.h>
17
-#include <drm/drm_crtc_helper.h>
18
-#include <drm/drm_fb_cma_helper.h>
19
-#include <drm/drm_gem_cma_helper.h>
20
-#include <drm/drm_plane_helper.h>
218
229 #include <linux/component.h>
2310 #include <linux/list.h>
11
+#include <linux/module.h>
2412 #include <linux/of_device.h>
2513 #include <linux/of_graph.h>
14
+#include <linux/dma-mapping.h>
15
+#include <linux/platform_device.h>
2616 #include <linux/reset.h>
17
+
18
+#include <drm/drm_atomic.h>
19
+#include <drm/drm_atomic_helper.h>
20
+#include <drm/drm_crtc.h>
21
+#include <drm/drm_fb_cma_helper.h>
22
+#include <drm/drm_fourcc.h>
23
+#include <drm/drm_gem_cma_helper.h>
24
+#include <drm/drm_plane_helper.h>
25
+#include <drm/drm_probe_helper.h>
2726
2827 #include "sun4i_backend.h"
2928 #include "sun4i_drv.h"
....@@ -34,6 +33,9 @@
3433 struct sun4i_backend_quirks {
3534 /* backend <-> TCON muxing selection done in backend */
3635 bool needs_output_muxing;
36
+
37
+ /* alpha at the lowest z position is not always supported */
38
+ bool supports_lowest_plane_alpha;
3739 };
3840
3941 static const u32 sunxi_rgb2yuv_coef[12] = {
....@@ -41,50 +43,6 @@
4143 0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808,
4244 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
4345 };
44
-
45
-/*
46
- * These coefficients are taken from the A33 BSP from Allwinner.
47
- *
48
- * The formula is for each component, each coefficient being multiplied by
49
- * 1024 and each constant being multiplied by 16:
50
- * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135
51
- * R = 1.164 * Y + 1.596 * V - 222
52
- * B = 1.164 * Y + 2.018 * U + 276
53
- *
54
- * This seems to be a conversion from Y[16:235] UV[16:240] to RGB[0:255],
55
- * following the BT601 spec.
56
- */
57
-static const u32 sunxi_bt601_yuv2rgb_coef[12] = {
58
- 0x000004a7, 0x00001e6f, 0x00001cbf, 0x00000877,
59
- 0x000004a7, 0x00000000, 0x00000662, 0x00003211,
60
- 0x000004a7, 0x00000812, 0x00000000, 0x00002eb1,
61
-};
62
-
63
-static inline bool sun4i_backend_format_is_planar_yuv(uint32_t format)
64
-{
65
- switch (format) {
66
- case DRM_FORMAT_YUV411:
67
- case DRM_FORMAT_YUV422:
68
- case DRM_FORMAT_YUV444:
69
- return true;
70
- default:
71
- return false;
72
- }
73
-}
74
-
75
-static inline bool sun4i_backend_format_is_packed_yuv422(uint32_t format)
76
-{
77
- switch (format) {
78
- case DRM_FORMAT_YUYV:
79
- case DRM_FORMAT_YVYU:
80
- case DRM_FORMAT_UYVY:
81
- case DRM_FORMAT_VYUY:
82
- return true;
83
-
84
- default:
85
- return false;
86
- }
87
-}
8846
8947 static void sun4i_backend_apply_color_correction(struct sunxi_engine *engine)
9048 {
....@@ -178,6 +136,35 @@
178136 return 0;
179137 }
180138
139
+static const uint32_t sun4i_backend_formats[] = {
140
+ DRM_FORMAT_ARGB1555,
141
+ DRM_FORMAT_ARGB4444,
142
+ DRM_FORMAT_ARGB8888,
143
+ DRM_FORMAT_RGB565,
144
+ DRM_FORMAT_RGB888,
145
+ DRM_FORMAT_RGBA4444,
146
+ DRM_FORMAT_RGBA5551,
147
+ DRM_FORMAT_UYVY,
148
+ DRM_FORMAT_VYUY,
149
+ DRM_FORMAT_XRGB8888,
150
+ DRM_FORMAT_YUYV,
151
+ DRM_FORMAT_YVYU,
152
+};
153
+
154
+bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier)
155
+{
156
+ unsigned int i;
157
+
158
+ if (modifier != DRM_FORMAT_MOD_LINEAR)
159
+ return false;
160
+
161
+ for (i = 0; i < ARRAY_SIZE(sun4i_backend_formats); i++)
162
+ if (sun4i_backend_formats[i] == fmt)
163
+ return true;
164
+
165
+ return false;
166
+}
167
+
181168 int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
182169 int layer, struct drm_plane *plane)
183170 {
....@@ -215,7 +202,8 @@
215202 {
216203 struct drm_plane_state *state = plane->state;
217204 struct drm_framebuffer *fb = state->fb;
218
- uint32_t format = fb->format->format;
205
+ const struct drm_format_info *format = fb->format;
206
+ const uint32_t fmt = format->format;
219207 u32 val = SUN4I_BACKEND_IYUVCTL_EN;
220208 int i;
221209
....@@ -233,16 +221,17 @@
233221 SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN);
234222
235223 /* TODO: Add support for the multi-planar YUV formats */
236
- if (sun4i_backend_format_is_packed_yuv422(format))
224
+ if (drm_format_info_is_yuv_packed(format) &&
225
+ drm_format_info_is_yuv_sampling_422(format))
237226 val |= SUN4I_BACKEND_IYUVCTL_FBFMT_PACKED_YUV422;
238227 else
239
- DRM_DEBUG_DRIVER("Unsupported YUV format (0x%x)\n", format);
228
+ DRM_DEBUG_DRIVER("Unsupported YUV format (0x%x)\n", fmt);
240229
241230 /*
242231 * Allwinner seems to list the pixel sequence from right to left, while
243232 * DRM lists it from left to right.
244233 */
245
- switch (format) {
234
+ switch (fmt) {
246235 case DRM_FORMAT_YUYV:
247236 val |= SUN4I_BACKEND_IYUVCTL_FBPS_VYUY;
248237 break;
....@@ -257,7 +246,7 @@
257246 break;
258247 default:
259248 DRM_DEBUG_DRIVER("Unsupported YUV pixel sequence (0x%x)\n",
260
- format);
249
+ fmt);
261250 }
262251
263252 regmap_write(backend->engine.regs, SUN4I_BACKEND_IYUVCTL_REG, val);
....@@ -371,13 +360,6 @@
371360 paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
372361 DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
373362
374
- /*
375
- * backend DMA accesses DRAM directly, bypassing the system
376
- * bus. As such, the address range is different and the buffer
377
- * address needs to be corrected.
378
- */
379
- paddr -= PHYS_OFFSET;
380
-
381363 if (fb->format->is_yuv)
382364 return sun4i_backend_update_yuv_buffer(backend, fb, paddr);
383365
....@@ -417,6 +399,15 @@
417399 return 0;
418400 }
419401
402
+void sun4i_backend_cleanup_layer(struct sun4i_backend *backend,
403
+ int layer)
404
+{
405
+ regmap_update_bits(backend->engine.regs,
406
+ SUN4I_BACKEND_ATTCTL_REG0(layer),
407
+ SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN |
408
+ SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN, 0);
409
+}
410
+
420411 static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state)
421412 {
422413 u16 src_h = state->src_h >> 16;
....@@ -435,11 +426,50 @@
435426 {
436427 struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane);
437428 struct sun4i_backend *backend = layer->backend;
429
+ uint32_t format = state->fb->format->format;
430
+ uint64_t modifier = state->fb->modifier;
438431
439432 if (IS_ERR(backend->frontend))
440433 return false;
441434
442
- return sun4i_backend_plane_uses_scaler(state);
435
+ if (!sun4i_frontend_format_is_supported(format, modifier))
436
+ return false;
437
+
438
+ if (!sun4i_backend_format_is_supported(format, modifier))
439
+ return true;
440
+
441
+ /*
442
+ * TODO: The backend alone allows 2x and 4x integer scaling, including
443
+ * support for an alpha component (which the frontend doesn't support).
444
+ * Use the backend directly instead of the frontend in this case, with
445
+ * another test to return false.
446
+ */
447
+
448
+ if (sun4i_backend_plane_uses_scaler(state))
449
+ return true;
450
+
451
+ /*
452
+ * Here the format is supported by both the frontend and the backend
453
+ * and no frontend scaling is required, so use the backend directly.
454
+ */
455
+ return false;
456
+}
457
+
458
+static bool sun4i_backend_plane_is_supported(struct drm_plane_state *state,
459
+ bool *uses_frontend)
460
+{
461
+ if (sun4i_backend_plane_uses_frontend(state)) {
462
+ *uses_frontend = true;
463
+ return true;
464
+ }
465
+
466
+ *uses_frontend = false;
467
+
468
+ /* Scaling is not supported without the frontend. */
469
+ if (sun4i_backend_plane_uses_scaler(state))
470
+ return false;
471
+
472
+ return true;
443473 }
444474
445475 static void sun4i_backend_atomic_begin(struct sunxi_engine *engine,
....@@ -457,12 +487,14 @@
457487 struct drm_crtc_state *crtc_state)
458488 {
459489 struct drm_plane_state *plane_states[SUN4I_BACKEND_NUM_LAYERS] = { 0 };
490
+ struct sun4i_backend *backend = engine_to_sun4i_backend(engine);
460491 struct drm_atomic_state *state = crtc_state->state;
461492 struct drm_device *drm = state->dev;
462493 struct drm_plane *plane;
463494 unsigned int num_planes = 0;
464495 unsigned int num_alpha_planes = 0;
465496 unsigned int num_frontend_planes = 0;
497
+ unsigned int num_alpha_planes_max = 1;
466498 unsigned int num_yuv_planes = 0;
467499 unsigned int current_pipe = 0;
468500 unsigned int i;
....@@ -480,14 +512,19 @@
480512 struct drm_framebuffer *fb = plane_state->fb;
481513 struct drm_format_name_buf format_name;
482514
483
- if (sun4i_backend_plane_uses_frontend(plane_state)) {
515
+ if (!sun4i_backend_plane_is_supported(plane_state,
516
+ &layer_state->uses_frontend))
517
+ return -EINVAL;
518
+
519
+ if (layer_state->uses_frontend) {
484520 DRM_DEBUG_DRIVER("Using the frontend for plane %d\n",
485521 plane->index);
486
-
487
- layer_state->uses_frontend = true;
488522 num_frontend_planes++;
489523 } else {
490
- layer_state->uses_frontend = false;
524
+ if (fb->format->is_yuv) {
525
+ DRM_DEBUG_DRIVER("Plane FB format is YUV\n");
526
+ num_yuv_planes++;
527
+ }
491528 }
492529
493530 DRM_DEBUG_DRIVER("Plane FB format is %s\n",
....@@ -495,11 +532,6 @@
495532 &format_name));
496533 if (fb->format->has_alpha || (plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE))
497534 num_alpha_planes++;
498
-
499
- if (fb->format->is_yuv) {
500
- DRM_DEBUG_DRIVER("Plane FB format is YUV\n");
501
- num_yuv_planes++;
502
- }
503535
504536 DRM_DEBUG_DRIVER("Plane zpos is %d\n",
505537 plane_state->normalized_zpos);
....@@ -526,32 +558,38 @@
526558 * the layer with the highest priority.
527559 *
528560 * The second step is the actual alpha blending, that takes
529
- * the two pipes as input, and uses the eventual alpha
561
+ * the two pipes as input, and uses the potential alpha
530562 * component to do the transparency between the two.
531563 *
532
- * This two steps scenario makes us unable to guarantee a
564
+ * This two-step scenario makes us unable to guarantee a
533565 * robust alpha blending between the 4 layers in all
534566 * situations, since this means that we need to have one layer
535567 * with alpha at the lowest position of our two pipes.
536568 *
537
- * However, we cannot even do that, since the hardware has a
538
- * bug where the lowest plane of the lowest pipe (pipe 0,
539
- * priority 0), if it has any alpha, will discard the pixel
540
- * entirely and just display the pixels in the background
541
- * color (black by default).
569
+ * However, we cannot even do that on every platform, since
570
+ * the hardware has a bug where the lowest plane of the lowest
571
+ * pipe (pipe 0, priority 0), if it has any alpha, will
572
+ * discard the pixel data entirely and just display the pixels
573
+ * in the background color (black by default).
542574 *
543
- * This means that we effectively have only three valid
544
- * configurations with alpha, all of them with the alpha being
545
- * on pipe1 with the lowest position, which can be 1, 2 or 3
546
- * depending on the number of planes and their zpos.
575
+ * This means that on the affected platforms, we effectively
576
+ * have only three valid configurations with alpha, all of
577
+ * them with the alpha being on pipe1 with the lowest
578
+ * position, which can be 1, 2 or 3 depending on the number of
579
+ * planes and their zpos.
547580 */
548
- if (num_alpha_planes > SUN4I_BACKEND_NUM_ALPHA_LAYERS) {
581
+
582
+ /* For platforms that are not affected by the issue described above. */
583
+ if (backend->quirks->supports_lowest_plane_alpha)
584
+ num_alpha_planes_max++;
585
+
586
+ if (num_alpha_planes > num_alpha_planes_max) {
549587 DRM_DEBUG_DRIVER("Too many planes with alpha, rejecting...\n");
550588 return -EINVAL;
551589 }
552590
553591 /* We can't have an alpha plane at the lowest position */
554
- if (plane_states[0]->fb->format->has_alpha ||
592
+ if (!backend->quirks->supports_lowest_plane_alpha &&
555593 (plane_states[0]->alpha != DRM_BLEND_ALPHA_OPAQUE))
556594 return -EINVAL;
557595
....@@ -673,33 +711,22 @@
673711 */
674712 static int sun4i_backend_of_get_id(struct device_node *node)
675713 {
676
- struct device_node *port, *ep;
677
- int ret = -EINVAL;
714
+ struct device_node *ep, *remote;
715
+ struct of_endpoint of_ep;
678716
679
- /* input is port 0 */
680
- port = of_graph_get_port_by_id(node, 0);
681
- if (!port)
717
+ /* Input port is 0, and we want the first endpoint. */
718
+ ep = of_graph_get_endpoint_by_regs(node, 0, -1);
719
+ if (!ep)
682720 return -EINVAL;
683721
684
- /* try finding an upstream endpoint */
685
- for_each_available_child_of_node(port, ep) {
686
- struct device_node *remote;
687
- u32 reg;
722
+ remote = of_graph_get_remote_endpoint(ep);
723
+ of_node_put(ep);
724
+ if (!remote)
725
+ return -EINVAL;
688726
689
- remote = of_graph_get_remote_endpoint(ep);
690
- if (!remote)
691
- continue;
692
-
693
- ret = of_property_read_u32(remote, "reg", &reg);
694
- if (ret)
695
- continue;
696
-
697
- ret = reg;
698
- }
699
-
700
- of_node_put(port);
701
-
702
- return ret;
727
+ of_graph_parse_endpoint(remote, &of_ep);
728
+ of_node_put(remote);
729
+ return of_ep.id;
703730 }
704731
705732 /* TODO: This needs to take multiple pipelines into account */
....@@ -742,7 +769,7 @@
742769 .vblank_quirk = sun4i_backend_vblank_quirk,
743770 };
744771
745
-static struct regmap_config sun4i_backend_regmap_config = {
772
+static const struct regmap_config sun4i_backend_regmap_config = {
746773 .reg_bits = 32,
747774 .val_bits = 32,
748775 .reg_stride = 4,
....@@ -766,6 +793,38 @@
766793 return -ENOMEM;
767794 dev_set_drvdata(dev, backend);
768795 spin_lock_init(&backend->frontend_lock);
796
+
797
+ if (of_find_property(dev->of_node, "interconnects", NULL)) {
798
+ /*
799
+ * This assume we have the same DMA constraints for all our the
800
+ * devices in our pipeline (all the backends, but also the
801
+ * frontends). This sounds bad, but it has always been the case
802
+ * for us, and DRM doesn't do per-device allocation either, so
803
+ * we would need to fix DRM first...
804
+ */
805
+ ret = of_dma_configure(drm->dev, dev->of_node, true);
806
+ if (ret)
807
+ return ret;
808
+ } else {
809
+ /*
810
+ * If we don't have the interconnect property, most likely
811
+ * because of an old DT, we need to set the DMA offset by hand
812
+ * on our device since the RAM mapping is at 0 for the DMA bus,
813
+ * unlike the CPU.
814
+ *
815
+ * XXX(hch): this has no business in a driver and needs to move
816
+ * to the device tree.
817
+ *
818
+ * If we have two subsequent calls to dma_direct_set_offset
819
+ * returns -EINVAL. Unfortunately, this happens when we have two
820
+ * backends in the system, and will result in the driver
821
+ * reporting an error while it has been setup properly before.
822
+ * Ignore EINVAL, but it should really be removed eventually.
823
+ */
824
+ ret = dma_direct_set_offset(drm->dev, PHYS_OFFSET, 0, SZ_4G);
825
+ if (ret && ret != -EINVAL)
826
+ return ret;
827
+ }
769828
770829 backend->engine.node = dev->of_node;
771830 backend->engine.ops = &sun4i_backend_engine_ops;
....@@ -808,6 +867,13 @@
808867 ret = PTR_ERR(backend->mod_clk);
809868 goto err_disable_bus_clk;
810869 }
870
+
871
+ ret = clk_set_rate_exclusive(backend->mod_clk, 300000000);
872
+ if (ret) {
873
+ dev_err(dev, "Couldn't set the module clock frequency\n");
874
+ goto err_disable_bus_clk;
875
+ }
876
+
811877 clk_prepare_enable(backend->mod_clk);
812878
813879 backend->ram_clk = devm_clk_get(dev, "ram");
....@@ -877,11 +943,14 @@
877943 : SUN4I_BACKEND_MODCTL_OUT_LCD0));
878944 }
879945
946
+ backend->quirks = quirks;
947
+
880948 return 0;
881949
882950 err_disable_ram_clk:
883951 clk_disable_unprepare(backend->ram_clk);
884952 err_disable_mod_clk:
953
+ clk_rate_exclusive_put(backend->mod_clk);
885954 clk_disable_unprepare(backend->mod_clk);
886955 err_disable_bus_clk:
887956 clk_disable_unprepare(backend->bus_clk);
....@@ -902,6 +971,7 @@
902971 sun4i_backend_free_sat(dev);
903972
904973 clk_disable_unprepare(backend->ram_clk);
974
+ clk_rate_exclusive_put(backend->mod_clk);
905975 clk_disable_unprepare(backend->mod_clk);
906976 clk_disable_unprepare(backend->bus_clk);
907977 reset_control_assert(backend->reset);
....@@ -939,6 +1009,7 @@
9391009 };
9401010
9411011 static const struct sun4i_backend_quirks sun8i_a33_backend_quirks = {
1012
+ .supports_lowest_plane_alpha = true,
9421013 };
9431014
9441015 static const struct sun4i_backend_quirks sun9i_backend_quirks = {
....@@ -962,6 +1033,10 @@
9621033 .data = &sun7i_backend_quirks,
9631034 },
9641035 {
1036
+ .compatible = "allwinner,sun8i-a23-display-backend",
1037
+ .data = &sun8i_a33_backend_quirks,
1038
+ },
1039
+ {
9651040 .compatible = "allwinner,sun8i-a33-display-backend",
9661041 .data = &sun8i_a33_backend_quirks,
9671042 },