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#include <linux/list.h>
27#include <drm/drmP.h>
28#include <drm/drm_plane_helper.h>
29#include <drm/drm_rect.h>
30#include <drm/drm_atomic.h>
31#include <drm/drm_atomic_uapi.h>
32#include <drm/drm_crtc_helper.h>
33#include <drm/drm_encoder.h>
34#include <drm/drm_atomic_helper.h>
35
36#define SUBPIXEL_MASK 0xffff
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
70static int get_connectors_for_crtc(struct drm_crtc *crtc,
71 struct drm_connector **connector_list,
72 int num_connectors)
73{
74 struct drm_device *dev = crtc->dev;
75 struct drm_connector *connector;
76 struct drm_connector_list_iter conn_iter;
77 int count = 0;
78
79
80
81
82
83
84 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
85
86 drm_connector_list_iter_begin(dev, &conn_iter);
87 drm_for_each_connector_iter(connector, &conn_iter) {
88 if (connector->encoder && connector->encoder->crtc == crtc) {
89 if (connector_list != NULL && count < num_connectors)
90 *(connector_list++) = connector;
91
92 count++;
93 }
94 }
95 drm_connector_list_iter_end(&conn_iter);
96
97 return count;
98}
99
100static int drm_plane_helper_check_update(struct drm_plane *plane,
101 struct drm_crtc *crtc,
102 struct drm_framebuffer *fb,
103 struct drm_rect *src,
104 struct drm_rect *dst,
105 unsigned int rotation,
106 int min_scale,
107 int max_scale,
108 bool can_position,
109 bool can_update_disabled,
110 bool *visible)
111{
112 struct drm_plane_state plane_state = {
113 .plane = plane,
114 .crtc = crtc,
115 .fb = fb,
116 .src_x = src->x1,
117 .src_y = src->y1,
118 .src_w = drm_rect_width(src),
119 .src_h = drm_rect_height(src),
120 .crtc_x = dst->x1,
121 .crtc_y = dst->y1,
122 .crtc_w = drm_rect_width(dst),
123 .crtc_h = drm_rect_height(dst),
124 .rotation = rotation,
125 .visible = *visible,
126 };
127 struct drm_crtc_state crtc_state = {
128 .crtc = crtc,
129 .enable = crtc->enabled,
130 .mode = crtc->mode,
131 };
132 int ret;
133
134 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
135 min_scale, max_scale,
136 can_position,
137 can_update_disabled);
138 if (ret)
139 return ret;
140
141 *src = plane_state.src;
142 *dst = plane_state.dst;
143 *visible = plane_state.visible;
144
145 return 0;
146}
147
148static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
149 struct drm_framebuffer *fb,
150 int crtc_x, int crtc_y,
151 unsigned int crtc_w, unsigned int crtc_h,
152 uint32_t src_x, uint32_t src_y,
153 uint32_t src_w, uint32_t src_h,
154 struct drm_modeset_acquire_ctx *ctx)
155{
156 struct drm_mode_set set = {
157 .crtc = crtc,
158 .fb = fb,
159 .mode = &crtc->mode,
160 .x = src_x >> 16,
161 .y = src_y >> 16,
162 };
163 struct drm_rect src = {
164 .x1 = src_x,
165 .y1 = src_y,
166 .x2 = src_x + src_w,
167 .y2 = src_y + src_h,
168 };
169 struct drm_rect dest = {
170 .x1 = crtc_x,
171 .y1 = crtc_y,
172 .x2 = crtc_x + crtc_w,
173 .y2 = crtc_y + crtc_h,
174 };
175 struct drm_connector **connector_list;
176 int num_connectors, ret;
177 bool visible;
178
179 ret = drm_plane_helper_check_update(plane, crtc, fb,
180 &src, &dest,
181 DRM_MODE_ROTATE_0,
182 DRM_PLANE_HELPER_NO_SCALING,
183 DRM_PLANE_HELPER_NO_SCALING,
184 false, false, &visible);
185 if (ret)
186 return ret;
187
188 if (!visible)
189
190
191
192
193
194 return plane->funcs->disable_plane(plane, ctx);
195
196
197 num_connectors = get_connectors_for_crtc(crtc, NULL, 0);
198 BUG_ON(num_connectors == 0);
199 connector_list = kcalloc(num_connectors, sizeof(*connector_list),
200 GFP_KERNEL);
201 if (!connector_list)
202 return -ENOMEM;
203 get_connectors_for_crtc(crtc, connector_list, num_connectors);
204
205 set.connectors = connector_list;
206 set.num_connectors = num_connectors;
207
208
209
210
211
212
213
214
215
216 ret = crtc->funcs->set_config(&set, ctx);
217
218 kfree(connector_list);
219 return ret;
220}
221
222static int drm_primary_helper_disable(struct drm_plane *plane,
223 struct drm_modeset_acquire_ctx *ctx)
224{
225 return -EINVAL;
226}
227
228
229
230
231
232
233
234
235
236void drm_primary_helper_destroy(struct drm_plane *plane)
237{
238 drm_plane_cleanup(plane);
239 kfree(plane);
240}
241EXPORT_SYMBOL(drm_primary_helper_destroy);
242
243const struct drm_plane_funcs drm_primary_helper_funcs = {
244 .update_plane = drm_primary_helper_update,
245 .disable_plane = drm_primary_helper_disable,
246 .destroy = drm_primary_helper_destroy,
247};
248EXPORT_SYMBOL(drm_primary_helper_funcs);
249