1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
From eb708cc358e2f94461f971012c9c477a41b01237 Mon Sep 17 00:00:00 2001
From: Eric Anholt <eric@anholt.net>
Date: Mon, 28 Dec 2015 14:34:44 -0800
Subject: [PATCH] drm/vc4: Move the plane clipping/scaling setup to a separate
function.
As we add actual scaling, this is going to get way more complicated.
Signed-off-by: Eric Anholt <eric@anholt.net>
(cherry picked from commit 5c6799942003df91801b1d2277bba34d71f99603)
---
drivers/gpu/drm/vc4/vc4_plane.c | 78 +++++++++++++++++++++++++++--------------
1 file changed, 52 insertions(+), 26 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -40,6 +40,14 @@ struct vc4_plane_state {
* hardware at vc4_crtc_atomic_flush() time.
*/
u32 __iomem *hw_dlist;
+
+ /* Clipped coordinates of the plane on the display. */
+ int crtc_x, crtc_y, crtc_w, crtc_h;
+
+ /* Offset to start scanning out from the start of the plane's
+ * BO.
+ */
+ u32 offset;
};
static inline struct vc4_plane_state *
@@ -167,22 +175,17 @@ static void vc4_dlist_write(struct vc4_p
vc4_state->dlist[vc4_state->dlist_count++] = val;
}
-/* Writes out a full display list for an active plane to the plane's
- * private dlist state.
- */
-static int vc4_plane_mode_set(struct drm_plane *plane,
- struct drm_plane_state *state)
+static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
{
struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
struct drm_framebuffer *fb = state->fb;
- struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
- u32 ctl0_offset = vc4_state->dlist_count;
- const struct hvs_format *format = vc4_get_hvs_format(fb->pixel_format);
- uint32_t offset = fb->offsets[0];
- int crtc_x = state->crtc_x;
- int crtc_y = state->crtc_y;
- int crtc_w = state->crtc_w;
- int crtc_h = state->crtc_h;
+
+ vc4_state->offset = fb->offsets[0];
+
+ vc4_state->crtc_x = state->crtc_x;
+ vc4_state->crtc_y = state->crtc_y;
+ vc4_state->crtc_w = state->crtc_w;
+ vc4_state->crtc_h = state->crtc_h;
if (state->crtc_w << 16 != state->src_w ||
state->crtc_h << 16 != state->src_h) {
@@ -194,18 +197,41 @@ static int vc4_plane_mode_set(struct drm
return -EINVAL;
}
- if (crtc_x < 0) {
- offset += drm_format_plane_cpp(fb->pixel_format, 0) * -crtc_x;
- crtc_w += crtc_x;
- crtc_x = 0;
+ if (vc4_state->crtc_x < 0) {
+ vc4_state->offset += (drm_format_plane_cpp(fb->pixel_format,
+ 0) *
+ -vc4_state->crtc_x);
+ vc4_state->crtc_w += vc4_state->crtc_x;
+ vc4_state->crtc_x = 0;
}
- if (crtc_y < 0) {
- offset += fb->pitches[0] * -crtc_y;
- crtc_h += crtc_y;
- crtc_y = 0;
+ if (vc4_state->crtc_y < 0) {
+ vc4_state->offset += fb->pitches[0] * -vc4_state->crtc_y;
+ vc4_state->crtc_h += vc4_state->crtc_y;
+ vc4_state->crtc_y = 0;
}
+ return 0;
+}
+
+
+/* Writes out a full display list for an active plane to the plane's
+ * private dlist state.
+ */
+static int vc4_plane_mode_set(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
+ struct drm_framebuffer *fb = state->fb;
+ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+ u32 ctl0_offset = vc4_state->dlist_count;
+ const struct hvs_format *format = vc4_get_hvs_format(fb->pixel_format);
+ int ret;
+
+ ret = vc4_plane_setup_clipping_and_scaling(state);
+ if (ret)
+ return ret;
+
vc4_dlist_write(vc4_state,
SCALER_CTL0_VALID |
(format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
@@ -215,8 +241,8 @@ static int vc4_plane_mode_set(struct drm
/* Position Word 0: Image Positions and Alpha Value */
vc4_dlist_write(vc4_state,
VC4_SET_FIELD(0xff, SCALER_POS0_FIXED_ALPHA) |
- VC4_SET_FIELD(crtc_x, SCALER_POS0_START_X) |
- VC4_SET_FIELD(crtc_y, SCALER_POS0_START_Y));
+ VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) |
+ VC4_SET_FIELD(vc4_state->crtc_y, SCALER_POS0_START_Y));
/* Position Word 1: Scaled Image Dimensions.
* Skipped due to SCALER_CTL0_UNITY scaling.
@@ -228,8 +254,8 @@ static int vc4_plane_mode_set(struct drm
SCALER_POS2_ALPHA_MODE_PIPELINE :
SCALER_POS2_ALPHA_MODE_FIXED,
SCALER_POS2_ALPHA_MODE) |
- VC4_SET_FIELD(crtc_w, SCALER_POS2_WIDTH) |
- VC4_SET_FIELD(crtc_h, SCALER_POS2_HEIGHT));
+ VC4_SET_FIELD(vc4_state->crtc_w, SCALER_POS2_WIDTH) |
+ VC4_SET_FIELD(vc4_state->crtc_h, SCALER_POS2_HEIGHT));
/* Position Word 3: Context. Written by the HVS. */
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
@@ -237,7 +263,7 @@ static int vc4_plane_mode_set(struct drm
vc4_state->pw0_offset = vc4_state->dlist_count;
/* Pointer Word 0: RGB / Y Pointer */
- vc4_dlist_write(vc4_state, bo->paddr + offset);
+ vc4_dlist_write(vc4_state, bo->paddr + vc4_state->offset);
/* Pointer Context Word 0: Written by the HVS */
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
|