diff options
author | Dave Airlie <airlied@redhat.com> | 2018-02-15 18:29:27 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-02-15 18:29:27 -0500 |
commit | 76ea0f334e7fb13226e64ee7de928611f5303faf (patch) | |
tree | 4a6b8d8f1b19a68072f2ce8f33add59be9a67be7 /drivers/gpu/drm/sun4i/sun4i_layer.c | |
parent | f0308d76906a5b65ec4fcc3b133394caa9f00638 (diff) | |
parent | 1bc3d3cce8c3b44c2b5ac6cee98c830bb40e6b0f (diff) |
Merge tag 'drm-misc-next-2018-02-13' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 4.17:
UAPI Changes:
- drm/vc4: Expose performance counters to userspace (Boris)
Cross-subsystem Changes:
- MAINTAINERS: Linus to maintain panel-arm-versatile in -misc (Linus)
Core Changes:
- Only use swiotlb when necessary (Chunming)
Driver Changes:
- drm/panel: Add support for ARM Versatile panels (Linus)
- pl111: Improvements around versatile panel support (Linus)
----------------------------------------
Tagged on 2018-02-06:
drm-misc-next for 4.17:
UAPI Changes:
- Validate mode flags + type (Ville)
- Deprecate unused mode flags PIXMUX, BCAST (Ville)
- Deprecate unused mode types BUILTIN, CRTC_C, CLOCK_C, DEFAULT (Ville)
Cross-subsystem Changes:
- MAINTAINERS: s/Daniel/Maarten/ for drm-misc (Daniel)
Core Changes:
- gem: Export gem functions for drivers to use (Samuel)
- bridge: Introduce bridge timings in drm_bridge (Linus)
- dma-buf: Allow exclusive fence to be bundled in fence array when
calling reservation_object_get_fences_rcu (Christian)
- dp: Add training pattern 4 and HBR3 support to dp helpers (Manasi)
- fourcc: Add alpha bit to formats to avoid driver format LUTs (Maxime)
- mode: Various cleanups + add new device-wide .mode_valid hook (Ville)
- atomic: Fix state leak when non-blocking commits fail (Leo)
NOTE: IIRC, this was cross-picked to -fixes so it might fall out
- crc: Allow polling on the data fd (Maarten)
Driver Changes:
- bridge/vga-dac: Add THS8134* support (Linus)
- tinydrm: Various MIPI DBI improvements/cleanups (Noralf)
- bridge/dw-mipi-dsi: Cleanups + use create_packet helper (Brian)
- drm/sun4i: Add Display Engine frontend support (Maxime)
- drm/sun4i: Add zpos support + increase num planes from 2 to 4 (Maxime)
- various: Use drm_mode_get_hv_timing() to fill plane clip rectangle (Ville)
- stm: Add 8-bit clut support, add dsi phy v1.31 support, +fixes (Phillipe)
Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
Cc: Chunming Zhou <david1.zhou@amd.com>
Cc: Samuel Li <Samuel.Li@amd.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Noralf Trønnes <noralf@tronnes.org>
Cc: Brian Norris <briannorris@chromium.org>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Manasi Navare <manasi.d.navare@intel.com>
Cc: Philippe Cornu <philippe.cornu@st.com>
Cc: Leo (Sunpeng) Li <sunpeng.li@amd.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
* tag 'drm-misc-next-2018-02-13' of git://anongit.freedesktop.org/drm/drm-misc: (115 commits)
drm/radeon: only enable swiotlb path when need v2
drm/amdgpu: only enable swiotlb alloc when need v2
drm: add func to get max iomem address v2
drm/vc4: Expose performance counters to userspace
drm: Print the pid when debug logging an ioctl error.
drm/stm: ltdc: remove non-alpha color formats on layer 2 for older hw
drm/stm: ltdc: add non-alpha color formats
drm/bridge/synopsys: dsi: Add 1.31 version support
drm/bridge/synopsys: dsi: Add read feature
drm/pl111: Support multiple endpoints on the CLCD
drm/pl111: Support variants with broken VBLANK
drm/pl111: Support variants with broken clock divider
drm/pl111: Handle the Versatile RGB/BGR565 mode
drm/pl111: Properly detect the ARM PL110 variants
drm/panel: Add support for ARM Versatile panels
drm/panel: Device tree bindings for ARM Versatile panels
drm/bridge: Rename argument from crtc to bridge
drm/crc: Add support for polling on the data fd.
drm/sun4i: Use drm_mode_get_hv_timing() to populate plane clip rectangle
drm/rcar-du: Use drm_mode_get_hv_timing() to populate plane clip rectangle
...
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun4i_layer.c')
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_layer.c | 117 |
1 files changed, 86 insertions, 31 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 7bddf12548d3..19be798e4fac 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c | |||
@@ -15,34 +15,107 @@ | |||
15 | #include <drm/drmP.h> | 15 | #include <drm/drmP.h> |
16 | 16 | ||
17 | #include "sun4i_backend.h" | 17 | #include "sun4i_backend.h" |
18 | #include "sun4i_frontend.h" | ||
18 | #include "sun4i_layer.h" | 19 | #include "sun4i_layer.h" |
19 | #include "sunxi_engine.h" | 20 | #include "sunxi_engine.h" |
20 | 21 | ||
21 | struct sun4i_plane_desc { | 22 | struct sun4i_plane_desc { |
22 | enum drm_plane_type type; | 23 | enum drm_plane_type type; |
23 | u8 pipe; | 24 | u8 pipe; |
24 | const uint32_t *formats; | 25 | const uint32_t *formats; |
25 | uint32_t nformats; | 26 | uint32_t nformats; |
26 | }; | 27 | }; |
27 | 28 | ||
29 | static void sun4i_backend_layer_reset(struct drm_plane *plane) | ||
30 | { | ||
31 | struct sun4i_layer *layer = plane_to_sun4i_layer(plane); | ||
32 | struct sun4i_layer_state *state; | ||
33 | |||
34 | if (plane->state) { | ||
35 | state = state_to_sun4i_layer_state(plane->state); | ||
36 | |||
37 | __drm_atomic_helper_plane_destroy_state(&state->state); | ||
38 | |||
39 | kfree(state); | ||
40 | plane->state = NULL; | ||
41 | } | ||
42 | |||
43 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
44 | if (state) { | ||
45 | plane->state = &state->state; | ||
46 | plane->state->plane = plane; | ||
47 | plane->state->zpos = layer->id; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static struct drm_plane_state * | ||
52 | sun4i_backend_layer_duplicate_state(struct drm_plane *plane) | ||
53 | { | ||
54 | struct sun4i_layer_state *orig = state_to_sun4i_layer_state(plane->state); | ||
55 | struct sun4i_layer_state *copy; | ||
56 | |||
57 | copy = kzalloc(sizeof(*copy), GFP_KERNEL); | ||
58 | if (!copy) | ||
59 | return NULL; | ||
60 | |||
61 | __drm_atomic_helper_plane_duplicate_state(plane, ©->state); | ||
62 | copy->uses_frontend = orig->uses_frontend; | ||
63 | |||
64 | return ©->state; | ||
65 | } | ||
66 | |||
67 | static void sun4i_backend_layer_destroy_state(struct drm_plane *plane, | ||
68 | struct drm_plane_state *state) | ||
69 | { | ||
70 | struct sun4i_layer_state *s_state = state_to_sun4i_layer_state(state); | ||
71 | |||
72 | __drm_atomic_helper_plane_destroy_state(state); | ||
73 | |||
74 | kfree(s_state); | ||
75 | } | ||
76 | |||
28 | static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane, | 77 | static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane, |
29 | struct drm_plane_state *old_state) | 78 | struct drm_plane_state *old_state) |
30 | { | 79 | { |
80 | struct sun4i_layer_state *layer_state = state_to_sun4i_layer_state(old_state); | ||
31 | struct sun4i_layer *layer = plane_to_sun4i_layer(plane); | 81 | struct sun4i_layer *layer = plane_to_sun4i_layer(plane); |
32 | struct sun4i_backend *backend = layer->backend; | 82 | struct sun4i_backend *backend = layer->backend; |
33 | 83 | ||
34 | sun4i_backend_layer_enable(backend, layer->id, false); | 84 | sun4i_backend_layer_enable(backend, layer->id, false); |
85 | |||
86 | if (layer_state->uses_frontend) { | ||
87 | unsigned long flags; | ||
88 | |||
89 | spin_lock_irqsave(&backend->frontend_lock, flags); | ||
90 | backend->frontend_teardown = true; | ||
91 | spin_unlock_irqrestore(&backend->frontend_lock, flags); | ||
92 | } | ||
35 | } | 93 | } |
36 | 94 | ||
37 | static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, | 95 | static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, |
38 | struct drm_plane_state *old_state) | 96 | struct drm_plane_state *old_state) |
39 | { | 97 | { |
98 | struct sun4i_layer_state *layer_state = state_to_sun4i_layer_state(plane->state); | ||
40 | struct sun4i_layer *layer = plane_to_sun4i_layer(plane); | 99 | struct sun4i_layer *layer = plane_to_sun4i_layer(plane); |
41 | struct sun4i_backend *backend = layer->backend; | 100 | struct sun4i_backend *backend = layer->backend; |
101 | struct sun4i_frontend *frontend = backend->frontend; | ||
102 | |||
103 | if (layer_state->uses_frontend) { | ||
104 | sun4i_frontend_init(frontend); | ||
105 | sun4i_frontend_update_coord(frontend, plane); | ||
106 | sun4i_frontend_update_buffer(frontend, plane); | ||
107 | sun4i_frontend_update_formats(frontend, plane, | ||
108 | DRM_FORMAT_ARGB8888); | ||
109 | sun4i_backend_update_layer_frontend(backend, layer->id, | ||
110 | DRM_FORMAT_ARGB8888); | ||
111 | sun4i_frontend_enable(frontend); | ||
112 | } else { | ||
113 | sun4i_backend_update_layer_formats(backend, layer->id, plane); | ||
114 | sun4i_backend_update_layer_buffer(backend, layer->id, plane); | ||
115 | } | ||
42 | 116 | ||
43 | sun4i_backend_update_layer_coord(backend, layer->id, plane); | 117 | sun4i_backend_update_layer_coord(backend, layer->id, plane); |
44 | sun4i_backend_update_layer_formats(backend, layer->id, plane); | 118 | sun4i_backend_update_layer_zpos(backend, layer->id, plane); |
45 | sun4i_backend_update_layer_buffer(backend, layer->id, plane); | ||
46 | sun4i_backend_layer_enable(backend, layer->id, true); | 119 | sun4i_backend_layer_enable(backend, layer->id, true); |
47 | } | 120 | } |
48 | 121 | ||
@@ -52,11 +125,11 @@ static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = { | |||
52 | }; | 125 | }; |
53 | 126 | ||
54 | static const struct drm_plane_funcs sun4i_backend_layer_funcs = { | 127 | static const struct drm_plane_funcs sun4i_backend_layer_funcs = { |
55 | .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, | 128 | .atomic_destroy_state = sun4i_backend_layer_destroy_state, |
56 | .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, | 129 | .atomic_duplicate_state = sun4i_backend_layer_duplicate_state, |
57 | .destroy = drm_plane_cleanup, | 130 | .destroy = drm_plane_cleanup, |
58 | .disable_plane = drm_atomic_helper_disable_plane, | 131 | .disable_plane = drm_atomic_helper_disable_plane, |
59 | .reset = drm_atomic_helper_plane_reset, | 132 | .reset = sun4i_backend_layer_reset, |
60 | .update_plane = drm_atomic_helper_update_plane, | 133 | .update_plane = drm_atomic_helper_update_plane, |
61 | }; | 134 | }; |
62 | 135 | ||
@@ -128,32 +201,12 @@ struct drm_plane **sun4i_layers_init(struct drm_device *drm, | |||
128 | struct sun4i_backend *backend = engine_to_sun4i_backend(engine); | 201 | struct sun4i_backend *backend = engine_to_sun4i_backend(engine); |
129 | int i; | 202 | int i; |
130 | 203 | ||
131 | planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1, | 204 | /* We need to have a sentinel at the need, hence the overallocation */ |
205 | planes = devm_kcalloc(drm->dev, SUN4I_BACKEND_NUM_LAYERS + 1, | ||
132 | sizeof(*planes), GFP_KERNEL); | 206 | sizeof(*planes), GFP_KERNEL); |
133 | if (!planes) | 207 | if (!planes) |
134 | return ERR_PTR(-ENOMEM); | 208 | return ERR_PTR(-ENOMEM); |
135 | 209 | ||
136 | /* | ||
137 | * The hardware is a bit unusual here. | ||
138 | * | ||
139 | * Even though it supports 4 layers, it does the composition | ||
140 | * in two separate steps. | ||
141 | * | ||
142 | * The first one is assigning a layer to one of its two | ||
143 | * pipes. If more that 1 layer is assigned to the same pipe, | ||
144 | * and if pixels overlaps, the pipe will take the pixel from | ||
145 | * the layer with the highest priority. | ||
146 | * | ||
147 | * The second step is the actual alpha blending, that takes | ||
148 | * the two pipes as input, and uses the eventual alpha | ||
149 | * component to do the transparency between the two. | ||
150 | * | ||
151 | * This two steps scenario makes us unable to guarantee a | ||
152 | * robust alpha blending between the 4 layers in all | ||
153 | * situations. So we just expose two layers, one per pipe. On | ||
154 | * SoCs that support it, sprites could fill the need for more | ||
155 | * layers. | ||
156 | */ | ||
157 | for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) { | 210 | for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) { |
158 | const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i]; | 211 | const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i]; |
159 | struct sun4i_layer *layer; | 212 | struct sun4i_layer *layer; |
@@ -165,6 +218,8 @@ struct drm_plane **sun4i_layers_init(struct drm_device *drm, | |||
165 | return ERR_CAST(layer); | 218 | return ERR_CAST(layer); |
166 | }; | 219 | }; |
167 | 220 | ||
221 | drm_plane_create_zpos_immutable_property(&layer->plane, i); | ||
222 | |||
168 | DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", | 223 | DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", |
169 | i ? "overlay" : "primary", plane->pipe); | 224 | i ? "overlay" : "primary", plane->pipe); |
170 | regmap_update_bits(engine->regs, SUN4I_BACKEND_ATTCTL_REG0(i), | 225 | regmap_update_bits(engine->regs, SUN4I_BACKEND_ATTCTL_REG0(i), |