aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_plane_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_plane_helper.c')
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c131
1 files changed, 95 insertions, 36 deletions
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 1b15643b4586..6d133149cc74 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -25,6 +25,7 @@
25 25
26#include <linux/list.h> 26#include <linux/list.h>
27#include <drm/drmP.h> 27#include <drm/drmP.h>
28#include <drm/drm_plane_helper.h>
28#include <drm/drm_rect.h> 29#include <drm/drm_rect.h>
29#include <drm/drm_plane_helper.h> 30#include <drm/drm_plane_helper.h>
30 31
@@ -74,6 +75,79 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
74} 75}
75 76
76/** 77/**
78 * drm_plane_helper_check_update() - Check plane update for validity
79 * @plane: plane object to update
80 * @crtc: owning CRTC of owning plane
81 * @fb: framebuffer to flip onto plane
82 * @src: source coordinates in 16.16 fixed point
83 * @dest: integer destination coordinates
84 * @clip: integer clipping coordinates
85 * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
86 * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
87 * @can_position: is it legal to position the plane such that it
88 * doesn't cover the entire crtc? This will generally
89 * only be false for primary planes.
90 * @can_update_disabled: can the plane be updated while the crtc
91 * is disabled?
92 * @visible: output parameter indicating whether plane is still visible after
93 * clipping
94 *
95 * Checks that a desired plane update is valid. Drivers that provide
96 * their own plane handling rather than helper-provided implementations may
97 * still wish to call this function to avoid duplication of error checking
98 * code.
99 *
100 * RETURNS:
101 * Zero if update appears valid, error code on failure
102 */
103int drm_plane_helper_check_update(struct drm_plane *plane,
104 struct drm_crtc *crtc,
105 struct drm_framebuffer *fb,
106 struct drm_rect *src,
107 struct drm_rect *dest,
108 const struct drm_rect *clip,
109 int min_scale,
110 int max_scale,
111 bool can_position,
112 bool can_update_disabled,
113 bool *visible)
114{
115 int hscale, vscale;
116
117 if (!crtc->enabled && !can_update_disabled) {
118 DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
119 return -EINVAL;
120 }
121
122 /* Check scaling */
123 hscale = drm_rect_calc_hscale(src, dest, min_scale, max_scale);
124 vscale = drm_rect_calc_vscale(src, dest, min_scale, max_scale);
125 if (hscale < 0 || vscale < 0) {
126 DRM_DEBUG_KMS("Invalid scaling of plane\n");
127 return -ERANGE;
128 }
129
130 *visible = drm_rect_clip_scaled(src, dest, clip, hscale, vscale);
131 if (!*visible)
132 /*
133 * Plane isn't visible; some drivers can handle this
134 * so we just return success here. Drivers that can't
135 * (including those that use the primary plane helper's
136 * update function) will return an error from their
137 * update_plane handler.
138 */
139 return 0;
140
141 if (!can_position && !drm_rect_equals(dest, clip)) {
142 DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
143 return -EINVAL;
144 }
145
146 return 0;
147}
148EXPORT_SYMBOL(drm_plane_helper_check_update);
149
150/**
77 * drm_primary_helper_update() - Helper for primary plane update 151 * drm_primary_helper_update() - Helper for primary plane update
78 * @plane: plane object to update 152 * @plane: plane object to update
79 * @crtc: owning CRTC of owning plane 153 * @crtc: owning CRTC of owning plane
@@ -121,57 +195,42 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
121 .x = src_x >> 16, 195 .x = src_x >> 16,
122 .y = src_y >> 16, 196 .y = src_y >> 16,
123 }; 197 };
198 struct drm_rect src = {
199 .x1 = src_x,
200 .y1 = src_y,
201 .x2 = src_x + src_w,
202 .y2 = src_y + src_h,
203 };
124 struct drm_rect dest = { 204 struct drm_rect dest = {
125 .x1 = crtc_x, 205 .x1 = crtc_x,
126 .y1 = crtc_y, 206 .y1 = crtc_y,
127 .x2 = crtc_x + crtc_w, 207 .x2 = crtc_x + crtc_w,
128 .y2 = crtc_y + crtc_h, 208 .y2 = crtc_y + crtc_h,
129 }; 209 };
130 struct drm_rect clip = { 210 const struct drm_rect clip = {
131 .x2 = crtc->mode.hdisplay, 211 .x2 = crtc->mode.hdisplay,
132 .y2 = crtc->mode.vdisplay, 212 .y2 = crtc->mode.vdisplay,
133 }; 213 };
134 struct drm_connector **connector_list; 214 struct drm_connector **connector_list;
135 int num_connectors, ret; 215 int num_connectors, ret;
216 bool visible;
136 217
137 if (!crtc->enabled) { 218 ret = drm_plane_helper_check_update(plane, crtc, fb,
138 DRM_DEBUG_KMS("Cannot update primary plane of a disabled CRTC.\n"); 219 &src, &dest, &clip,
139 return -EINVAL; 220 DRM_PLANE_HELPER_NO_SCALING,
140 } 221 DRM_PLANE_HELPER_NO_SCALING,
141 222 false, false, &visible);
142 /* Disallow subpixel positioning */
143 if ((src_x | src_y | src_w | src_h) & SUBPIXEL_MASK) {
144 DRM_DEBUG_KMS("Primary plane does not support subpixel positioning\n");
145 return -EINVAL;
146 }
147
148 /* Primary planes are locked to their owning CRTC */
149 if (plane->possible_crtcs != drm_crtc_mask(crtc)) {
150 DRM_DEBUG_KMS("Cannot change primary plane CRTC\n");
151 return -EINVAL;
152 }
153
154 /* Disallow scaling */
155 src_w >>= 16;
156 src_h >>= 16;
157 if (crtc_w != src_w || crtc_h != src_h) {
158 DRM_DEBUG_KMS("Can't scale primary plane\n");
159 return -EINVAL;
160 }
161
162 /* Make sure primary plane covers entire CRTC */
163 drm_rect_intersect(&dest, &clip);
164 if (dest.x1 != 0 || dest.y1 != 0 ||
165 dest.x2 != crtc->mode.hdisplay || dest.y2 != crtc->mode.vdisplay) {
166 DRM_DEBUG_KMS("Primary plane must cover entire CRTC\n");
167 return -EINVAL;
168 }
169
170 /* Framebuffer must be big enough to cover entire plane */
171 ret = drm_crtc_check_viewport(crtc, crtc_x, crtc_y, &crtc->mode, fb);
172 if (ret) 223 if (ret)
173 return ret; 224 return ret;
174 225
226 if (!visible)
227 /*
228 * Primary plane isn't visible. Note that unless a driver
229 * provides their own disable function, this will just
230 * wind up returning -EINVAL to userspace.
231 */
232 return plane->funcs->disable_plane(plane);
233
175 /* Find current connectors for CRTC */ 234 /* Find current connectors for CRTC */
176 num_connectors = get_connectors_for_crtc(crtc, NULL, 0); 235 num_connectors = get_connectors_for_crtc(crtc, NULL, 0);
177 BUG_ON(num_connectors == 0); 236 BUG_ON(num_connectors == 0);