Skip to content

Commit 18315ee

Browse files
committed
drm: apple: Move plane bits out of apple_drv/iomfb_flush
Now that dcp may use multiple planes with more complex paramters move this out of iomfb_flush and use the appropriate KMS atomic plane helper functions. Also move most plane handling functions from apple_drv.c to its own file. Signed-off-by: Janne Grunau <[email protected]>
1 parent e20025c commit 18315ee

10 files changed

Lines changed: 357 additions & 265 deletions

File tree

drivers/gpu/drm/apple/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ appledrm-y += ibootep.o
1111
appledrm-y += iomfb_v12_3.o
1212
appledrm-y += iomfb_v13_3.o
1313
appledrm-y += epic/dpavservep.o
14+
appledrm-y += plane.o
1415

1516

1617
appledrm-$(CONFIG_TRACING) += trace.o

drivers/gpu/drm/apple/apple_drv.c

Lines changed: 1 addition & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include <drm/drm_drv.h>
2727
#include <drm/drm_fb_helper.h>
2828
#include <drm/drm_fbdev_dma.h>
29-
#include <drm/drm_fourcc.h>
3029
#include <drm/drm_fb_dma_helper.h>
3130
#include <drm/drm_gem_dma_helper.h>
3231
#include <drm/drm_gem_framebuffer_helper.h>
@@ -40,12 +39,11 @@
4039
#include <drm/drm_fixed.h>
4140

4241
#include "dcp.h"
42+
#include "plane.h"
4343

4444
#define DRIVER_NAME "apple"
4545
#define DRIVER_DESC "Apple display controller DRM driver"
4646

47-
#define FRAC_16_16(mult, div) (((mult) << 16) / (div))
48-
4947
#define MAX_COPROCESSORS 3
5048

5149
struct apple_drm_private {
@@ -77,172 +75,6 @@ static const struct drm_driver apple_drm_driver = {
7775
.fops = &apple_fops,
7876
};
7977

80-
static int apple_plane_atomic_check(struct drm_plane *plane,
81-
struct drm_atomic_state *state)
82-
{
83-
struct drm_plane_state *new_plane_state;
84-
struct drm_crtc_state *crtc_state;
85-
struct drm_rect *dst;
86-
int ret;
87-
88-
new_plane_state = drm_atomic_get_new_plane_state(state, plane);
89-
90-
if (!new_plane_state->crtc)
91-
return 0;
92-
93-
crtc_state = drm_atomic_get_crtc_state(state, new_plane_state->crtc);
94-
if (IS_ERR(crtc_state))
95-
return PTR_ERR(crtc_state);
96-
97-
/*
98-
* DCP limits downscaling to 2x and upscaling to 4x. Attempting to
99-
* scale outside these bounds errors out when swapping.
100-
*
101-
* This function also takes care of clipping the src/dest rectangles,
102-
* which is required for correct operation. Partially off-screen
103-
* surfaces may appear corrupted.
104-
*
105-
* DCP does not distinguish plane types in the hardware, so we set
106-
* can_position. If the primary plane does not fill the screen, the
107-
* hardware will fill in zeroes (black).
108-
*/
109-
ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
110-
FRAC_16_16(1, 2),
111-
FRAC_16_16(4, 1),
112-
true, true);
113-
if (ret < 0)
114-
return ret;
115-
116-
if (!new_plane_state->visible)
117-
return 0;
118-
119-
/*
120-
* DCP does not allow a surface to clip off the screen, and will crash
121-
* if any blended surface is smaller than 32x32. Reject the atomic op
122-
* if the plane will crash DCP.
123-
*
124-
* This is most pertinent to cursors. Userspace should fall back to
125-
* software cursors if the plane check is rejected.
126-
*/
127-
dst = &new_plane_state->dst;
128-
if (drm_rect_width(dst) < 32 || drm_rect_height(dst) < 32) {
129-
dev_err_once(state->dev->dev,
130-
"Plane operation would have crashed DCP! Rejected!\n\
131-
DCP requires 32x32 of every plane to be within screen space.\n\
132-
Your compositor asked to overlay [%dx%d, %dx%d] on %dx%d.\n\
133-
This is not supported, and your compositor should have\n\
134-
switched to software compositing when this operation failed.\n\
135-
You should not have noticed this at all. If your screen\n\
136-
froze/hitched, or your compositor crashed, please report\n\
137-
this to the your compositor's developers. We will not\n\
138-
throw this error again until you next reboot.\n",
139-
dst->x1, dst->y1, dst->x2, dst->y2,
140-
crtc_state->mode.hdisplay, crtc_state->mode.vdisplay);
141-
return -EINVAL;
142-
}
143-
144-
return 0;
145-
}
146-
147-
static void apple_plane_atomic_update(struct drm_plane *plane,
148-
struct drm_atomic_state *state)
149-
{
150-
/* Handled in atomic_flush */
151-
}
152-
153-
static const struct drm_plane_helper_funcs apple_primary_plane_helper_funcs = {
154-
.atomic_check = apple_plane_atomic_check,
155-
.atomic_update = apple_plane_atomic_update,
156-
.get_scanout_buffer = drm_fb_dma_get_scanout_buffer,
157-
};
158-
159-
static const struct drm_plane_helper_funcs apple_plane_helper_funcs = {
160-
.atomic_check = apple_plane_atomic_check,
161-
.atomic_update = apple_plane_atomic_update,
162-
};
163-
164-
static void apple_plane_cleanup(struct drm_plane *plane)
165-
{
166-
drm_plane_cleanup(plane);
167-
kfree(plane);
168-
}
169-
170-
static const struct drm_plane_funcs apple_plane_funcs = {
171-
.update_plane = drm_atomic_helper_update_plane,
172-
.disable_plane = drm_atomic_helper_disable_plane,
173-
.destroy = apple_plane_cleanup,
174-
.reset = drm_atomic_helper_plane_reset,
175-
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
176-
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
177-
};
178-
179-
/*
180-
* Table of supported formats, mapping from DRM fourccs to DCP fourccs.
181-
*
182-
* For future work, DCP supports more formats not listed, including YUV
183-
* formats, an extra RGBA format, and a biplanar RGB10_A8 format (fourcc b3a8)
184-
* used for HDR.
185-
*
186-
* Note: we don't have non-alpha formats but userspace breaks without XRGB. It
187-
* doesn't matter for the primary plane, but cursors/overlays must not
188-
* advertise formats without alpha.
189-
*/
190-
static const u32 dcp_primary_formats[] = {
191-
DRM_FORMAT_XRGB2101010,
192-
DRM_FORMAT_XRGB8888,
193-
DRM_FORMAT_ARGB8888,
194-
DRM_FORMAT_XBGR8888,
195-
DRM_FORMAT_ABGR8888,
196-
};
197-
198-
static const u32 dcp_overlay_formats[] = {
199-
DRM_FORMAT_ARGB8888,
200-
DRM_FORMAT_ABGR8888,
201-
};
202-
203-
u64 apple_format_modifiers[] = {
204-
DRM_FORMAT_MOD_LINEAR,
205-
DRM_FORMAT_MOD_INVALID
206-
};
207-
208-
static struct drm_plane *apple_plane_init(struct drm_device *dev,
209-
unsigned long possible_crtcs,
210-
enum drm_plane_type type)
211-
{
212-
int ret;
213-
struct drm_plane *plane;
214-
215-
plane = kzalloc(sizeof(*plane), GFP_KERNEL);
216-
217-
switch (type) {
218-
case DRM_PLANE_TYPE_PRIMARY:
219-
ret = drm_universal_plane_init(dev, plane, possible_crtcs,
220-
&apple_plane_funcs,
221-
dcp_primary_formats, ARRAY_SIZE(dcp_primary_formats),
222-
apple_format_modifiers, type, NULL);
223-
break;
224-
case DRM_PLANE_TYPE_OVERLAY:
225-
case DRM_PLANE_TYPE_CURSOR:
226-
ret = drm_universal_plane_init(dev, plane, possible_crtcs,
227-
&apple_plane_funcs,
228-
dcp_overlay_formats, ARRAY_SIZE(dcp_overlay_formats),
229-
apple_format_modifiers, type, NULL);
230-
break;
231-
default:
232-
return NULL;
233-
}
234-
235-
if (ret)
236-
return ERR_PTR(ret);
237-
238-
if (type == DRM_PLANE_TYPE_PRIMARY)
239-
drm_plane_helper_add(plane, &apple_primary_plane_helper_funcs);
240-
else
241-
drm_plane_helper_add(plane, &apple_plane_helper_funcs);
242-
243-
return plane;
244-
}
245-
24678
static enum drm_connector_status
24779
apple_connector_detect(struct drm_connector *connector, bool force)
24880
{

drivers/gpu/drm/apple/iomfb.c

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -356,25 +356,6 @@ struct dcp_rect drm_to_dcp_rect(struct drm_rect *rect)
356356
.h = drm_rect_height(rect) };
357357
}
358358

359-
u32 drm_format_to_dcp(u32 drm)
360-
{
361-
switch (drm) {
362-
case DRM_FORMAT_XRGB8888:
363-
case DRM_FORMAT_ARGB8888:
364-
return fourcc_code('A', 'R', 'G', 'B');
365-
366-
case DRM_FORMAT_XBGR8888:
367-
case DRM_FORMAT_ABGR8888:
368-
return fourcc_code('A', 'B', 'G', 'R');
369-
370-
case DRM_FORMAT_XRGB2101010:
371-
return fourcc_code('r', '0', '3', 'w');
372-
}
373-
374-
pr_warn("DRM format %X not supported in DCP\n", drm);
375-
return 0;
376-
}
377-
378359
int dcp_get_modes(struct drm_connector *connector)
379360
{
380361
struct apple_connector *apple_connector = to_apple_connector(connector);

drivers/gpu/drm/apple/iomfb.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ enum iomfb_property_id {
7979
#define SWAP_SURFACES 4
8080
/* We have 4 surfaces, but we can only ever blend two */
8181
#define MAX_BLEND_SURFACES 2
82-
#define MAX_PLANES 3
8382

8483
enum dcp_colorspace {
8584
DCP_COLORSPACE_BG_SRGB = 0,
@@ -113,25 +112,6 @@ struct dcp_rect {
113112
*/
114113
#define IOMFB_SET_BACKGROUND BIT(31)
115114

116-
/* Information describing a plane of a planar compressed surface */
117-
struct dcp_plane_info {
118-
u32 width;
119-
u32 height;
120-
u32 base;
121-
u32 offset;
122-
u32 stride;
123-
u32 size;
124-
u16 tile_size;
125-
u8 tile_w;
126-
u8 tile_h;
127-
u32 unk[13];
128-
} __packed;
129-
130-
struct dcp_component_types {
131-
u8 count;
132-
u8 types[7];
133-
} __packed;
134-
135115
struct dcp_allocate_bandwidth_req {
136116
u64 unk1;
137117
u64 unk2;

drivers/gpu/drm/apple/iomfb_internal.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,6 @@ void dcp_ack(struct apple_dcp *dcp, enum dcp_context_id context);
116116
*/
117117
struct dcp_rect drm_to_dcp_rect(struct drm_rect *rect);
118118

119-
u32 drm_format_to_dcp(u32 drm);
120-
121119
/* The user may own drm_display_mode, so we need to search for our copy */
122120
struct dcp_display_mode *lookup_mode(struct apple_dcp *dcp,
123121
const struct drm_display_mode *mode);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// SPDX-License-Identifier: GPL-2.0-only OR MIT
2+
/*
3+
* Copyright (C) The Asahi Linux Contributors
4+
*/
5+
6+
7+
#ifndef __APPLE_IOMFB_PLANE_H__
8+
#define __APPLE_IOMFB_PLANE_H__
9+
10+
#include <linux/types.h>
11+
12+
#define DCP_SURF_MAX_PLANES 3
13+
14+
/* Information describing a plane of a planar compressed surface */
15+
struct dcp_plane_info {
16+
u32 width;
17+
u32 height;
18+
u32 base;
19+
u32 offset;
20+
u32 stride;
21+
u32 size;
22+
u16 tile_size;
23+
u8 tile_w;
24+
u8 tile_h;
25+
u32 unk[13];
26+
} __packed;
27+
28+
struct dcp_component_types {
29+
u8 count;
30+
u8 types[7];
31+
} __packed;
32+
33+
/* Information describing a surface */
34+
struct dcp_surface {
35+
u8 is_tiled;
36+
u8 is_tearing_allowed;
37+
u8 is_premultiplied;
38+
u32 plane_cnt;
39+
u32 plane_cnt2;
40+
u32 format; /* DCP fourcc */
41+
u32 ycbcr_matrix;
42+
u8 xfer_func;
43+
u8 colorspace;
44+
u32 stride;
45+
u16 pix_size;
46+
u8 pel_w;
47+
u8 pel_h;
48+
u32 offset;
49+
u32 width;
50+
u32 height;
51+
u32 buf_size;
52+
u64 protection_opts;
53+
u32 surface_id;
54+
struct dcp_component_types comp_types[DCP_SURF_MAX_PLANES];
55+
u64 has_comp;
56+
struct dcp_plane_info planes[DCP_SURF_MAX_PLANES];
57+
u64 has_planes;
58+
u32 compression_info[DCP_SURF_MAX_PLANES][13];
59+
u64 has_compr_info;
60+
u32 unk_num;
61+
u32 unk_denom;
62+
} __packed;
63+
64+
#endif /* __APPLE_IOMFB_PLANE_H__ */

drivers/gpu/drm/apple/iomfb_template.c

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,10 +1305,10 @@ void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, stru
13051305
}
13061306

13071307
for_each_oldnew_plane_in_state(state, plane, old_state, new_state, plane_idx) {
1308+
struct apple_plane_state *apple_state = to_apple_plane_state(new_state);
13081309
struct drm_framebuffer *fb = new_state->fb;
13091310
struct drm_gem_dma_object *obj;
13101311
struct drm_rect src_rect;
1311-
bool is_premultiplied = false;
13121312

13131313
/* skip planes not for this crtc */
13141314
if (old_state->crtc != crtc && new_state->crtc != crtc)
@@ -1357,15 +1357,6 @@ void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, stru
13571357
req->surf_null[l] = false;
13581358
has_surface = 1;
13591359

1360-
/*
1361-
* DCP doesn't support XBGR8 / XRGB8 natively. Blending as
1362-
* pre-multiplied alpha with a black background can be used as
1363-
* workaround for the bottommost plane.
1364-
*/
1365-
if (fb->format->format == DRM_FORMAT_XRGB8888 ||
1366-
fb->format->format == DRM_FORMAT_XBGR8888)
1367-
is_premultiplied = true;
1368-
13691360
drm_rect_fp_to_int(&src_rect, &new_state->src);
13701361

13711362
req->swap.src_rect[l] = drm_to_dcp_rect(&src_rect);
@@ -1382,24 +1373,7 @@ void DCP_FW_NAME(iomfb_flush)(struct apple_dcp *dcp, struct drm_crtc *crtc, stru
13821373
if (obj)
13831374
req->surf_iova[l] = obj->dma_addr + fb->offsets[0];
13841375

1385-
req->surf[l] = (struct DCP_FW_NAME(dcp_surface)){
1386-
.is_premultiplied = is_premultiplied,
1387-
.format = drm_format_to_dcp(fb->format->format),
1388-
.xfer_func = DCP_XFER_FUNC_SDR,
1389-
.colorspace = DCP_COLORSPACE_NATIVE,
1390-
.stride = fb->pitches[0],
1391-
.width = fb->width,
1392-
.height = fb->height,
1393-
.buf_size = fb->height * fb->pitches[0],
1394-
.surface_id = req->swap.surf_ids[l],
1395-
1396-
/* Only used for compressed or multiplanar surfaces */
1397-
.pix_size = 1,
1398-
.pel_w = 1,
1399-
.pel_h = 1,
1400-
.has_comp = 1,
1401-
.has_planes = 1,
1402-
};
1376+
req->surf[l].base = apple_state->surf;
14031377

14041378
}
14051379

0 commit comments

Comments
 (0)