brintos

brintos / linux-shallow public Read only

0
0
Text · 8.4 KiB · 7982be4 Raw
282 lines · c
1/*2 * Copyright (C) 2014 Intel Corporation3 *4 * DRM universal plane helper functions5 *6 * Permission is hereby granted, free of charge, to any person obtaining a7 * copy of this software and associated documentation files (the "Software"),8 * to deal in the Software without restriction, including without limitation9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,10 * and/or sell copies of the Software, and to permit persons to whom the11 * Software is furnished to do so, subject to the following conditions:12 *13 * The above copyright notice and this permission notice (including the next14 * paragraph) shall be included in all copies or substantial portions of the15 * Software.16 *17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER21 * 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 THE23 * SOFTWARE.24 */25 26#include <linux/list.h>27 28#include <drm/drm_atomic.h>29#include <drm/drm_atomic_helper.h>30#include <drm/drm_atomic_uapi.h>31#include <drm/drm_device.h>32#include <drm/drm_drv.h>33#include <drm/drm_encoder.h>34#include <drm/drm_plane_helper.h>35#include <drm/drm_print.h>36#include <drm/drm_rect.h>37 38#define SUBPIXEL_MASK 0xffff39 40/**41 * DOC: overview42 *43 * This helper library contains helpers to implement primary plane support on44 * top of the normal CRTC configuration interface.45 * Since the legacy &drm_mode_config_funcs.set_config interface ties the primary46 * plane together with the CRTC state this does not allow userspace to disable47 * the primary plane itself. The default primary plane only expose XRBG8888 and48 * ARGB8888 as valid pixel formats for the attached framebuffer.49 *50 * Drivers are highly recommended to implement proper support for primary51 * planes, and newly merged drivers must not rely upon these transitional52 * helpers.53 *54 * The plane helpers share the function table structures with other helpers,55 * specifically also the atomic helpers. See &struct drm_plane_helper_funcs for56 * the details.57 */58 59/*60 * Returns the connectors currently associated with a CRTC.  This function61 * should be called twice:  once with a NULL connector list to retrieve62 * the list size, and once with the properly allocated list to be filled in.63 */64static int get_connectors_for_crtc(struct drm_crtc *crtc,65				   struct drm_connector **connector_list,66				   int num_connectors)67{68	struct drm_device *dev = crtc->dev;69	struct drm_connector *connector;70	struct drm_connector_list_iter conn_iter;71	int count = 0;72 73	/*74	 * Note: Once we change the plane hooks to more fine-grained locking we75	 * need to grab the connection_mutex here to be able to make these76	 * checks.77	 */78	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));79 80	drm_connector_list_iter_begin(dev, &conn_iter);81	drm_for_each_connector_iter(connector, &conn_iter) {82		if (connector->encoder && connector->encoder->crtc == crtc) {83			if (connector_list != NULL && count < num_connectors)84				*(connector_list++) = connector;85 86			count++;87		}88	}89	drm_connector_list_iter_end(&conn_iter);90 91	return count;92}93 94static int drm_plane_helper_check_update(struct drm_plane *plane,95					 struct drm_crtc *crtc,96					 struct drm_framebuffer *fb,97					 struct drm_rect *src,98					 struct drm_rect *dst,99					 unsigned int rotation,100					 int min_scale,101					 int max_scale,102					 bool can_position,103					 bool can_update_disabled,104					 bool *visible)105{106	struct drm_plane_state plane_state = {107		.plane = plane,108		.crtc = crtc,109		.fb = fb,110		.src_x = src->x1,111		.src_y = src->y1,112		.src_w = drm_rect_width(src),113		.src_h = drm_rect_height(src),114		.crtc_x = dst->x1,115		.crtc_y = dst->y1,116		.crtc_w = drm_rect_width(dst),117		.crtc_h = drm_rect_height(dst),118		.rotation = rotation,119	};120	struct drm_crtc_state crtc_state = {121		.crtc = crtc,122		.enable = crtc->enabled,123		.mode = crtc->mode,124	};125	int ret;126 127	ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,128						  min_scale, max_scale,129						  can_position,130						  can_update_disabled);131	if (ret)132		return ret;133 134	*src = plane_state.src;135	*dst = plane_state.dst;136	*visible = plane_state.visible;137 138	return 0;139}140 141/**142 * drm_plane_helper_update_primary - Helper for updating primary planes143 * @plane: plane to update144 * @crtc: the plane's new CRTC145 * @fb: the plane's new framebuffer146 * @crtc_x: x coordinate within CRTC147 * @crtc_y: y coordinate within CRTC148 * @crtc_w: width coordinate within CRTC149 * @crtc_h: height coordinate within CRTC150 * @src_x: x coordinate within source151 * @src_y: y coordinate within source152 * @src_w: width coordinate within source153 * @src_h: height coordinate within source154 * @ctx: modeset locking context155 *156 * This helper validates the given parameters and updates the primary plane.157 *158 * This function is only useful for non-atomic modesetting. Don't use159 * it in new drivers.160 *161 * Returns:162 * Zero on success, or an errno code otherwise.163 */164int drm_plane_helper_update_primary(struct drm_plane *plane, struct drm_crtc *crtc,165				    struct drm_framebuffer *fb,166				    int crtc_x, int crtc_y,167				    unsigned int crtc_w, unsigned int crtc_h,168				    uint32_t src_x, uint32_t src_y,169				    uint32_t src_w, uint32_t src_h,170				    struct drm_modeset_acquire_ctx *ctx)171{172	struct drm_mode_set set = {173		.crtc = crtc,174		.fb = fb,175		.mode = &crtc->mode,176		.x = src_x >> 16,177		.y = src_y >> 16,178	};179	struct drm_rect src = {180		.x1 = src_x,181		.y1 = src_y,182		.x2 = src_x + src_w,183		.y2 = src_y + src_h,184	};185	struct drm_rect dest = {186		.x1 = crtc_x,187		.y1 = crtc_y,188		.x2 = crtc_x + crtc_w,189		.y2 = crtc_y + crtc_h,190	};191	struct drm_device *dev = plane->dev;192	struct drm_connector **connector_list;193	int num_connectors, ret;194	bool visible;195 196	if (drm_WARN_ON_ONCE(dev, drm_drv_uses_atomic_modeset(dev)))197		return -EINVAL;198 199	ret = drm_plane_helper_check_update(plane, crtc, fb,200					    &src, &dest,201					    DRM_MODE_ROTATE_0,202					    DRM_PLANE_NO_SCALING,203					    DRM_PLANE_NO_SCALING,204					    false, false, &visible);205	if (ret)206		return ret;207 208	if (!visible)209		/*210		 * Primary plane isn't visible.  Note that unless a driver211		 * provides their own disable function, this will just212		 * wind up returning -EINVAL to userspace.213		 */214		return plane->funcs->disable_plane(plane, ctx);215 216	/* Find current connectors for CRTC */217	num_connectors = get_connectors_for_crtc(crtc, NULL, 0);218	BUG_ON(num_connectors == 0);219	connector_list = kcalloc(num_connectors, sizeof(*connector_list),220				 GFP_KERNEL);221	if (!connector_list)222		return -ENOMEM;223	get_connectors_for_crtc(crtc, connector_list, num_connectors);224 225	set.connectors = connector_list;226	set.num_connectors = num_connectors;227 228	/*229	 * We call set_config() directly here rather than using230	 * drm_mode_set_config_internal.  We're reprogramming the same231	 * connectors that were already in use, so we shouldn't need the extra232	 * cross-CRTC fb refcounting to accommodate stealing connectors.233	 * drm_mode_setplane() already handles the basic refcounting for the234	 * framebuffers involved in this operation.235	 */236	ret = crtc->funcs->set_config(&set, ctx);237 238	kfree(connector_list);239	return ret;240}241EXPORT_SYMBOL(drm_plane_helper_update_primary);242 243/**244 * drm_plane_helper_disable_primary - Helper for disabling primary planes245 * @plane: plane to disable246 * @ctx: modeset locking context247 *248 * This helper returns an error when trying to disable the primary249 * plane.250 *251 * This function is only useful for non-atomic modesetting. Don't use252 * it in new drivers.253 *254 * Returns:255 * An errno code.256 */257int drm_plane_helper_disable_primary(struct drm_plane *plane,258				     struct drm_modeset_acquire_ctx *ctx)259{260	struct drm_device *dev = plane->dev;261 262	drm_WARN_ON_ONCE(dev, drm_drv_uses_atomic_modeset(dev));263 264	return -EINVAL;265}266EXPORT_SYMBOL(drm_plane_helper_disable_primary);267 268/**269 * drm_plane_helper_destroy() - Helper for primary plane destruction270 * @plane: plane to destroy271 *272 * Provides a default plane destroy handler for primary planes.  This handler273 * is called during CRTC destruction.  We disable the primary plane, remove274 * it from the DRM plane list, and deallocate the plane structure.275 */276void drm_plane_helper_destroy(struct drm_plane *plane)277{278	drm_plane_cleanup(plane);279	kfree(plane);280}281EXPORT_SYMBOL(drm_plane_helper_destroy);282