1 /* 2 * Copyright (C) 2014 Intel Corporation 3 * 4 * DRM universal plane helper functions 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 */ 25 26 #include <linux/list.h> 27 #include <linux/export.h> 28 #include <drm/drmP.h> 29 #include <drm/drm_rect.h> 30 #include <drm/drm_plane_helper.h> 31 32 #define SUBPIXEL_MASK 0xffff 33 34 /* 35 * This is the minimal list of formats that seem to be safe for modeset use 36 * with all current DRM drivers. Most hardware can actually support more 37 * formats than this and drivers may specify a more accurate list when 38 * creating the primary plane. However drivers that still call 39 * drm_plane_init() will use this minimal format list as the default. 40 */ 41 static const uint32_t safe_modeset_formats[] = { 42 DRM_FORMAT_XRGB8888, 43 DRM_FORMAT_ARGB8888, 44 }; 45 46 /* 47 * Returns the connectors currently associated with a CRTC. This function 48 * should be called twice: once with a NULL connector list to retrieve 49 * the list size, and once with the properly allocated list to be filled in. 50 */ 51 static int get_connectors_for_crtc(struct drm_crtc *crtc, 52 struct drm_connector **connector_list, 53 int num_connectors) 54 { 55 struct drm_device *dev = crtc->dev; 56 struct drm_connector *connector; 57 int count = 0; 58 59 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 60 if (connector->encoder && connector->encoder->crtc == crtc) { 61 if (connector_list != NULL && count < num_connectors) 62 *(connector_list++) = connector; 63 64 count++; 65 } 66 67 return count; 68 } 69 70 /** 71 * drm_primary_helper_update() - Helper for primary plane update 72 * @plane: plane object to update 73 * @crtc: owning CRTC of owning plane 74 * @fb: framebuffer to flip onto plane 75 * @crtc_x: x offset of primary plane on crtc 76 * @crtc_y: y offset of primary plane on crtc 77 * @crtc_w: width of primary plane rectangle on crtc 78 * @crtc_h: height of primary plane rectangle on crtc 79 * @src_x: x offset of @fb for panning 80 * @src_y: y offset of @fb for panning 81 * @src_w: width of source rectangle in @fb 82 * @src_h: height of source rectangle in @fb 83 * 84 * Provides a default plane update handler for primary planes. This is handler 85 * is called in response to a userspace SetPlane operation on the plane with a 86 * non-NULL framebuffer. We call the driver's modeset handler to update the 87 * framebuffer. 88 * 89 * SetPlane() on a primary plane of a disabled CRTC is not supported, and will 90 * return an error. 91 * 92 * Note that we make some assumptions about hardware limitations that may not be 93 * true for all hardware -- 94 * 1) Primary plane cannot be repositioned. 95 * 2) Primary plane cannot be scaled. 96 * 3) Primary plane must cover the entire CRTC. 97 * 4) Subpixel positioning is not supported. 98 * Drivers for hardware that don't have these restrictions can provide their 99 * own implementation rather than using this helper. 100 * 101 * RETURNS: 102 * Zero on success, error code on failure 103 */ 104 int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, 105 struct drm_framebuffer *fb, 106 int crtc_x, int crtc_y, 107 unsigned int crtc_w, unsigned int crtc_h, 108 uint32_t src_x, uint32_t src_y, 109 uint32_t src_w, uint32_t src_h) 110 { 111 struct drm_mode_set set = { 112 .crtc = crtc, 113 .fb = fb, 114 .mode = &crtc->mode, 115 .x = src_x >> 16, 116 .y = src_y >> 16, 117 }; 118 struct drm_rect dest = { 119 .x1 = crtc_x, 120 .y1 = crtc_y, 121 .x2 = crtc_x + crtc_w, 122 .y2 = crtc_y + crtc_h, 123 }; 124 struct drm_rect clip = { 125 .x2 = crtc->mode.hdisplay, 126 .y2 = crtc->mode.vdisplay, 127 }; 128 struct drm_connector **connector_list; 129 struct drm_framebuffer *tmpfb; 130 int num_connectors, ret; 131 132 if (!crtc->enabled) { 133 DRM_DEBUG_KMS("Cannot update primary plane of a disabled CRTC.\n"); 134 return -EINVAL; 135 } 136 137 /* Disallow subpixel positioning */ 138 if ((src_x | src_y | src_w | src_h) & SUBPIXEL_MASK) { 139 DRM_DEBUG_KMS("Primary plane does not support subpixel positioning\n"); 140 return -EINVAL; 141 } 142 143 /* Primary planes are locked to their owning CRTC */ 144 if (plane->possible_crtcs != drm_crtc_mask(crtc)) { 145 DRM_DEBUG_KMS("Cannot change primary plane CRTC\n"); 146 return -EINVAL; 147 } 148 149 /* Disallow scaling */ 150 if (crtc_w != src_w || crtc_h != src_h) { 151 DRM_DEBUG_KMS("Can't scale primary plane\n"); 152 return -EINVAL; 153 } 154 155 /* Make sure primary plane covers entire CRTC */ 156 drm_rect_intersect(&dest, &clip); 157 if (dest.x1 != 0 || dest.y1 != 0 || 158 dest.x2 != crtc->mode.hdisplay || dest.y2 != crtc->mode.vdisplay) { 159 DRM_DEBUG_KMS("Primary plane must cover entire CRTC\n"); 160 return -EINVAL; 161 } 162 163 /* Framebuffer must be big enough to cover entire plane */ 164 ret = drm_crtc_check_viewport(crtc, crtc_x, crtc_y, &crtc->mode, fb); 165 if (ret) 166 return ret; 167 168 /* Find current connectors for CRTC */ 169 num_connectors = get_connectors_for_crtc(crtc, NULL, 0); 170 BUG_ON(num_connectors == 0); 171 connector_list = kzalloc(num_connectors * sizeof(*connector_list), 172 GFP_KERNEL); 173 if (!connector_list) 174 return -ENOMEM; 175 get_connectors_for_crtc(crtc, connector_list, num_connectors); 176 177 set.connectors = connector_list; 178 set.num_connectors = num_connectors; 179 180 /* 181 * set_config() adjusts crtc->primary->fb; however the DRM setplane 182 * code that called us expects to handle the framebuffer update and 183 * reference counting; save and restore the current fb before 184 * calling it. 185 * 186 * N.B., we call set_config() directly here rather than using 187 * drm_mode_set_config_internal. We're reprogramming the same 188 * connectors that were already in use, so we shouldn't need the extra 189 * cross-CRTC fb refcounting to accomodate stealing connectors. 190 * drm_mode_setplane() already handles the basic refcounting for the 191 * framebuffers involved in this operation. 192 */ 193 tmpfb = plane->fb; 194 ret = crtc->funcs->set_config(&set); 195 plane->fb = tmpfb; 196 197 kfree(connector_list); 198 return ret; 199 } 200 EXPORT_SYMBOL(drm_primary_helper_update); 201 202 /** 203 * drm_primary_helper_disable() - Helper for primary plane disable 204 * @plane: plane to disable 205 * 206 * Provides a default plane disable handler for primary planes. This is handler 207 * is called in response to a userspace SetPlane operation on the plane with a 208 * NULL framebuffer parameter. It unconditionally fails the disable call with 209 * -EINVAL the only way to disable the primary plane without driver support is 210 * to disable the entier CRTC. Which does not match the plane ->disable hook. 211 * 212 * Note that some hardware may be able to disable the primary plane without 213 * disabling the whole CRTC. Drivers for such hardware should provide their 214 * own disable handler that disables just the primary plane (and they'll likely 215 * need to provide their own update handler as well to properly re-enable a 216 * disabled primary plane). 217 * 218 * RETURNS: 219 * Unconditionally returns -EINVAL. 220 */ 221 int drm_primary_helper_disable(struct drm_plane *plane) 222 { 223 return -EINVAL; 224 } 225 EXPORT_SYMBOL(drm_primary_helper_disable); 226 227 /** 228 * drm_primary_helper_destroy() - Helper for primary plane destruction 229 * @plane: plane to destroy 230 * 231 * Provides a default plane destroy handler for primary planes. This handler 232 * is called during CRTC destruction. We disable the primary plane, remove 233 * it from the DRM plane list, and deallocate the plane structure. 234 */ 235 void drm_primary_helper_destroy(struct drm_plane *plane) 236 { 237 plane->funcs->disable_plane(plane); 238 drm_plane_cleanup(plane); 239 kfree(plane); 240 } 241 EXPORT_SYMBOL(drm_primary_helper_destroy); 242 243 const 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 }; 248 EXPORT_SYMBOL(drm_primary_helper_funcs); 249 250 /** 251 * drm_primary_helper_create_plane() - Create a generic primary plane 252 * @dev: drm device 253 * @formats: pixel formats supported, or NULL for a default safe list 254 * @num_formats: size of @formats; ignored if @formats is NULL 255 * 256 * Allocates and initializes a primary plane that can be used with the primary 257 * plane helpers. Drivers that wish to use driver-specific plane structures or 258 * provide custom handler functions may perform their own allocation and 259 * initialization rather than calling this function. 260 */ 261 struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev, 262 const uint32_t *formats, 263 int num_formats) 264 { 265 struct drm_plane *primary; 266 int ret; 267 268 primary = kzalloc(sizeof(*primary), GFP_KERNEL); 269 if (primary == NULL) { 270 DRM_DEBUG_KMS("Failed to allocate primary plane\n"); 271 return NULL; 272 } 273 274 if (formats == NULL) { 275 formats = safe_modeset_formats; 276 num_formats = ARRAY_SIZE(safe_modeset_formats); 277 } 278 279 /* possible_crtc's will be filled in later by crtc_init */ 280 ret = drm_plane_init(dev, primary, 0, &drm_primary_helper_funcs, 281 formats, num_formats, 282 DRM_PLANE_TYPE_PRIMARY); 283 if (ret) { 284 kfree(primary); 285 primary = NULL; 286 } 287 288 return primary; 289 } 290 EXPORT_SYMBOL(drm_primary_helper_create_plane); 291 292 /** 293 * drm_crtc_init - Legacy CRTC initialization function 294 * @dev: DRM device 295 * @crtc: CRTC object to init 296 * @funcs: callbacks for the new CRTC 297 * 298 * Initialize a CRTC object with a default helper-provided primary plane and no 299 * cursor plane. 300 * 301 * Returns: 302 * Zero on success, error code on failure. 303 */ 304 int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, 305 const struct drm_crtc_funcs *funcs) 306 { 307 struct drm_plane *primary; 308 309 primary = drm_primary_helper_create_plane(dev, NULL, 0); 310 return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs); 311 } 312 EXPORT_SYMBOL(drm_crtc_init); 313