blob: 2d7bedf286473c20b0da3ba7bd5a3c945f0c7be6 [file] [log] [blame]
Dave Airlief453ba02008-11-07 14:05:41 -08001/*
2 * Copyright (c) 2006-2008 Intel Corporation
3 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
4 * Copyright (c) 2008 Red Hat Inc.
5 *
6 * DRM core CRTC related functions
7 *
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that copyright
11 * notice and this permission notice appear in supporting documentation, and
12 * that the name of the copyright holders not be used in advertising or
13 * publicity pertaining to distribution of the software without specific,
14 * written prior permission. The copyright holders make no representations
15 * about the suitability of this software for any purpose. It is provided "as
16 * is" without express or implied warranty.
17 *
18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * OF THIS SOFTWARE.
25 *
26 * Authors:
27 * Keith Packard
28 * Eric Anholt <eric@anholt.net>
29 * Dave Airlie <airlied@linux.ie>
30 * Jesse Barnes <jesse.barnes@intel.com>
31 */
Ville Syrjälä6ba6d032013-06-10 11:15:10 +030032#include <linux/ctype.h>
Dave Airlief453ba02008-11-07 14:05:41 -080033#include <linux/list.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090034#include <linux/slab.h>
Paul Gortmaker2d1a8a42011-08-30 18:16:33 -040035#include <linux/export.h>
David Howells760285e2012-10-02 18:01:07 +010036#include <drm/drmP.h>
37#include <drm/drm_crtc.h>
38#include <drm/drm_edid.h>
39#include <drm/drm_fourcc.h>
Rob Clark51fd3712013-11-19 12:10:12 -050040#include <drm/drm_modeset_lock.h>
Rob Clark88a48e22014-12-18 16:01:50 -050041#include <drm/drm_atomic.h>
Daniel Vetter3b96a0b2016-06-21 10:54:22 +020042#include <drm/drm_auth.h>
Daniel Vetter7520a272016-08-15 16:07:02 +020043#include <drm/drm_framebuffer.h>
Dave Airlief453ba02008-11-07 14:05:41 -080044
Daniel Vetter8bd441b2014-01-23 15:35:24 +010045#include "drm_crtc_internal.h"
Daniel Vetter67d0ec42014-09-10 12:43:53 +020046#include "drm_internal.h"
Daniel Vetter8bd441b2014-01-23 15:35:24 +010047
Dave Airlief453ba02008-11-07 14:05:41 -080048/*
49 * Global properties
50 */
Thierry Reding4dfd9092014-12-10 13:03:34 +010051static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
Rob Clark9922ab52014-04-01 20:16:57 -040052 { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
53 { DRM_PLANE_TYPE_PRIMARY, "Primary" },
54 { DRM_PLANE_TYPE_CURSOR, "Cursor" },
55};
56
Daniel Vetter52217192016-08-12 22:48:50 +020057/*
58 * Optional properties
Daniel Vetterc8e32cc2014-03-10 21:33:02 +010059 */
Lukas Wunner6a0d9522016-06-08 18:47:27 +020060/**
61 * drm_crtc_force_disable - Forcibly turn off a CRTC
62 * @crtc: CRTC to turn off
63 *
64 * Returns:
65 * Zero on success, error code on failure.
66 */
67int drm_crtc_force_disable(struct drm_crtc *crtc)
68{
69 struct drm_mode_set set = {
70 .crtc = crtc,
71 };
72
73 return drm_mode_set_config_internal(&set);
74}
75EXPORT_SYMBOL(drm_crtc_force_disable);
76
77/**
78 * drm_crtc_force_disable_all - Forcibly turn off all enabled CRTCs
79 * @dev: DRM device whose CRTCs to turn off
80 *
81 * Drivers may want to call this on unload to ensure that all displays are
82 * unlit and the GPU is in a consistent, low power state. Takes modeset locks.
83 *
84 * Returns:
85 * Zero on success, error code on failure.
86 */
87int drm_crtc_force_disable_all(struct drm_device *dev)
88{
89 struct drm_crtc *crtc;
90 int ret = 0;
91
92 drm_modeset_lock_all(dev);
93 drm_for_each_crtc(crtc, dev)
94 if (crtc->enabled) {
95 ret = drm_crtc_force_disable(crtc);
96 if (ret)
97 goto out;
98 }
99out:
100 drm_modeset_unlock_all(dev);
101 return ret;
102}
103EXPORT_SYMBOL(drm_crtc_force_disable_all);
104
Rob Clark51fd3712013-11-19 12:10:12 -0500105DEFINE_WW_CLASS(crtc_ww_class);
106
Ville Syrjäläfa3ab4c2015-12-08 18:41:53 +0200107static unsigned int drm_num_crtcs(struct drm_device *dev)
108{
109 unsigned int num = 0;
110 struct drm_crtc *tmp;
111
112 drm_for_each_crtc(tmp, dev) {
113 num++;
114 }
115
116 return num;
117}
118
Benjamin Gaignard79190ea2016-06-21 16:37:09 +0200119static int drm_crtc_register_all(struct drm_device *dev)
120{
121 struct drm_crtc *crtc;
122 int ret = 0;
123
124 drm_for_each_crtc(crtc, dev) {
125 if (crtc->funcs->late_register)
126 ret = crtc->funcs->late_register(crtc);
127 if (ret)
128 return ret;
129 }
130
131 return 0;
132}
133
134static void drm_crtc_unregister_all(struct drm_device *dev)
135{
136 struct drm_crtc *crtc;
137
138 drm_for_each_crtc(crtc, dev) {
139 if (crtc->funcs->early_unregister)
140 crtc->funcs->early_unregister(crtc);
141 }
142}
143
Dave Airlief453ba02008-11-07 14:05:41 -0800144/**
Matt Ropere13161a2014-04-01 15:22:38 -0700145 * drm_crtc_init_with_planes - Initialise a new CRTC object with
146 * specified primary and cursor planes.
Dave Airlief453ba02008-11-07 14:05:41 -0800147 * @dev: DRM device
148 * @crtc: CRTC object to init
Matt Ropere13161a2014-04-01 15:22:38 -0700149 * @primary: Primary plane for CRTC
150 * @cursor: Cursor plane for CRTC
Dave Airlief453ba02008-11-07 14:05:41 -0800151 * @funcs: callbacks for the new CRTC
Ville Syrjäläf9882872015-12-09 16:19:31 +0200152 * @name: printf style format string for the CRTC name, or NULL for default name
Dave Airlief453ba02008-11-07 14:05:41 -0800153 *
Daniel Vetter532b3672016-09-21 10:59:25 +0200154 * Inits a new object created as base part of a driver crtc object. Drivers
155 * should use this function instead of drm_crtc_init(), which is only provided
156 * for backwards compatibility with drivers which do not yet support universal
157 * planes). For really simple hardware which has only 1 plane look at
158 * drm_simple_display_pipe_init() instead.
Ville Syrjälä6bfc56a2012-03-13 12:35:48 +0200159 *
Daniel Vetterc8e32cc2014-03-10 21:33:02 +0100160 * Returns:
Ville Syrjälä6bfc56a2012-03-13 12:35:48 +0200161 * Zero on success, error code on failure.
Dave Airlief453ba02008-11-07 14:05:41 -0800162 */
Matt Ropere13161a2014-04-01 15:22:38 -0700163int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
164 struct drm_plane *primary,
Matt Roperfc1d3e42014-06-10 08:28:11 -0700165 struct drm_plane *cursor,
Ville Syrjäläf9882872015-12-09 16:19:31 +0200166 const struct drm_crtc_funcs *funcs,
167 const char *name, ...)
Dave Airlief453ba02008-11-07 14:05:41 -0800168{
Rob Clark51fd3712013-11-19 12:10:12 -0500169 struct drm_mode_config *config = &dev->mode_config;
Ville Syrjälä6bfc56a2012-03-13 12:35:48 +0200170 int ret;
171
Benjamin Gaignard522cf912015-03-17 12:05:29 +0100172 WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY);
173 WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR);
174
Dave Airlief453ba02008-11-07 14:05:41 -0800175 crtc->dev = dev;
176 crtc->funcs = funcs;
177
Daniel Vetter3b24f7d2016-06-08 14:19:00 +0200178 INIT_LIST_HEAD(&crtc->commit_list);
179 spin_lock_init(&crtc->commit_lock);
180
Rob Clark51fd3712013-11-19 12:10:12 -0500181 drm_modeset_lock_init(&crtc->mutex);
Ville Syrjälä6bfc56a2012-03-13 12:35:48 +0200182 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
183 if (ret)
Daniel Vetterbaf698b2014-11-12 11:59:47 +0100184 return ret;
Dave Airlief453ba02008-11-07 14:05:41 -0800185
Ville Syrjäläfa3ab4c2015-12-08 18:41:53 +0200186 if (name) {
187 va_list ap;
188
189 va_start(ap, name);
190 crtc->name = kvasprintf(GFP_KERNEL, name, ap);
191 va_end(ap);
192 } else {
193 crtc->name = kasprintf(GFP_KERNEL, "crtc-%d",
194 drm_num_crtcs(dev));
195 }
196 if (!crtc->name) {
Dave Airlie7c8f6d22016-04-15 15:10:32 +1000197 drm_mode_object_unregister(dev, &crtc->base);
Ville Syrjäläfa3ab4c2015-12-08 18:41:53 +0200198 return -ENOMEM;
199 }
200
Paulo Zanonibffd9de02012-05-15 18:09:05 -0300201 crtc->base.properties = &crtc->properties;
202
Rob Clark51fd3712013-11-19 12:10:12 -0500203 list_add_tail(&crtc->head, &config->crtc_list);
Chris Wilson490d3d12016-05-27 20:05:00 +0100204 crtc->index = config->num_crtc++;
Ville Syrjälä6bfc56a2012-03-13 12:35:48 +0200205
Matt Ropere13161a2014-04-01 15:22:38 -0700206 crtc->primary = primary;
Matt Roperfc1d3e42014-06-10 08:28:11 -0700207 crtc->cursor = cursor;
Matt Ropere13161a2014-04-01 15:22:38 -0700208 if (primary)
209 primary->possible_crtcs = 1 << drm_crtc_index(crtc);
Matt Roperfc1d3e42014-06-10 08:28:11 -0700210 if (cursor)
211 cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
Matt Ropere13161a2014-04-01 15:22:38 -0700212
Daniel Vettereab3bbe2015-01-22 16:36:21 +0100213 if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
214 drm_object_attach_property(&crtc->base, config->prop_active, 0);
Daniel Stone955f3c32015-05-25 19:11:52 +0100215 drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
Daniel Vettereab3bbe2015-01-22 16:36:21 +0100216 }
217
Daniel Vetterbaf698b2014-11-12 11:59:47 +0100218 return 0;
Dave Airlief453ba02008-11-07 14:05:41 -0800219}
Matt Ropere13161a2014-04-01 15:22:38 -0700220EXPORT_SYMBOL(drm_crtc_init_with_planes);
Dave Airlief453ba02008-11-07 14:05:41 -0800221
222/**
Ville Syrjäläad6f5c32013-06-05 12:39:55 +0000223 * drm_crtc_cleanup - Clean up the core crtc usage
Dave Airlief453ba02008-11-07 14:05:41 -0800224 * @crtc: CRTC to cleanup
225 *
Ville Syrjäläad6f5c32013-06-05 12:39:55 +0000226 * This function cleans up @crtc and removes it from the DRM mode setting
227 * core. Note that the function does *not* free the crtc structure itself,
228 * this is the responsibility of the caller.
Dave Airlief453ba02008-11-07 14:05:41 -0800229 */
230void drm_crtc_cleanup(struct drm_crtc *crtc)
231{
232 struct drm_device *dev = crtc->dev;
233
Chris Wilson490d3d12016-05-27 20:05:00 +0100234 /* Note that the crtc_list is considered to be static; should we
235 * remove the drm_crtc at runtime we would have to decrement all
236 * the indices on the drm_crtc after us in the crtc_list.
237 */
238
Sachin Kamat9e1c1562012-11-19 09:44:56 +0000239 kfree(crtc->gamma_store);
240 crtc->gamma_store = NULL;
Dave Airlief453ba02008-11-07 14:05:41 -0800241
Rob Clark51fd3712013-11-19 12:10:12 -0500242 drm_modeset_lock_fini(&crtc->mutex);
243
Dave Airlie7c8f6d22016-04-15 15:10:32 +1000244 drm_mode_object_unregister(dev, &crtc->base);
Dave Airlief453ba02008-11-07 14:05:41 -0800245 list_del(&crtc->head);
246 dev->mode_config.num_crtc--;
Thierry Reding3009c032014-11-25 12:09:49 +0100247
248 WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state);
249 if (crtc->state && crtc->funcs->atomic_destroy_state)
250 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
Thierry Redinga18c0af2014-12-10 11:38:49 +0100251
Ville Syrjäläfa3ab4c2015-12-08 18:41:53 +0200252 kfree(crtc->name);
253
Thierry Redinga18c0af2014-12-10 11:38:49 +0100254 memset(crtc, 0, sizeof(*crtc));
Dave Airlief453ba02008-11-07 14:05:41 -0800255}
256EXPORT_SYMBOL(drm_crtc_cleanup);
257
Benjamin Gaignard79190ea2016-06-21 16:37:09 +0200258int drm_modeset_register_all(struct drm_device *dev)
259{
260 int ret;
261
262 ret = drm_plane_register_all(dev);
263 if (ret)
264 goto err_plane;
265
266 ret = drm_crtc_register_all(dev);
267 if (ret)
268 goto err_crtc;
269
270 ret = drm_encoder_register_all(dev);
271 if (ret)
272 goto err_encoder;
273
274 ret = drm_connector_register_all(dev);
275 if (ret)
276 goto err_connector;
277
278 return 0;
279
280err_connector:
281 drm_encoder_unregister_all(dev);
282err_encoder:
283 drm_crtc_unregister_all(dev);
284err_crtc:
285 drm_plane_unregister_all(dev);
286err_plane:
287 return ret;
288}
289
290void drm_modeset_unregister_all(struct drm_device *dev)
291{
292 drm_connector_unregister_all(dev);
293 drm_encoder_unregister_all(dev);
294 drm_crtc_unregister_all(dev);
295 drm_plane_unregister_all(dev);
296}
297
Rob Clark6b4959f2014-12-18 16:01:53 -0500298static int drm_mode_create_standard_properties(struct drm_device *dev)
Dave Airlief453ba02008-11-07 14:05:41 -0800299{
Rob Clark356af0e2014-12-18 16:01:52 -0500300 struct drm_property *prop;
Daniel Vetter52217192016-08-12 22:48:50 +0200301 int ret;
Dave Airlief453ba02008-11-07 14:05:41 -0800302
Daniel Vetter52217192016-08-12 22:48:50 +0200303 ret = drm_connector_create_standard_properties(dev);
304 if (ret)
305 return ret;
Dave Airlie6f134d72014-10-20 16:30:50 +1000306
Rob Clark6b4959f2014-12-18 16:01:53 -0500307 prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
Rob Clark9922ab52014-04-01 20:16:57 -0400308 "type", drm_plane_type_enum_list,
309 ARRAY_SIZE(drm_plane_type_enum_list));
Rob Clark6b4959f2014-12-18 16:01:53 -0500310 if (!prop)
311 return -ENOMEM;
312 dev->mode_config.plane_type_property = prop;
313
314 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
315 "SRC_X", 0, UINT_MAX);
316 if (!prop)
317 return -ENOMEM;
318 dev->mode_config.prop_src_x = prop;
319
320 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
321 "SRC_Y", 0, UINT_MAX);
322 if (!prop)
323 return -ENOMEM;
324 dev->mode_config.prop_src_y = prop;
325
326 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
327 "SRC_W", 0, UINT_MAX);
328 if (!prop)
329 return -ENOMEM;
330 dev->mode_config.prop_src_w = prop;
331
332 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
333 "SRC_H", 0, UINT_MAX);
334 if (!prop)
335 return -ENOMEM;
336 dev->mode_config.prop_src_h = prop;
337
338 prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
339 "CRTC_X", INT_MIN, INT_MAX);
340 if (!prop)
341 return -ENOMEM;
342 dev->mode_config.prop_crtc_x = prop;
343
344 prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
345 "CRTC_Y", INT_MIN, INT_MAX);
346 if (!prop)
347 return -ENOMEM;
348 dev->mode_config.prop_crtc_y = prop;
349
350 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
351 "CRTC_W", 0, INT_MAX);
352 if (!prop)
353 return -ENOMEM;
354 dev->mode_config.prop_crtc_w = prop;
355
356 prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
357 "CRTC_H", 0, INT_MAX);
358 if (!prop)
359 return -ENOMEM;
360 dev->mode_config.prop_crtc_h = prop;
361
362 prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
363 "FB_ID", DRM_MODE_OBJECT_FB);
364 if (!prop)
365 return -ENOMEM;
366 dev->mode_config.prop_fb_id = prop;
367
368 prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
369 "CRTC_ID", DRM_MODE_OBJECT_CRTC);
370 if (!prop)
371 return -ENOMEM;
372 dev->mode_config.prop_crtc_id = prop;
Rob Clark9922ab52014-04-01 20:16:57 -0400373
Daniel Vettereab3bbe2015-01-22 16:36:21 +0100374 prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
375 "ACTIVE");
376 if (!prop)
377 return -ENOMEM;
378 dev->mode_config.prop_active = prop;
379
Daniel Stone955f3c32015-05-25 19:11:52 +0100380 prop = drm_property_create(dev,
381 DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
382 "MODE_ID", 0);
383 if (!prop)
384 return -ENOMEM;
385 dev->mode_config.prop_mode_id = prop;
386
Lionel Landwerlin5488dc12016-02-26 17:05:00 +0000387 prop = drm_property_create(dev,
388 DRM_MODE_PROP_BLOB,
389 "DEGAMMA_LUT", 0);
390 if (!prop)
391 return -ENOMEM;
392 dev->mode_config.degamma_lut_property = prop;
393
394 prop = drm_property_create_range(dev,
395 DRM_MODE_PROP_IMMUTABLE,
396 "DEGAMMA_LUT_SIZE", 0, UINT_MAX);
397 if (!prop)
398 return -ENOMEM;
399 dev->mode_config.degamma_lut_size_property = prop;
400
401 prop = drm_property_create(dev,
402 DRM_MODE_PROP_BLOB,
403 "CTM", 0);
404 if (!prop)
405 return -ENOMEM;
406 dev->mode_config.ctm_property = prop;
407
408 prop = drm_property_create(dev,
409 DRM_MODE_PROP_BLOB,
410 "GAMMA_LUT", 0);
411 if (!prop)
412 return -ENOMEM;
413 dev->mode_config.gamma_lut_property = prop;
414
415 prop = drm_property_create_range(dev,
416 DRM_MODE_PROP_IMMUTABLE,
417 "GAMMA_LUT_SIZE", 0, UINT_MAX);
418 if (!prop)
419 return -ENOMEM;
420 dev->mode_config.gamma_lut_size_property = prop;
421
Rob Clark9922ab52014-04-01 20:16:57 -0400422 return 0;
423}
424
Dave Airlief453ba02008-11-07 14:05:41 -0800425/**
Dave Airlief453ba02008-11-07 14:05:41 -0800426 * drm_mode_getresources - get graphics configuration
Daniel Vetter065a50ed2012-12-02 00:09:18 +0100427 * @dev: drm device for the ioctl
428 * @data: data pointer for the ioctl
429 * @file_priv: drm file for the ioctl call
Dave Airlief453ba02008-11-07 14:05:41 -0800430 *
Dave Airlief453ba02008-11-07 14:05:41 -0800431 * Construct a set of configuration description structures and return
432 * them to the user, including CRTC, connector and framebuffer configuration.
433 *
434 * Called by the user via ioctl.
435 *
Daniel Vetterc8e32cc2014-03-10 21:33:02 +0100436 * Returns:
Daniel Vetter1a498632014-11-19 18:38:09 +0100437 * Zero on success, negative errno on failure.
Dave Airlief453ba02008-11-07 14:05:41 -0800438 */
439int drm_mode_getresources(struct drm_device *dev, void *data,
440 struct drm_file *file_priv)
441{
442 struct drm_mode_card_res *card_res = data;
443 struct list_head *lh;
444 struct drm_framebuffer *fb;
445 struct drm_connector *connector;
446 struct drm_crtc *crtc;
447 struct drm_encoder *encoder;
448 int ret = 0;
449 int connector_count = 0;
450 int crtc_count = 0;
451 int fb_count = 0;
452 int encoder_count = 0;
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200453 int copied = 0;
Dave Airlief453ba02008-11-07 14:05:41 -0800454 uint32_t __user *fb_id;
455 uint32_t __user *crtc_id;
456 uint32_t __user *connector_id;
457 uint32_t __user *encoder_id;
Dave Airlief453ba02008-11-07 14:05:41 -0800458
Dave Airliefb3b06c2011-02-08 13:55:21 +1000459 if (!drm_core_check_feature(dev, DRIVER_MODESET))
460 return -EINVAL;
461
Dave Airlief453ba02008-11-07 14:05:41 -0800462
Daniel Vetter4b096ac2012-12-10 21:19:18 +0100463 mutex_lock(&file_priv->fbs_lock);
Dave Airlief453ba02008-11-07 14:05:41 -0800464 /*
465 * For the non-control nodes we need to limit the list of resources
466 * by IDs in the group list for this node
467 */
468 list_for_each(lh, &file_priv->fbs)
469 fb_count++;
470
Daniel Vetter4b096ac2012-12-10 21:19:18 +0100471 /* handle this in 4 parts */
472 /* FBs */
473 if (card_res->count_fbs >= fb_count) {
474 copied = 0;
475 fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
476 list_for_each_entry(fb, &file_priv->fbs, filp_head) {
477 if (put_user(fb->base.id, fb_id + copied)) {
478 mutex_unlock(&file_priv->fbs_lock);
479 return -EFAULT;
480 }
481 copied++;
482 }
483 }
484 card_res->count_fbs = fb_count;
485 mutex_unlock(&file_priv->fbs_lock);
486
Daniel Vetterfcf93f62014-11-12 08:45:01 +0100487 /* mode_config.mutex protects the connector list against e.g. DP MST
488 * connector hot-adding. CRTC/Plane lists are invariant. */
489 mutex_lock(&dev->mode_config.mutex);
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200490 drm_for_each_crtc(crtc, dev)
491 crtc_count++;
Dave Airlief453ba02008-11-07 14:05:41 -0800492
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200493 drm_for_each_connector(connector, dev)
494 connector_count++;
Dave Airlief453ba02008-11-07 14:05:41 -0800495
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200496 drm_for_each_encoder(encoder, dev)
497 encoder_count++;
Dave Airlief453ba02008-11-07 14:05:41 -0800498
499 card_res->max_height = dev->mode_config.max_height;
500 card_res->min_height = dev->mode_config.min_height;
501 card_res->max_width = dev->mode_config.max_width;
502 card_res->min_width = dev->mode_config.min_width;
503
Dave Airlief453ba02008-11-07 14:05:41 -0800504 /* CRTCs */
505 if (card_res->count_crtcs >= crtc_count) {
506 copied = 0;
507 crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200508 drm_for_each_crtc(crtc, dev) {
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200509 if (put_user(crtc->base.id, crtc_id + copied)) {
510 ret = -EFAULT;
511 goto out;
Dave Airlief453ba02008-11-07 14:05:41 -0800512 }
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200513 copied++;
Dave Airlief453ba02008-11-07 14:05:41 -0800514 }
515 }
516 card_res->count_crtcs = crtc_count;
517
518 /* Encoders */
519 if (card_res->count_encoders >= encoder_count) {
520 copied = 0;
521 encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200522 drm_for_each_encoder(encoder, dev) {
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200523 if (put_user(encoder->base.id, encoder_id +
524 copied)) {
525 ret = -EFAULT;
526 goto out;
Dave Airlief453ba02008-11-07 14:05:41 -0800527 }
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200528 copied++;
Dave Airlief453ba02008-11-07 14:05:41 -0800529 }
530 }
531 card_res->count_encoders = encoder_count;
532
533 /* Connectors */
534 if (card_res->count_connectors >= connector_count) {
535 copied = 0;
536 connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200537 drm_for_each_connector(connector, dev) {
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200538 if (put_user(connector->base.id,
539 connector_id + copied)) {
540 ret = -EFAULT;
541 goto out;
Dave Airlief453ba02008-11-07 14:05:41 -0800542 }
Daniel Vetter9c7060f2015-07-09 23:44:36 +0200543 copied++;
Dave Airlief453ba02008-11-07 14:05:41 -0800544 }
545 }
546 card_res->count_connectors = connector_count;
547
Dave Airlief453ba02008-11-07 14:05:41 -0800548out:
Daniel Vetterfcf93f62014-11-12 08:45:01 +0100549 mutex_unlock(&dev->mode_config.mutex);
Dave Airlief453ba02008-11-07 14:05:41 -0800550 return ret;
551}
552
553/**
554 * drm_mode_getcrtc - get CRTC configuration
Daniel Vetter065a50ed2012-12-02 00:09:18 +0100555 * @dev: drm device for the ioctl
556 * @data: data pointer for the ioctl
557 * @file_priv: drm file for the ioctl call
Dave Airlief453ba02008-11-07 14:05:41 -0800558 *
Dave Airlief453ba02008-11-07 14:05:41 -0800559 * Construct a CRTC configuration structure to return to the user.
560 *
561 * Called by the user via ioctl.
562 *
Daniel Vetterc8e32cc2014-03-10 21:33:02 +0100563 * Returns:
Daniel Vetter1a498632014-11-19 18:38:09 +0100564 * Zero on success, negative errno on failure.
Dave Airlief453ba02008-11-07 14:05:41 -0800565 */
566int drm_mode_getcrtc(struct drm_device *dev,
567 void *data, struct drm_file *file_priv)
568{
569 struct drm_mode_crtc *crtc_resp = data;
570 struct drm_crtc *crtc;
Dave Airlief453ba02008-11-07 14:05:41 -0800571
Dave Airliefb3b06c2011-02-08 13:55:21 +1000572 if (!drm_core_check_feature(dev, DRIVER_MODESET))
573 return -EINVAL;
574
Rob Clarka2b34e22013-10-05 16:36:52 -0400575 crtc = drm_crtc_find(dev, crtc_resp->crtc_id);
Daniel Vetterfcf93f62014-11-12 08:45:01 +0100576 if (!crtc)
577 return -ENOENT;
Dave Airlief453ba02008-11-07 14:05:41 -0800578
Daniel Vetterfcf93f62014-11-12 08:45:01 +0100579 drm_modeset_lock_crtc(crtc, crtc->primary);
Dave Airlief453ba02008-11-07 14:05:41 -0800580 crtc_resp->gamma_size = crtc->gamma_size;
Matt Roperf4510a22014-04-01 15:22:40 -0700581 if (crtc->primary->fb)
582 crtc_resp->fb_id = crtc->primary->fb->base.id;
Dave Airlief453ba02008-11-07 14:05:41 -0800583 else
584 crtc_resp->fb_id = 0;
585
Daniel Vetter31c946e2015-02-22 12:24:17 +0100586 if (crtc->state) {
587 crtc_resp->x = crtc->primary->state->src_x >> 16;
588 crtc_resp->y = crtc->primary->state->src_y >> 16;
589 if (crtc->state->enable) {
Daniel Stone934a8a82015-05-22 13:34:48 +0100590 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
Daniel Vetter31c946e2015-02-22 12:24:17 +0100591 crtc_resp->mode_valid = 1;
Dave Airlief453ba02008-11-07 14:05:41 -0800592
Daniel Vetter31c946e2015-02-22 12:24:17 +0100593 } else {
594 crtc_resp->mode_valid = 0;
595 }
Dave Airlief453ba02008-11-07 14:05:41 -0800596 } else {
Daniel Vetter31c946e2015-02-22 12:24:17 +0100597 crtc_resp->x = crtc->x;
598 crtc_resp->y = crtc->y;
599 if (crtc->enabled) {
Daniel Stone934a8a82015-05-22 13:34:48 +0100600 drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode);
Daniel Vetter31c946e2015-02-22 12:24:17 +0100601 crtc_resp->mode_valid = 1;
602
603 } else {
604 crtc_resp->mode_valid = 0;
605 }
Dave Airlief453ba02008-11-07 14:05:41 -0800606 }
Daniel Vetterfcf93f62014-11-12 08:45:01 +0100607 drm_modeset_unlock_crtc(crtc);
Dave Airlief453ba02008-11-07 14:05:41 -0800608
Daniel Vetterbaf698b2014-11-12 11:59:47 +0100609 return 0;
Dave Airlief453ba02008-11-07 14:05:41 -0800610}
611
Dave Airlief453ba02008-11-07 14:05:41 -0800612/**
Daniel Vetter2d13b672012-12-11 13:47:23 +0100613 * drm_mode_set_config_internal - helper to call ->set_config
614 * @set: modeset config to set
615 *
616 * This is a little helper to wrap internal calls to the ->set_config driver
617 * interface. The only thing it adds is correct refcounting dance.
Thierry Reding4dfd9092014-12-10 13:03:34 +0100618 *
Daniel Vetterc8e32cc2014-03-10 21:33:02 +0100619 * Returns:
Daniel Vetter1a498632014-11-19 18:38:09 +0100620 * Zero on success, negative errno on failure.
Daniel Vetter2d13b672012-12-11 13:47:23 +0100621 */
622int drm_mode_set_config_internal(struct drm_mode_set *set)
623{
624 struct drm_crtc *crtc = set->crtc;
Daniel Vetter5cef29a2013-06-15 00:13:16 +0200625 struct drm_framebuffer *fb;
626 struct drm_crtc *tmp;
Daniel Vetterb0d12322012-12-11 01:07:12 +0100627 int ret;
Daniel Vetter2d13b672012-12-11 13:47:23 +0100628
Daniel Vetter5cef29a2013-06-15 00:13:16 +0200629 /*
630 * NOTE: ->set_config can also disable other crtcs (if we steal all
631 * connectors from it), hence we need to refcount the fbs across all
632 * crtcs. Atomic modeset will have saner semantics ...
633 */
Daniel Vettere4f62542015-07-09 23:44:35 +0200634 drm_for_each_crtc(tmp, crtc->dev)
Daniel Vetter3d30a592014-07-27 13:42:42 +0200635 tmp->primary->old_fb = tmp->primary->fb;
Daniel Vetter5cef29a2013-06-15 00:13:16 +0200636
Daniel Vetterb0d12322012-12-11 01:07:12 +0100637 fb = set->fb;
638
639 ret = crtc->funcs->set_config(set);
640 if (ret == 0) {
Matt Ropere13161a2014-04-01 15:22:38 -0700641 crtc->primary->crtc = crtc;
Daniel Vetter0fe27f02014-04-23 17:34:06 +0200642 crtc->primary->fb = fb;
Daniel Vetter5cef29a2013-06-15 00:13:16 +0200643 }
Daniel Vettercc85e122013-06-15 00:13:15 +0200644
Daniel Vettere4f62542015-07-09 23:44:35 +0200645 drm_for_each_crtc(tmp, crtc->dev) {
Matt Roperf4510a22014-04-01 15:22:40 -0700646 if (tmp->primary->fb)
647 drm_framebuffer_reference(tmp->primary->fb);
Daniel Vetter3d30a592014-07-27 13:42:42 +0200648 if (tmp->primary->old_fb)
649 drm_framebuffer_unreference(tmp->primary->old_fb);
650 tmp->primary->old_fb = NULL;
Daniel Vetterb0d12322012-12-11 01:07:12 +0100651 }
652
653 return ret;
Daniel Vetter2d13b672012-12-11 13:47:23 +0100654}
655EXPORT_SYMBOL(drm_mode_set_config_internal);
656
Matt Roperaf936292014-04-01 15:22:34 -0700657/**
Gustavo Padovanecb7e162014-12-01 15:40:09 -0800658 * drm_crtc_get_hv_timing - Fetches hdisplay/vdisplay for given mode
659 * @mode: mode to query
660 * @hdisplay: hdisplay value to fill in
661 * @vdisplay: vdisplay value to fill in
662 *
663 * The vdisplay value will be doubled if the specified mode is a stereo mode of
664 * the appropriate layout.
665 */
666void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
667 int *hdisplay, int *vdisplay)
668{
669 struct drm_display_mode adjusted;
670
671 drm_mode_copy(&adjusted, mode);
672 drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
673 *hdisplay = adjusted.crtc_hdisplay;
674 *vdisplay = adjusted.crtc_vdisplay;
675}
676EXPORT_SYMBOL(drm_crtc_get_hv_timing);
677
678/**
Matt Roperaf936292014-04-01 15:22:34 -0700679 * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
680 * CRTC viewport
681 * @crtc: CRTC that framebuffer will be displayed on
682 * @x: x panning
683 * @y: y panning
684 * @mode: mode that framebuffer will be displayed under
685 * @fb: framebuffer to check size of
Damien Lespiauc11e9282013-09-25 16:45:30 +0100686 */
Matt Roperaf936292014-04-01 15:22:34 -0700687int drm_crtc_check_viewport(const struct drm_crtc *crtc,
688 int x, int y,
689 const struct drm_display_mode *mode,
690 const struct drm_framebuffer *fb)
Damien Lespiauc11e9282013-09-25 16:45:30 +0100691
692{
693 int hdisplay, vdisplay;
694
Gustavo Padovanecb7e162014-12-01 15:40:09 -0800695 drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
Damien Lespiaua0c1bbb2013-09-25 16:45:31 +0100696
Ville Syrjälä33e0be62015-10-16 18:38:39 +0300697 if (crtc->state &&
Joonas Lahtinen31ad61e2016-07-29 08:50:05 +0300698 crtc->primary->state->rotation & (DRM_ROTATE_90 |
699 DRM_ROTATE_270))
Damien Lespiauc11e9282013-09-25 16:45:30 +0100700 swap(hdisplay, vdisplay);
701
Daniel Vetter43968d72016-09-21 10:59:24 +0200702 return drm_framebuffer_check_src_coords(x << 16, y << 16,
703 hdisplay << 16, vdisplay << 16,
704 fb);
Damien Lespiauc11e9282013-09-25 16:45:30 +0100705}
Matt Roperaf936292014-04-01 15:22:34 -0700706EXPORT_SYMBOL(drm_crtc_check_viewport);
Damien Lespiauc11e9282013-09-25 16:45:30 +0100707
Daniel Vetter2d13b672012-12-11 13:47:23 +0100708/**
Dave Airlief453ba02008-11-07 14:05:41 -0800709 * drm_mode_setcrtc - set CRTC configuration
Daniel Vetter065a50ed2012-12-02 00:09:18 +0100710 * @dev: drm device for the ioctl
711 * @data: data pointer for the ioctl
712 * @file_priv: drm file for the ioctl call
Dave Airlief453ba02008-11-07 14:05:41 -0800713 *
Dave Airlief453ba02008-11-07 14:05:41 -0800714 * Build a new CRTC configuration based on user request.
715 *
716 * Called by the user via ioctl.
717 *
Daniel Vetterc8e32cc2014-03-10 21:33:02 +0100718 * Returns:
Daniel Vetter1a498632014-11-19 18:38:09 +0100719 * Zero on success, negative errno on failure.
Dave Airlief453ba02008-11-07 14:05:41 -0800720 */
721int drm_mode_setcrtc(struct drm_device *dev, void *data,
722 struct drm_file *file_priv)
723{
724 struct drm_mode_config *config = &dev->mode_config;
725 struct drm_mode_crtc *crtc_req = data;
Ville Syrjälä6653cc82012-03-13 12:35:38 +0200726 struct drm_crtc *crtc;
Dave Airlief453ba02008-11-07 14:05:41 -0800727 struct drm_connector **connector_set = NULL, *connector;
728 struct drm_framebuffer *fb = NULL;
729 struct drm_display_mode *mode = NULL;
730 struct drm_mode_set set;
731 uint32_t __user *set_connectors_ptr;
Laurent Pinchart4a1b0712012-05-17 13:27:21 +0200732 int ret;
Dave Airlief453ba02008-11-07 14:05:41 -0800733 int i;
734
Dave Airliefb3b06c2011-02-08 13:55:21 +1000735 if (!drm_core_check_feature(dev, DRIVER_MODESET))
736 return -EINVAL;
737
Zhao Junwang01447e92015-07-07 17:08:35 +0800738 /*
739 * Universal plane src offsets are only 16.16, prevent havoc for
740 * drivers using universal plane code internally.
741 */
742 if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
Ville Syrjälä1d97e912012-03-13 12:35:41 +0200743 return -ERANGE;
744
Daniel Vetter84849902012-12-02 00:28:11 +0100745 drm_modeset_lock_all(dev);
Rob Clarka2b34e22013-10-05 16:36:52 -0400746 crtc = drm_crtc_find(dev, crtc_req->crtc_id);
747 if (!crtc) {
Zhao Yakui58367ed2009-07-20 13:48:07 +0800748 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
Ville Syrjäläf27657f2013-10-17 13:35:00 +0300749 ret = -ENOENT;
Dave Airlief453ba02008-11-07 14:05:41 -0800750 goto out;
751 }
Ville Syrjäläfa3ab4c2015-12-08 18:41:53 +0200752 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
Dave Airlief453ba02008-11-07 14:05:41 -0800753
754 if (crtc_req->mode_valid) {
755 /* If we have a mode we need a framebuffer. */
756 /* If we pass -1, set the mode with the currently bound fb */
757 if (crtc_req->fb_id == -1) {
Matt Roperf4510a22014-04-01 15:22:40 -0700758 if (!crtc->primary->fb) {
Ville Syrjälä6653cc82012-03-13 12:35:38 +0200759 DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
760 ret = -EINVAL;
761 goto out;
Dave Airlief453ba02008-11-07 14:05:41 -0800762 }
Matt Roperf4510a22014-04-01 15:22:40 -0700763 fb = crtc->primary->fb;
Daniel Vetterb0d12322012-12-11 01:07:12 +0100764 /* Make refcounting symmetric with the lookup path. */
765 drm_framebuffer_reference(fb);
Dave Airlief453ba02008-11-07 14:05:41 -0800766 } else {
Daniel Vetter786b99e2012-12-02 21:53:40 +0100767 fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
768 if (!fb) {
Zhao Yakui58367ed2009-07-20 13:48:07 +0800769 DRM_DEBUG_KMS("Unknown FB ID%d\n",
770 crtc_req->fb_id);
Ville Syrjälä37c4e702013-10-17 13:35:01 +0300771 ret = -ENOENT;
Dave Airlief453ba02008-11-07 14:05:41 -0800772 goto out;
773 }
Dave Airlief453ba02008-11-07 14:05:41 -0800774 }
775
776 mode = drm_mode_create(dev);
Ville Syrjäläee34ab52012-03-13 12:35:43 +0200777 if (!mode) {
778 ret = -ENOMEM;
779 goto out;
780 }
781
Daniel Stone934a8a82015-05-22 13:34:48 +0100782 ret = drm_mode_convert_umode(mode, &crtc_req->mode);
Ville Syrjälä90367bf2012-03-13 12:35:44 +0200783 if (ret) {
784 DRM_DEBUG_KMS("Invalid mode\n");
785 goto out;
786 }
787
Laurent Pinchart7eb5f302015-03-09 10:41:07 +0200788 /*
789 * Check whether the primary plane supports the fb pixel format.
790 * Drivers not implementing the universal planes API use a
791 * default formats list provided by the DRM core which doesn't
792 * match real hardware capabilities. Skip the check in that
793 * case.
794 */
795 if (!crtc->primary->format_default) {
796 ret = drm_plane_check_pixel_format(crtc->primary,
797 fb->pixel_format);
798 if (ret) {
Eric Engestromd3828142016-08-15 16:29:55 +0100799 char *format_name = drm_get_format_name(fb->pixel_format);
Eric Engestrom90844f02016-08-15 01:02:38 +0100800 DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name);
801 kfree(format_name);
Laurent Pinchart7eb5f302015-03-09 10:41:07 +0200802 goto out;
803 }
804 }
805
Damien Lespiauc11e9282013-09-25 16:45:30 +0100806 ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
807 mode, fb);
808 if (ret)
Ville Syrjälä5f61bb42012-03-13 12:35:45 +0200809 goto out;
Damien Lespiauc11e9282013-09-25 16:45:30 +0100810
Dave Airlief453ba02008-11-07 14:05:41 -0800811 }
812
813 if (crtc_req->count_connectors == 0 && mode) {
Zhao Yakui58367ed2009-07-20 13:48:07 +0800814 DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
Dave Airlief453ba02008-11-07 14:05:41 -0800815 ret = -EINVAL;
816 goto out;
817 }
818
Jakob Bornecrantz7781de72009-08-03 13:43:58 +0100819 if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
Zhao Yakui58367ed2009-07-20 13:48:07 +0800820 DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
Dave Airlief453ba02008-11-07 14:05:41 -0800821 crtc_req->count_connectors);
822 ret = -EINVAL;
823 goto out;
824 }
825
826 if (crtc_req->count_connectors > 0) {
827 u32 out_id;
828
829 /* Avoid unbounded kernel memory allocation */
830 if (crtc_req->count_connectors > config->num_connector) {
831 ret = -EINVAL;
832 goto out;
833 }
834
Thierry Reding2f6c5382014-12-10 13:03:36 +0100835 connector_set = kmalloc_array(crtc_req->count_connectors,
836 sizeof(struct drm_connector *),
837 GFP_KERNEL);
Dave Airlief453ba02008-11-07 14:05:41 -0800838 if (!connector_set) {
839 ret = -ENOMEM;
840 goto out;
841 }
842
843 for (i = 0; i < crtc_req->count_connectors; i++) {
Dave Airlieb164d312016-04-27 11:10:09 +1000844 connector_set[i] = NULL;
Ville Syrjälä81f6c7f2011-12-20 00:06:42 +0200845 set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
Dave Airlief453ba02008-11-07 14:05:41 -0800846 if (get_user(out_id, &set_connectors_ptr[i])) {
847 ret = -EFAULT;
848 goto out;
849 }
850
Dave Airlieb164d312016-04-27 11:10:09 +1000851 connector = drm_connector_lookup(dev, out_id);
Rob Clarka2b34e22013-10-05 16:36:52 -0400852 if (!connector) {
Zhao Yakui58367ed2009-07-20 13:48:07 +0800853 DRM_DEBUG_KMS("Connector id %d unknown\n",
854 out_id);
Ville Syrjäläf27657f2013-10-17 13:35:00 +0300855 ret = -ENOENT;
Dave Airlief453ba02008-11-07 14:05:41 -0800856 goto out;
857 }
Jerome Glisse94401062010-07-15 15:43:25 -0400858 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
859 connector->base.id,
Jani Nikula25933822014-06-03 14:56:20 +0300860 connector->name);
Dave Airlief453ba02008-11-07 14:05:41 -0800861
862 connector_set[i] = connector;
863 }
864 }
865
866 set.crtc = crtc;
867 set.x = crtc_req->x;
868 set.y = crtc_req->y;
869 set.mode = mode;
870 set.connectors = connector_set;
871 set.num_connectors = crtc_req->count_connectors;
Dave Airlie5ef5f722009-08-17 13:11:23 +1000872 set.fb = fb;
Daniel Vetter2d13b672012-12-11 13:47:23 +0100873 ret = drm_mode_set_config_internal(&set);
Dave Airlief453ba02008-11-07 14:05:41 -0800874
875out:
Daniel Vetterb0d12322012-12-11 01:07:12 +0100876 if (fb)
877 drm_framebuffer_unreference(fb);
878
Dave Airlieb164d312016-04-27 11:10:09 +1000879 if (connector_set) {
880 for (i = 0; i < crtc_req->count_connectors; i++) {
881 if (connector_set[i])
882 drm_connector_unreference(connector_set[i]);
883 }
884 }
Dave Airlief453ba02008-11-07 14:05:41 -0800885 kfree(connector_set);
Ville Syrjäläee34ab52012-03-13 12:35:43 +0200886 drm_mode_destroy(dev, mode);
Daniel Vetter84849902012-12-02 00:28:11 +0100887 drm_modeset_unlock_all(dev);
Dave Airlief453ba02008-11-07 14:05:41 -0800888 return ret;
889}
890
Daniel Vetter949619f2016-08-29 10:27:51 +0200891int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
892 struct drm_property *property,
893 uint64_t value)
Paulo Zanonibffd9de02012-05-15 18:09:05 -0300894{
895 int ret = -EINVAL;
896 struct drm_crtc *crtc = obj_to_crtc(obj);
897
898 if (crtc->funcs->set_property)
899 ret = crtc->funcs->set_property(crtc, property, value);
900 if (!ret)
901 drm_object_property_set_value(obj, property, value);
902
903 return ret;
904}
905
Thomas Wood3a5f87c2014-08-20 14:45:00 +0100906/**
Daniel Vetterc8e32cc2014-03-10 21:33:02 +0100907 * drm_mode_config_reset - call ->reset callbacks
908 * @dev: drm device
909 *
910 * This functions calls all the crtc's, encoder's and connector's ->reset
911 * callback. Drivers can use this in e.g. their driver load or resume code to
912 * reset hardware and software state.
913 */
Chris Wilsoneb033552011-01-24 15:11:08 +0000914void drm_mode_config_reset(struct drm_device *dev)
915{
916 struct drm_crtc *crtc;
Daniel Vetter2a0d7cf2014-07-29 15:32:37 +0200917 struct drm_plane *plane;
Chris Wilsoneb033552011-01-24 15:11:08 +0000918 struct drm_encoder *encoder;
919 struct drm_connector *connector;
920
Daniel Vettere4f62542015-07-09 23:44:35 +0200921 drm_for_each_plane(plane, dev)
Daniel Vetter2a0d7cf2014-07-29 15:32:37 +0200922 if (plane->funcs->reset)
923 plane->funcs->reset(plane);
924
Daniel Vettere4f62542015-07-09 23:44:35 +0200925 drm_for_each_crtc(crtc, dev)
Chris Wilsoneb033552011-01-24 15:11:08 +0000926 if (crtc->funcs->reset)
927 crtc->funcs->reset(crtc);
928
Daniel Vettere4f62542015-07-09 23:44:35 +0200929 drm_for_each_encoder(encoder, dev)
Chris Wilsoneb033552011-01-24 15:11:08 +0000930 if (encoder->funcs->reset)
931 encoder->funcs->reset(encoder);
932
Daniel Vetterf8c2ba32015-07-29 08:32:43 +0200933 mutex_lock(&dev->mode_config.mutex);
Dave Airlie4eebf602015-08-17 14:13:53 +1000934 drm_for_each_connector(connector, dev)
Chris Wilsoneb033552011-01-24 15:11:08 +0000935 if (connector->funcs->reset)
936 connector->funcs->reset(connector);
Daniel Vetterf8c2ba32015-07-29 08:32:43 +0200937 mutex_unlock(&dev->mode_config.mutex);
Chris Wilsoneb033552011-01-24 15:11:08 +0000938}
939EXPORT_SYMBOL(drm_mode_config_reset);
Dave Airlieff72145b2011-02-07 12:16:14 +1000940
Daniel Vetterc8e32cc2014-03-10 21:33:02 +0100941/**
942 * drm_mode_create_dumb_ioctl - create a dumb backing storage buffer
943 * @dev: DRM device
944 * @data: ioctl data
945 * @file_priv: DRM file info
946 *
947 * This creates a new dumb buffer in the driver's backing storage manager (GEM,
948 * TTM or something else entirely) and returns the resulting buffer handle. This
949 * handle can then be wrapped up into a framebuffer modeset object.
950 *
951 * Note that userspace is not allowed to use such objects for render
952 * acceleration - drivers must create their own private ioctls for such a use
953 * case.
954 *
955 * Called by the user via ioctl.
956 *
957 * Returns:
Daniel Vetter1a498632014-11-19 18:38:09 +0100958 * Zero on success, negative errno on failure.
Daniel Vetterc8e32cc2014-03-10 21:33:02 +0100959 */
Dave Airlieff72145b2011-02-07 12:16:14 +1000960int drm_mode_create_dumb_ioctl(struct drm_device *dev,
961 void *data, struct drm_file *file_priv)
962{
963 struct drm_mode_create_dumb *args = data;
David Herrmannb28cd412014-01-20 20:09:55 +0100964 u32 cpp, stride, size;
Dave Airlieff72145b2011-02-07 12:16:14 +1000965
966 if (!dev->driver->dumb_create)
967 return -ENOSYS;
David Herrmannb28cd412014-01-20 20:09:55 +0100968 if (!args->width || !args->height || !args->bpp)
969 return -EINVAL;
970
971 /* overflow checks for 32bit size calculations */
David Herrmann00e72082014-08-24 19:23:26 +0200972 /* NOTE: DIV_ROUND_UP() can overflow */
David Herrmannb28cd412014-01-20 20:09:55 +0100973 cpp = DIV_ROUND_UP(args->bpp, 8);
David Herrmann00e72082014-08-24 19:23:26 +0200974 if (!cpp || cpp > 0xffffffffU / args->width)
David Herrmannb28cd412014-01-20 20:09:55 +0100975 return -EINVAL;
976 stride = cpp * args->width;
977 if (args->height > 0xffffffffU / stride)
978 return -EINVAL;
979
980 /* test for wrap-around */
981 size = args->height * stride;
982 if (PAGE_ALIGN(size) == 0)
983 return -EINVAL;
984
Thierry Redingf6085952014-11-03 11:14:14 +0100985 /*
986 * handle, pitch and size are output parameters. Zero them out to
987 * prevent drivers from accidentally using uninitialized data. Since
988 * not all existing userspace is clearing these fields properly we
989 * cannot reject IOCTL with garbage in them.
990 */
991 args->handle = 0;
992 args->pitch = 0;
993 args->size = 0;
994
Dave Airlieff72145b2011-02-07 12:16:14 +1000995 return dev->driver->dumb_create(file_priv, dev, args);
996}
997
Daniel Vetterc8e32cc2014-03-10 21:33:02 +0100998/**
999 * drm_mode_mmap_dumb_ioctl - create an mmap offset for a dumb backing storage buffer
1000 * @dev: DRM device
1001 * @data: ioctl data
1002 * @file_priv: DRM file info
1003 *
1004 * Allocate an offset in the drm device node's address space to be able to
1005 * memory map a dumb buffer.
1006 *
1007 * Called by the user via ioctl.
1008 *
1009 * Returns:
Daniel Vetter1a498632014-11-19 18:38:09 +01001010 * Zero on success, negative errno on failure.
Daniel Vetterc8e32cc2014-03-10 21:33:02 +01001011 */
Dave Airlieff72145b2011-02-07 12:16:14 +10001012int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
1013 void *data, struct drm_file *file_priv)
1014{
1015 struct drm_mode_map_dumb *args = data;
1016
1017 /* call driver ioctl to get mmap offset */
1018 if (!dev->driver->dumb_map_offset)
1019 return -ENOSYS;
1020
1021 return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
1022}
1023
Daniel Vetterc8e32cc2014-03-10 21:33:02 +01001024/**
1025 * drm_mode_destroy_dumb_ioctl - destroy a dumb backing strage buffer
1026 * @dev: DRM device
1027 * @data: ioctl data
1028 * @file_priv: DRM file info
1029 *
1030 * This destroys the userspace handle for the given dumb backing storage buffer.
1031 * Since buffer objects must be reference counted in the kernel a buffer object
1032 * won't be immediately freed if a framebuffer modeset object still uses it.
1033 *
1034 * Called by the user via ioctl.
1035 *
1036 * Returns:
Daniel Vetter1a498632014-11-19 18:38:09 +01001037 * Zero on success, negative errno on failure.
Daniel Vetterc8e32cc2014-03-10 21:33:02 +01001038 */
Dave Airlieff72145b2011-02-07 12:16:14 +10001039int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
1040 void *data, struct drm_file *file_priv)
1041{
1042 struct drm_mode_destroy_dumb *args = data;
1043
1044 if (!dev->driver->dumb_destroy)
1045 return -ENOSYS;
1046
1047 return dev->driver->dumb_destroy(file_priv, dev, args->handle);
1048}
Dave Airlie248dbc22011-11-29 20:02:54 +00001049
Daniel Vetterc8e32cc2014-03-10 21:33:02 +01001050/**
Laurent Pinchart87d24fc2013-04-15 15:37:16 +02001051 * drm_mode_config_init - initialize DRM mode_configuration structure
1052 * @dev: DRM device
1053 *
1054 * Initialize @dev's mode_config structure, used for tracking the graphics
1055 * configuration of @dev.
1056 *
1057 * Since this initializes the modeset locks, no locking is possible. Which is no
1058 * problem, since this should happen single threaded at init time. It is the
1059 * driver's problem to ensure this guarantee.
1060 *
1061 */
1062void drm_mode_config_init(struct drm_device *dev)
1063{
1064 mutex_init(&dev->mode_config.mutex);
Rob Clark51fd3712013-11-19 12:10:12 -05001065 drm_modeset_lock_init(&dev->mode_config.connection_mutex);
Laurent Pinchart87d24fc2013-04-15 15:37:16 +02001066 mutex_init(&dev->mode_config.idr_mutex);
1067 mutex_init(&dev->mode_config.fb_lock);
Daniel Stone8fb6e7a2015-04-20 19:22:54 +01001068 mutex_init(&dev->mode_config.blob_lock);
Laurent Pinchart87d24fc2013-04-15 15:37:16 +02001069 INIT_LIST_HEAD(&dev->mode_config.fb_list);
1070 INIT_LIST_HEAD(&dev->mode_config.crtc_list);
1071 INIT_LIST_HEAD(&dev->mode_config.connector_list);
1072 INIT_LIST_HEAD(&dev->mode_config.encoder_list);
1073 INIT_LIST_HEAD(&dev->mode_config.property_list);
1074 INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
1075 INIT_LIST_HEAD(&dev->mode_config.plane_list);
1076 idr_init(&dev->mode_config.crtc_idr);
Dave Airlie138f9eb2014-10-20 16:17:17 +10001077 idr_init(&dev->mode_config.tile_idr);
Maarten Lankhorst5fff80b2016-02-17 08:32:05 +01001078 ida_init(&dev->mode_config.connector_ida);
Laurent Pinchart87d24fc2013-04-15 15:37:16 +02001079
1080 drm_modeset_lock_all(dev);
Rob Clark6b4959f2014-12-18 16:01:53 -05001081 drm_mode_create_standard_properties(dev);
Laurent Pinchart87d24fc2013-04-15 15:37:16 +02001082 drm_modeset_unlock_all(dev);
1083
1084 /* Just to be sure */
1085 dev->mode_config.num_fb = 0;
1086 dev->mode_config.num_connector = 0;
1087 dev->mode_config.num_crtc = 0;
1088 dev->mode_config.num_encoder = 0;
Matt Ropere27dde32014-04-01 15:22:30 -07001089 dev->mode_config.num_overlay_plane = 0;
1090 dev->mode_config.num_total_plane = 0;
Laurent Pinchart87d24fc2013-04-15 15:37:16 +02001091}
1092EXPORT_SYMBOL(drm_mode_config_init);
1093
1094/**
1095 * drm_mode_config_cleanup - free up DRM mode_config info
1096 * @dev: DRM device
1097 *
1098 * Free up all the connectors and CRTCs associated with this DRM device, then
1099 * free up the framebuffers and associated buffer objects.
1100 *
1101 * Note that since this /should/ happen single-threaded at driver/device
1102 * teardown time, no locking is required. It's the driver's job to ensure that
1103 * this guarantee actually holds true.
1104 *
1105 * FIXME: cleanup any dangling user buffer objects too
1106 */
1107void drm_mode_config_cleanup(struct drm_device *dev)
1108{
1109 struct drm_connector *connector, *ot;
1110 struct drm_crtc *crtc, *ct;
1111 struct drm_encoder *encoder, *enct;
1112 struct drm_framebuffer *fb, *fbt;
1113 struct drm_property *property, *pt;
1114 struct drm_property_blob *blob, *bt;
1115 struct drm_plane *plane, *plt;
1116
1117 list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
1118 head) {
1119 encoder->funcs->destroy(encoder);
1120 }
1121
1122 list_for_each_entry_safe(connector, ot,
1123 &dev->mode_config.connector_list, head) {
1124 connector->funcs->destroy(connector);
1125 }
1126
1127 list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
1128 head) {
1129 drm_property_destroy(dev, property);
1130 }
1131
Maarten Lankhorstf35034f2016-03-22 15:42:14 +01001132 list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
1133 head) {
1134 plane->funcs->destroy(plane);
1135 }
1136
1137 list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
1138 crtc->funcs->destroy(crtc);
1139 }
1140
Laurent Pinchart87d24fc2013-04-15 15:37:16 +02001141 list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
Daniel Stonee2f5d2e2015-05-22 13:34:51 +01001142 head_global) {
Daniel Stone6bcacf52015-04-20 19:22:55 +01001143 drm_property_unreference_blob(blob);
Laurent Pinchart87d24fc2013-04-15 15:37:16 +02001144 }
1145
1146 /*
1147 * Single-threaded teardown context, so it's not required to grab the
1148 * fb_lock to protect against concurrent fb_list access. Contrary, it
1149 * would actually deadlock with the drm_framebuffer_cleanup function.
1150 *
1151 * Also, if there are any framebuffers left, that's a driver leak now,
1152 * so politely WARN about this.
1153 */
1154 WARN_ON(!list_empty(&dev->mode_config.fb_list));
1155 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
Dave Airlied0f37cf62016-04-15 15:10:36 +10001156 drm_framebuffer_free(&fb->base.refcount);
Laurent Pinchart87d24fc2013-04-15 15:37:16 +02001157 }
1158
Maarten Lankhorst5fff80b2016-02-17 08:32:05 +01001159 ida_destroy(&dev->mode_config.connector_ida);
Dave Airlie138f9eb2014-10-20 16:17:17 +10001160 idr_destroy(&dev->mode_config.tile_idr);
Laurent Pinchart87d24fc2013-04-15 15:37:16 +02001161 idr_destroy(&dev->mode_config.crtc_idr);
Rob Clark51fd3712013-11-19 12:10:12 -05001162 drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
Laurent Pinchart87d24fc2013-04-15 15:37:16 +02001163}
1164EXPORT_SYMBOL(drm_mode_config_cleanup);
Ville Syrjäläc1df5f32014-07-08 10:31:53 +05301165
Dave Airlie138f9eb2014-10-20 16:17:17 +10001166/**
1167 * DOC: Tile group
1168 *
1169 * Tile groups are used to represent tiled monitors with a unique
1170 * integer identifier. Tiled monitors using DisplayID v1.3 have
1171 * a unique 8-byte handle, we store this in a tile group, so we
1172 * have a common identifier for all tiles in a monitor group.
1173 */
1174static void drm_tile_group_free(struct kref *kref)
1175{
1176 struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
1177 struct drm_device *dev = tg->dev;
1178 mutex_lock(&dev->mode_config.idr_mutex);
1179 idr_remove(&dev->mode_config.tile_idr, tg->id);
1180 mutex_unlock(&dev->mode_config.idr_mutex);
1181 kfree(tg);
1182}
1183
1184/**
1185 * drm_mode_put_tile_group - drop a reference to a tile group.
1186 * @dev: DRM device
1187 * @tg: tile group to drop reference to.
1188 *
1189 * drop reference to tile group and free if 0.
1190 */
1191void drm_mode_put_tile_group(struct drm_device *dev,
1192 struct drm_tile_group *tg)
1193{
1194 kref_put(&tg->refcount, drm_tile_group_free);
1195}
1196
1197/**
1198 * drm_mode_get_tile_group - get a reference to an existing tile group
1199 * @dev: DRM device
1200 * @topology: 8-bytes unique per monitor.
1201 *
1202 * Use the unique bytes to get a reference to an existing tile group.
1203 *
1204 * RETURNS:
1205 * tile group or NULL if not found.
1206 */
1207struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
1208 char topology[8])
1209{
1210 struct drm_tile_group *tg;
1211 int id;
1212 mutex_lock(&dev->mode_config.idr_mutex);
1213 idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
1214 if (!memcmp(tg->group_data, topology, 8)) {
1215 if (!kref_get_unless_zero(&tg->refcount))
1216 tg = NULL;
1217 mutex_unlock(&dev->mode_config.idr_mutex);
1218 return tg;
1219 }
1220 }
1221 mutex_unlock(&dev->mode_config.idr_mutex);
1222 return NULL;
1223}
Rob Clark81ddd1b2015-03-27 13:01:52 -04001224EXPORT_SYMBOL(drm_mode_get_tile_group);
Dave Airlie138f9eb2014-10-20 16:17:17 +10001225
1226/**
1227 * drm_mode_create_tile_group - create a tile group from a displayid description
1228 * @dev: DRM device
1229 * @topology: 8-bytes unique per monitor.
1230 *
1231 * Create a tile group for the unique monitor, and get a unique
1232 * identifier for the tile group.
1233 *
1234 * RETURNS:
1235 * new tile group or error.
1236 */
1237struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
1238 char topology[8])
1239{
1240 struct drm_tile_group *tg;
1241 int ret;
1242
1243 tg = kzalloc(sizeof(*tg), GFP_KERNEL);
1244 if (!tg)
1245 return ERR_PTR(-ENOMEM);
1246
1247 kref_init(&tg->refcount);
1248 memcpy(tg->group_data, topology, 8);
1249 tg->dev = dev;
1250
1251 mutex_lock(&dev->mode_config.idr_mutex);
1252 ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
1253 if (ret >= 0) {
1254 tg->id = ret;
1255 } else {
1256 kfree(tg);
1257 tg = ERR_PTR(ret);
1258 }
1259
1260 mutex_unlock(&dev->mode_config.idr_mutex);
1261 return tg;
1262}
Rob Clark81ddd1b2015-03-27 13:01:52 -04001263EXPORT_SYMBOL(drm_mode_create_tile_group);