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/export.h> 27 #include <linux/list.h> 28 29 #include <drm/drm_atomic.h> 30 #include <drm/drm_atomic_helper.h> 31 #include <drm/drm_atomic_uapi.h> 32 #include <drm/drm_device.h> 33 #include <drm/drm_drv.h> 34 #include <drm/drm_encoder.h> 35 #include <drm/drm_plane_helper.h> 36 #include <drm/drm_print.h> 37 #include <drm/drm_rect.h> 38 39 #define SUBPIXEL_MASK 0xffff 40 41 /** 42 * DOC: overview 43 * 44 * This helper library contains helpers to implement primary plane support on 45 * top of the normal CRTC configuration interface. 46 * Since the legacy &drm_mode_config_funcs.set_config interface ties the primary 47 * plane together with the CRTC state this does not allow userspace to disable 48 * the primary plane itself. The default primary plane only expose XRBG8888 and 49 * ARGB8888 as valid pixel formats for the attached framebuffer. 50 * 51 * Drivers are highly recommended to implement proper support for primary 52 * planes, and newly merged drivers must not rely upon these transitional 53 * helpers. 54 * 55 * The plane helpers share the function table structures with other helpers, 56 * specifically also the atomic helpers. See &struct drm_plane_helper_funcs for 57 * the details. 58 */ 59 60 /* 61 * Returns the connectors currently associated with a CRTC. This function 62 * should be called twice: once with a NULL connector list to retrieve 63 * the list size, and once with the properly allocated list to be filled in. 64 */ 65 static int get_connectors_for_crtc(struct drm_crtc *crtc, 66 struct drm_connector **connector_list, 67 int num_connectors) 68 { 69 struct drm_device *dev = crtc->dev; 70 struct drm_connector *connector; 71 struct drm_connector_list_iter conn_iter; 72 int count = 0; 73 74 /* 75 * Note: Once we change the plane hooks to more fine-grained locking we 76 * need to grab the connection_mutex here to be able to make these 77 * checks. 78 */ 79 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); 80 81 drm_connector_list_iter_begin(dev, &conn_iter); 82 drm_for_each_connector_iter(connector, &conn_iter) { 83 if (connector->encoder && connector->encoder->crtc == crtc) { 84 if (connector_list != NULL && count < num_connectors) 85 *(connector_list++) = connector; 86 87 count++; 88 } 89 } 90 drm_connector_list_iter_end(&conn_iter); 91 92 return count; 93 } 94 95 static int drm_plane_helper_check_update(struct drm_plane *plane, 96 struct drm_crtc *crtc, 97 struct drm_framebuffer *fb, 98 struct drm_rect *src, 99 struct drm_rect *dst, 100 unsigned int rotation, 101 int min_scale, 102 int max_scale, 103 bool can_position, 104 bool can_update_disabled, 105 bool *visible) 106 { 107 struct drm_plane_state plane_state = { 108 .plane = plane, 109 .crtc = crtc, 110 .fb = fb, 111 .src_x = src->x1, 112 .src_y = src->y1, 113 .src_w = drm_rect_width(src), 114 .src_h = drm_rect_height(src), 115 .crtc_x = dst->x1, 116 .crtc_y = dst->y1, 117 .crtc_w = drm_rect_width(dst), 118 .crtc_h = drm_rect_height(dst), 119 .rotation = rotation, 120 }; 121 struct drm_crtc_state crtc_state = { 122 .crtc = crtc, 123 .enable = crtc->enabled, 124 .mode = crtc->mode, 125 }; 126 int ret; 127 128 ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state, 129 min_scale, max_scale, 130 can_position, 131 can_update_disabled); 132 if (ret) 133 return ret; 134 135 *src = plane_state.src; 136 *dst = plane_state.dst; 137 *visible = plane_state.visible; 138 139 return 0; 140 } 141 142 /** 143 * drm_plane_helper_update_primary - Helper for updating primary planes 144 * @plane: plane to update 145 * @crtc: the plane's new CRTC 146 * @fb: the plane's new framebuffer 147 * @crtc_x: x coordinate within CRTC 148 * @crtc_y: y coordinate within CRTC 149 * @crtc_w: width coordinate within CRTC 150 * @crtc_h: height coordinate within CRTC 151 * @src_x: x coordinate within source 152 * @src_y: y coordinate within source 153 * @src_w: width coordinate within source 154 * @src_h: height coordinate within source 155 * @ctx: modeset locking context 156 * 157 * This helper validates the given parameters and updates the primary plane. 158 * 159 * This function is only useful for non-atomic modesetting. Don't use 160 * it in new drivers. 161 * 162 * Returns: 163 * Zero on success, or an errno code otherwise. 164 */ 165 int drm_plane_helper_update_primary(struct drm_plane *plane, struct drm_crtc *crtc, 166 struct drm_framebuffer *fb, 167 int crtc_x, int crtc_y, 168 unsigned int crtc_w, unsigned int crtc_h, 169 uint32_t src_x, uint32_t src_y, 170 uint32_t src_w, uint32_t src_h, 171 struct drm_modeset_acquire_ctx *ctx) 172 { 173 struct drm_mode_set set = { 174 .crtc = crtc, 175 .fb = fb, 176 .mode = &crtc->mode, 177 .x = src_x >> 16, 178 .y = src_y >> 16, 179 }; 180 struct drm_rect src = { 181 .x1 = src_x, 182 .y1 = src_y, 183 .x2 = src_x + src_w, 184 .y2 = src_y + src_h, 185 }; 186 struct drm_rect dest = { 187 .x1 = crtc_x, 188 .y1 = crtc_y, 189 .x2 = crtc_x + crtc_w, 190 .y2 = crtc_y + crtc_h, 191 }; 192 struct drm_device *dev = plane->dev; 193 struct drm_connector **connector_list; 194 int num_connectors, ret; 195 bool visible; 196 197 if (drm_WARN_ON_ONCE(dev, drm_drv_uses_atomic_modeset(dev))) 198 return -EINVAL; 199 200 ret = drm_plane_helper_check_update(plane, crtc, fb, 201 &src, &dest, 202 DRM_MODE_ROTATE_0, 203 DRM_PLANE_NO_SCALING, 204 DRM_PLANE_NO_SCALING, 205 false, false, &visible); 206 if (ret) 207 return ret; 208 209 if (!visible) 210 /* 211 * Primary plane isn't visible. Note that unless a driver 212 * provides their own disable function, this will just 213 * wind up returning -EINVAL to userspace. 214 */ 215 return plane->funcs->disable_plane(plane, ctx); 216 217 /* Find current connectors for CRTC */ 218 num_connectors = get_connectors_for_crtc(crtc, NULL, 0); 219 BUG_ON(num_connectors == 0); 220 connector_list = kcalloc(num_connectors, sizeof(*connector_list), 221 GFP_KERNEL); 222 if (!connector_list) 223 return -ENOMEM; 224 get_connectors_for_crtc(crtc, connector_list, num_connectors); 225 226 set.connectors = connector_list; 227 set.num_connectors = num_connectors; 228 229 /* 230 * We call set_config() directly here rather than using 231 * drm_mode_set_config_internal. We're reprogramming the same 232 * connectors that were already in use, so we shouldn't need the extra 233 * cross-CRTC fb refcounting to accommodate stealing connectors. 234 * drm_mode_setplane() already handles the basic refcounting for the 235 * framebuffers involved in this operation. 236 */ 237 ret = crtc->funcs->set_config(&set, ctx); 238 239 kfree(connector_list); 240 return ret; 241 } 242 EXPORT_SYMBOL(drm_plane_helper_update_primary); 243 244 /** 245 * drm_plane_helper_disable_primary - Helper for disabling primary planes 246 * @plane: plane to disable 247 * @ctx: modeset locking context 248 * 249 * This helper returns an error when trying to disable the primary 250 * plane. 251 * 252 * This function is only useful for non-atomic modesetting. Don't use 253 * it in new drivers. 254 * 255 * Returns: 256 * An errno code. 257 */ 258 int drm_plane_helper_disable_primary(struct drm_plane *plane, 259 struct drm_modeset_acquire_ctx *ctx) 260 { 261 struct drm_device *dev = plane->dev; 262 263 drm_WARN_ON_ONCE(dev, drm_drv_uses_atomic_modeset(dev)); 264 265 return -EINVAL; 266 } 267 EXPORT_SYMBOL(drm_plane_helper_disable_primary); 268 269 /** 270 * drm_plane_helper_destroy() - Helper for primary plane destruction 271 * @plane: plane to destroy 272 * 273 * Provides a default plane destroy handler for primary planes. This handler 274 * is called during CRTC destruction. We disable the primary plane, remove 275 * it from the DRM plane list, and deallocate the plane structure. 276 */ 277 void drm_plane_helper_destroy(struct drm_plane *plane) 278 { 279 drm_plane_cleanup(plane); 280 kfree(plane); 281 } 282 EXPORT_SYMBOL(drm_plane_helper_destroy); 283