Home | History | Annotate | Line # | Download | only in drm
      1  1.5  riastrad /*	$NetBSD: drm_mode_config.c,v 1.5 2021/12/19 12:32:01 riastradh Exp $	*/
      2  1.1  riastrad 
      3  1.1  riastrad /*
      4  1.1  riastrad  * Copyright (c) 2016 Intel Corporation
      5  1.1  riastrad  *
      6  1.1  riastrad  * Permission to use, copy, modify, distribute, and sell this software and its
      7  1.1  riastrad  * documentation for any purpose is hereby granted without fee, provided that
      8  1.1  riastrad  * the above copyright notice appear in all copies and that both that copyright
      9  1.1  riastrad  * notice and this permission notice appear in supporting documentation, and
     10  1.1  riastrad  * that the name of the copyright holders not be used in advertising or
     11  1.1  riastrad  * publicity pertaining to distribution of the software without specific,
     12  1.1  riastrad  * written prior permission.  The copyright holders make no representations
     13  1.1  riastrad  * about the suitability of this software for any purpose.  It is provided "as
     14  1.1  riastrad  * is" without express or implied warranty.
     15  1.1  riastrad  *
     16  1.1  riastrad  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     17  1.1  riastrad  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     18  1.1  riastrad  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     19  1.1  riastrad  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     20  1.1  riastrad  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     21  1.1  riastrad  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     22  1.1  riastrad  * OF THIS SOFTWARE.
     23  1.1  riastrad  */
     24  1.1  riastrad 
     25  1.1  riastrad #include <sys/cdefs.h>
     26  1.5  riastrad __KERNEL_RCSID(0, "$NetBSD: drm_mode_config.c,v 1.5 2021/12/19 12:32:01 riastradh Exp $");
     27  1.1  riastrad 
     28  1.1  riastrad #include <linux/uaccess.h>
     29  1.1  riastrad 
     30  1.1  riastrad #include <drm/drm_drv.h>
     31  1.1  riastrad #include <drm/drm_encoder.h>
     32  1.1  riastrad #include <drm/drm_file.h>
     33  1.1  riastrad #include <drm/drm_mode_config.h>
     34  1.1  riastrad #include <drm/drm_print.h>
     35  1.1  riastrad #include <linux/dma-resv.h>
     36  1.1  riastrad 
     37  1.1  riastrad #include "drm_crtc_internal.h"
     38  1.1  riastrad #include "drm_internal.h"
     39  1.1  riastrad 
     40  1.3  riastrad #include <linux/nbsd-namespace.h>
     41  1.3  riastrad 
     42  1.1  riastrad int drm_modeset_register_all(struct drm_device *dev)
     43  1.1  riastrad {
     44  1.1  riastrad 	int ret;
     45  1.1  riastrad 
     46  1.1  riastrad 	ret = drm_plane_register_all(dev);
     47  1.1  riastrad 	if (ret)
     48  1.1  riastrad 		goto err_plane;
     49  1.1  riastrad 
     50  1.1  riastrad 	ret = drm_crtc_register_all(dev);
     51  1.1  riastrad 	if  (ret)
     52  1.1  riastrad 		goto err_crtc;
     53  1.1  riastrad 
     54  1.1  riastrad 	ret = drm_encoder_register_all(dev);
     55  1.1  riastrad 	if (ret)
     56  1.1  riastrad 		goto err_encoder;
     57  1.1  riastrad 
     58  1.1  riastrad 	ret = drm_connector_register_all(dev);
     59  1.1  riastrad 	if (ret)
     60  1.1  riastrad 		goto err_connector;
     61  1.1  riastrad 
     62  1.1  riastrad 	return 0;
     63  1.1  riastrad 
     64  1.1  riastrad err_connector:
     65  1.1  riastrad 	drm_encoder_unregister_all(dev);
     66  1.1  riastrad err_encoder:
     67  1.1  riastrad 	drm_crtc_unregister_all(dev);
     68  1.1  riastrad err_crtc:
     69  1.1  riastrad 	drm_plane_unregister_all(dev);
     70  1.1  riastrad err_plane:
     71  1.1  riastrad 	return ret;
     72  1.1  riastrad }
     73  1.1  riastrad 
     74  1.1  riastrad void drm_modeset_unregister_all(struct drm_device *dev)
     75  1.1  riastrad {
     76  1.1  riastrad 	drm_connector_unregister_all(dev);
     77  1.1  riastrad 	drm_encoder_unregister_all(dev);
     78  1.1  riastrad 	drm_crtc_unregister_all(dev);
     79  1.1  riastrad 	drm_plane_unregister_all(dev);
     80  1.1  riastrad }
     81  1.1  riastrad 
     82  1.1  riastrad /**
     83  1.1  riastrad  * drm_mode_getresources - get graphics configuration
     84  1.1  riastrad  * @dev: drm device for the ioctl
     85  1.1  riastrad  * @data: data pointer for the ioctl
     86  1.1  riastrad  * @file_priv: drm file for the ioctl call
     87  1.1  riastrad  *
     88  1.1  riastrad  * Construct a set of configuration description structures and return
     89  1.1  riastrad  * them to the user, including CRTC, connector and framebuffer configuration.
     90  1.1  riastrad  *
     91  1.1  riastrad  * Called by the user via ioctl.
     92  1.1  riastrad  *
     93  1.1  riastrad  * Returns:
     94  1.1  riastrad  * Zero on success, negative errno on failure.
     95  1.1  riastrad  */
     96  1.1  riastrad int drm_mode_getresources(struct drm_device *dev, void *data,
     97  1.1  riastrad 			  struct drm_file *file_priv)
     98  1.1  riastrad {
     99  1.1  riastrad 	struct drm_mode_card_res *card_res = data;
    100  1.1  riastrad 	struct drm_framebuffer *fb;
    101  1.1  riastrad 	struct drm_connector *connector;
    102  1.1  riastrad 	struct drm_crtc *crtc;
    103  1.1  riastrad 	struct drm_encoder *encoder;
    104  1.1  riastrad 	int count, ret = 0;
    105  1.1  riastrad 	uint32_t __user *fb_id;
    106  1.1  riastrad 	uint32_t __user *crtc_id;
    107  1.1  riastrad 	uint32_t __user *connector_id;
    108  1.1  riastrad 	uint32_t __user *encoder_id;
    109  1.1  riastrad 	struct drm_connector_list_iter conn_iter;
    110  1.1  riastrad 
    111  1.1  riastrad 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
    112  1.1  riastrad 		return -EOPNOTSUPP;
    113  1.1  riastrad 
    114  1.1  riastrad 	mutex_lock(&file_priv->fbs_lock);
    115  1.1  riastrad 	count = 0;
    116  1.1  riastrad 	fb_id = u64_to_user_ptr(card_res->fb_id_ptr);
    117  1.1  riastrad 	list_for_each_entry(fb, &file_priv->fbs, filp_head) {
    118  1.1  riastrad 		if (count < card_res->count_fbs &&
    119  1.1  riastrad 		    put_user(fb->base.id, fb_id + count)) {
    120  1.1  riastrad 			mutex_unlock(&file_priv->fbs_lock);
    121  1.1  riastrad 			return -EFAULT;
    122  1.1  riastrad 		}
    123  1.1  riastrad 		count++;
    124  1.1  riastrad 	}
    125  1.1  riastrad 	card_res->count_fbs = count;
    126  1.1  riastrad 	mutex_unlock(&file_priv->fbs_lock);
    127  1.1  riastrad 
    128  1.1  riastrad 	card_res->max_height = dev->mode_config.max_height;
    129  1.1  riastrad 	card_res->min_height = dev->mode_config.min_height;
    130  1.1  riastrad 	card_res->max_width = dev->mode_config.max_width;
    131  1.1  riastrad 	card_res->min_width = dev->mode_config.min_width;
    132  1.1  riastrad 
    133  1.1  riastrad 	count = 0;
    134  1.1  riastrad 	crtc_id = u64_to_user_ptr(card_res->crtc_id_ptr);
    135  1.1  riastrad 	drm_for_each_crtc(crtc, dev) {
    136  1.1  riastrad 		if (drm_lease_held(file_priv, crtc->base.id)) {
    137  1.1  riastrad 			if (count < card_res->count_crtcs &&
    138  1.1  riastrad 			    put_user(crtc->base.id, crtc_id + count))
    139  1.1  riastrad 				return -EFAULT;
    140  1.1  riastrad 			count++;
    141  1.1  riastrad 		}
    142  1.1  riastrad 	}
    143  1.1  riastrad 	card_res->count_crtcs = count;
    144  1.1  riastrad 
    145  1.1  riastrad 	count = 0;
    146  1.1  riastrad 	encoder_id = u64_to_user_ptr(card_res->encoder_id_ptr);
    147  1.1  riastrad 	drm_for_each_encoder(encoder, dev) {
    148  1.1  riastrad 		if (count < card_res->count_encoders &&
    149  1.1  riastrad 		    put_user(encoder->base.id, encoder_id + count))
    150  1.1  riastrad 			return -EFAULT;
    151  1.1  riastrad 		count++;
    152  1.1  riastrad 	}
    153  1.1  riastrad 	card_res->count_encoders = count;
    154  1.1  riastrad 
    155  1.1  riastrad 	drm_connector_list_iter_begin(dev, &conn_iter);
    156  1.1  riastrad 	count = 0;
    157  1.1  riastrad 	connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
    158  1.1  riastrad 	drm_for_each_connector_iter(connector, &conn_iter) {
    159  1.1  riastrad 		/* only expose writeback connectors if userspace understands them */
    160  1.1  riastrad 		if (!file_priv->writeback_connectors &&
    161  1.1  riastrad 		    (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK))
    162  1.1  riastrad 			continue;
    163  1.1  riastrad 
    164  1.1  riastrad 		if (drm_lease_held(file_priv, connector->base.id)) {
    165  1.1  riastrad 			if (count < card_res->count_connectors &&
    166  1.1  riastrad 			    put_user(connector->base.id, connector_id + count)) {
    167  1.1  riastrad 				drm_connector_list_iter_end(&conn_iter);
    168  1.1  riastrad 				return -EFAULT;
    169  1.1  riastrad 			}
    170  1.1  riastrad 			count++;
    171  1.1  riastrad 		}
    172  1.1  riastrad 	}
    173  1.1  riastrad 	card_res->count_connectors = count;
    174  1.1  riastrad 	drm_connector_list_iter_end(&conn_iter);
    175  1.1  riastrad 
    176  1.1  riastrad 	return ret;
    177  1.1  riastrad }
    178  1.1  riastrad 
    179  1.1  riastrad /**
    180  1.1  riastrad  * drm_mode_config_reset - call ->reset callbacks
    181  1.1  riastrad  * @dev: drm device
    182  1.1  riastrad  *
    183  1.1  riastrad  * This functions calls all the crtc's, encoder's and connector's ->reset
    184  1.1  riastrad  * callback. Drivers can use this in e.g. their driver load or resume code to
    185  1.1  riastrad  * reset hardware and software state.
    186  1.1  riastrad  */
    187  1.1  riastrad void drm_mode_config_reset(struct drm_device *dev)
    188  1.1  riastrad {
    189  1.1  riastrad 	struct drm_crtc *crtc;
    190  1.1  riastrad 	struct drm_plane *plane;
    191  1.1  riastrad 	struct drm_encoder *encoder;
    192  1.1  riastrad 	struct drm_connector *connector;
    193  1.1  riastrad 	struct drm_connector_list_iter conn_iter;
    194  1.1  riastrad 
    195  1.1  riastrad 	drm_for_each_plane(plane, dev)
    196  1.1  riastrad 		if (plane->funcs->reset)
    197  1.1  riastrad 			plane->funcs->reset(plane);
    198  1.1  riastrad 
    199  1.1  riastrad 	drm_for_each_crtc(crtc, dev)
    200  1.1  riastrad 		if (crtc->funcs->reset)
    201  1.1  riastrad 			crtc->funcs->reset(crtc);
    202  1.1  riastrad 
    203  1.1  riastrad 	drm_for_each_encoder(encoder, dev)
    204  1.1  riastrad 		if (encoder->funcs->reset)
    205  1.1  riastrad 			encoder->funcs->reset(encoder);
    206  1.1  riastrad 
    207  1.1  riastrad 	drm_connector_list_iter_begin(dev, &conn_iter);
    208  1.1  riastrad 	drm_for_each_connector_iter(connector, &conn_iter)
    209  1.1  riastrad 		if (connector->funcs->reset)
    210  1.1  riastrad 			connector->funcs->reset(connector);
    211  1.1  riastrad 	drm_connector_list_iter_end(&conn_iter);
    212  1.1  riastrad }
    213  1.1  riastrad EXPORT_SYMBOL(drm_mode_config_reset);
    214  1.1  riastrad 
    215  1.1  riastrad /*
    216  1.1  riastrad  * Global properties
    217  1.1  riastrad  */
    218  1.1  riastrad static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
    219  1.1  riastrad 	{ DRM_PLANE_TYPE_OVERLAY, "Overlay" },
    220  1.1  riastrad 	{ DRM_PLANE_TYPE_PRIMARY, "Primary" },
    221  1.1  riastrad 	{ DRM_PLANE_TYPE_CURSOR, "Cursor" },
    222  1.1  riastrad };
    223  1.1  riastrad 
    224  1.1  riastrad static int drm_mode_create_standard_properties(struct drm_device *dev)
    225  1.1  riastrad {
    226  1.1  riastrad 	struct drm_property *prop;
    227  1.1  riastrad 	int ret;
    228  1.1  riastrad 
    229  1.1  riastrad 	ret = drm_connector_create_standard_properties(dev);
    230  1.1  riastrad 	if (ret)
    231  1.1  riastrad 		return ret;
    232  1.1  riastrad 
    233  1.1  riastrad 	prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
    234  1.1  riastrad 					"type", drm_plane_type_enum_list,
    235  1.1  riastrad 					ARRAY_SIZE(drm_plane_type_enum_list));
    236  1.1  riastrad 	if (!prop)
    237  1.1  riastrad 		return -ENOMEM;
    238  1.1  riastrad 	dev->mode_config.plane_type_property = prop;
    239  1.1  riastrad 
    240  1.1  riastrad 	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
    241  1.1  riastrad 			"SRC_X", 0, UINT_MAX);
    242  1.1  riastrad 	if (!prop)
    243  1.1  riastrad 		return -ENOMEM;
    244  1.1  riastrad 	dev->mode_config.prop_src_x = prop;
    245  1.1  riastrad 
    246  1.1  riastrad 	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
    247  1.1  riastrad 			"SRC_Y", 0, UINT_MAX);
    248  1.1  riastrad 	if (!prop)
    249  1.1  riastrad 		return -ENOMEM;
    250  1.1  riastrad 	dev->mode_config.prop_src_y = prop;
    251  1.1  riastrad 
    252  1.1  riastrad 	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
    253  1.1  riastrad 			"SRC_W", 0, UINT_MAX);
    254  1.1  riastrad 	if (!prop)
    255  1.1  riastrad 		return -ENOMEM;
    256  1.1  riastrad 	dev->mode_config.prop_src_w = prop;
    257  1.1  riastrad 
    258  1.1  riastrad 	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
    259  1.1  riastrad 			"SRC_H", 0, UINT_MAX);
    260  1.1  riastrad 	if (!prop)
    261  1.1  riastrad 		return -ENOMEM;
    262  1.1  riastrad 	dev->mode_config.prop_src_h = prop;
    263  1.1  riastrad 
    264  1.1  riastrad 	prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
    265  1.1  riastrad 			"CRTC_X", INT_MIN, INT_MAX);
    266  1.1  riastrad 	if (!prop)
    267  1.1  riastrad 		return -ENOMEM;
    268  1.1  riastrad 	dev->mode_config.prop_crtc_x = prop;
    269  1.1  riastrad 
    270  1.1  riastrad 	prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
    271  1.1  riastrad 			"CRTC_Y", INT_MIN, INT_MAX);
    272  1.1  riastrad 	if (!prop)
    273  1.1  riastrad 		return -ENOMEM;
    274  1.1  riastrad 	dev->mode_config.prop_crtc_y = prop;
    275  1.1  riastrad 
    276  1.1  riastrad 	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
    277  1.1  riastrad 			"CRTC_W", 0, INT_MAX);
    278  1.1  riastrad 	if (!prop)
    279  1.1  riastrad 		return -ENOMEM;
    280  1.1  riastrad 	dev->mode_config.prop_crtc_w = prop;
    281  1.1  riastrad 
    282  1.1  riastrad 	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
    283  1.1  riastrad 			"CRTC_H", 0, INT_MAX);
    284  1.1  riastrad 	if (!prop)
    285  1.1  riastrad 		return -ENOMEM;
    286  1.1  riastrad 	dev->mode_config.prop_crtc_h = prop;
    287  1.1  riastrad 
    288  1.1  riastrad 	prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
    289  1.1  riastrad 			"FB_ID", DRM_MODE_OBJECT_FB);
    290  1.1  riastrad 	if (!prop)
    291  1.1  riastrad 		return -ENOMEM;
    292  1.1  riastrad 	dev->mode_config.prop_fb_id = prop;
    293  1.1  riastrad 
    294  1.1  riastrad 	prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
    295  1.1  riastrad 			"IN_FENCE_FD", -1, INT_MAX);
    296  1.1  riastrad 	if (!prop)
    297  1.1  riastrad 		return -ENOMEM;
    298  1.1  riastrad 	dev->mode_config.prop_in_fence_fd = prop;
    299  1.1  riastrad 
    300  1.1  riastrad 	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
    301  1.1  riastrad 			"OUT_FENCE_PTR", 0, U64_MAX);
    302  1.1  riastrad 	if (!prop)
    303  1.1  riastrad 		return -ENOMEM;
    304  1.1  riastrad 	dev->mode_config.prop_out_fence_ptr = prop;
    305  1.1  riastrad 
    306  1.1  riastrad 	prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
    307  1.1  riastrad 			"CRTC_ID", DRM_MODE_OBJECT_CRTC);
    308  1.1  riastrad 	if (!prop)
    309  1.1  riastrad 		return -ENOMEM;
    310  1.1  riastrad 	dev->mode_config.prop_crtc_id = prop;
    311  1.1  riastrad 
    312  1.1  riastrad 	prop = drm_property_create(dev,
    313  1.1  riastrad 			DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
    314  1.1  riastrad 			"FB_DAMAGE_CLIPS", 0);
    315  1.1  riastrad 	if (!prop)
    316  1.1  riastrad 		return -ENOMEM;
    317  1.1  riastrad 	dev->mode_config.prop_fb_damage_clips = prop;
    318  1.1  riastrad 
    319  1.1  riastrad 	prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
    320  1.1  riastrad 			"ACTIVE");
    321  1.1  riastrad 	if (!prop)
    322  1.1  riastrad 		return -ENOMEM;
    323  1.1  riastrad 	dev->mode_config.prop_active = prop;
    324  1.1  riastrad 
    325  1.1  riastrad 	prop = drm_property_create(dev,
    326  1.1  riastrad 			DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
    327  1.1  riastrad 			"MODE_ID", 0);
    328  1.1  riastrad 	if (!prop)
    329  1.1  riastrad 		return -ENOMEM;
    330  1.1  riastrad 	dev->mode_config.prop_mode_id = prop;
    331  1.1  riastrad 
    332  1.1  riastrad 	prop = drm_property_create_bool(dev, 0,
    333  1.1  riastrad 			"VRR_ENABLED");
    334  1.1  riastrad 	if (!prop)
    335  1.1  riastrad 		return -ENOMEM;
    336  1.1  riastrad 	dev->mode_config.prop_vrr_enabled = prop;
    337  1.1  riastrad 
    338  1.1  riastrad 	prop = drm_property_create(dev,
    339  1.1  riastrad 			DRM_MODE_PROP_BLOB,
    340  1.1  riastrad 			"DEGAMMA_LUT", 0);
    341  1.1  riastrad 	if (!prop)
    342  1.1  riastrad 		return -ENOMEM;
    343  1.1  riastrad 	dev->mode_config.degamma_lut_property = prop;
    344  1.1  riastrad 
    345  1.1  riastrad 	prop = drm_property_create_range(dev,
    346  1.1  riastrad 			DRM_MODE_PROP_IMMUTABLE,
    347  1.1  riastrad 			"DEGAMMA_LUT_SIZE", 0, UINT_MAX);
    348  1.1  riastrad 	if (!prop)
    349  1.1  riastrad 		return -ENOMEM;
    350  1.1  riastrad 	dev->mode_config.degamma_lut_size_property = prop;
    351  1.1  riastrad 
    352  1.1  riastrad 	prop = drm_property_create(dev,
    353  1.1  riastrad 			DRM_MODE_PROP_BLOB,
    354  1.1  riastrad 			"CTM", 0);
    355  1.1  riastrad 	if (!prop)
    356  1.1  riastrad 		return -ENOMEM;
    357  1.1  riastrad 	dev->mode_config.ctm_property = prop;
    358  1.1  riastrad 
    359  1.1  riastrad 	prop = drm_property_create(dev,
    360  1.1  riastrad 			DRM_MODE_PROP_BLOB,
    361  1.1  riastrad 			"GAMMA_LUT", 0);
    362  1.1  riastrad 	if (!prop)
    363  1.1  riastrad 		return -ENOMEM;
    364  1.1  riastrad 	dev->mode_config.gamma_lut_property = prop;
    365  1.1  riastrad 
    366  1.1  riastrad 	prop = drm_property_create_range(dev,
    367  1.1  riastrad 			DRM_MODE_PROP_IMMUTABLE,
    368  1.1  riastrad 			"GAMMA_LUT_SIZE", 0, UINT_MAX);
    369  1.1  riastrad 	if (!prop)
    370  1.1  riastrad 		return -ENOMEM;
    371  1.1  riastrad 	dev->mode_config.gamma_lut_size_property = prop;
    372  1.1  riastrad 
    373  1.1  riastrad 	prop = drm_property_create(dev,
    374  1.1  riastrad 				   DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB,
    375  1.1  riastrad 				   "IN_FORMATS", 0);
    376  1.1  riastrad 	if (!prop)
    377  1.1  riastrad 		return -ENOMEM;
    378  1.1  riastrad 	dev->mode_config.modifiers_property = prop;
    379  1.1  riastrad 
    380  1.1  riastrad 	return 0;
    381  1.1  riastrad }
    382  1.1  riastrad 
    383  1.1  riastrad /**
    384  1.1  riastrad  * drm_mode_config_init - initialize DRM mode_configuration structure
    385  1.1  riastrad  * @dev: DRM device
    386  1.1  riastrad  *
    387  1.1  riastrad  * Initialize @dev's mode_config structure, used for tracking the graphics
    388  1.1  riastrad  * configuration of @dev.
    389  1.1  riastrad  *
    390  1.1  riastrad  * Since this initializes the modeset locks, no locking is possible. Which is no
    391  1.1  riastrad  * problem, since this should happen single threaded at init time. It is the
    392  1.1  riastrad  * driver's problem to ensure this guarantee.
    393  1.1  riastrad  *
    394  1.1  riastrad  */
    395  1.1  riastrad void drm_mode_config_init(struct drm_device *dev)
    396  1.1  riastrad {
    397  1.1  riastrad 	mutex_init(&dev->mode_config.mutex);
    398  1.1  riastrad 	drm_modeset_lock_init(&dev->mode_config.connection_mutex);
    399  1.1  riastrad 	mutex_init(&dev->mode_config.idr_mutex);
    400  1.1  riastrad 	mutex_init(&dev->mode_config.fb_lock);
    401  1.1  riastrad 	mutex_init(&dev->mode_config.blob_lock);
    402  1.1  riastrad 	INIT_LIST_HEAD(&dev->mode_config.fb_list);
    403  1.1  riastrad 	INIT_LIST_HEAD(&dev->mode_config.crtc_list);
    404  1.1  riastrad 	INIT_LIST_HEAD(&dev->mode_config.connector_list);
    405  1.1  riastrad 	INIT_LIST_HEAD(&dev->mode_config.encoder_list);
    406  1.1  riastrad 	INIT_LIST_HEAD(&dev->mode_config.property_list);
    407  1.1  riastrad 	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
    408  1.1  riastrad 	INIT_LIST_HEAD(&dev->mode_config.plane_list);
    409  1.1  riastrad 	INIT_LIST_HEAD(&dev->mode_config.privobj_list);
    410  1.1  riastrad 	idr_init(&dev->mode_config.object_idr);
    411  1.1  riastrad 	idr_init(&dev->mode_config.tile_idr);
    412  1.1  riastrad 	ida_init(&dev->mode_config.connector_ida);
    413  1.1  riastrad 	spin_lock_init(&dev->mode_config.connector_list_lock);
    414  1.1  riastrad 
    415  1.1  riastrad 	init_llist_head(&dev->mode_config.connector_free_list);
    416  1.1  riastrad 	INIT_WORK(&dev->mode_config.connector_free_work, drm_connector_free_work_fn);
    417  1.1  riastrad 
    418  1.1  riastrad 	drm_mode_create_standard_properties(dev);
    419  1.1  riastrad 
    420  1.1  riastrad 	/* Just to be sure */
    421  1.1  riastrad 	dev->mode_config.num_fb = 0;
    422  1.1  riastrad 	dev->mode_config.num_connector = 0;
    423  1.1  riastrad 	dev->mode_config.num_crtc = 0;
    424  1.1  riastrad 	dev->mode_config.num_encoder = 0;
    425  1.1  riastrad 	dev->mode_config.num_total_plane = 0;
    426  1.1  riastrad 
    427  1.1  riastrad 	if (IS_ENABLED(CONFIG_LOCKDEP)) {
    428  1.1  riastrad 		struct drm_modeset_acquire_ctx modeset_ctx;
    429  1.1  riastrad 		struct ww_acquire_ctx resv_ctx;
    430  1.1  riastrad 		struct dma_resv resv;
    431  1.1  riastrad 		int ret;
    432  1.1  riastrad 
    433  1.1  riastrad 		dma_resv_init(&resv);
    434  1.1  riastrad 
    435  1.1  riastrad 		drm_modeset_acquire_init(&modeset_ctx, 0);
    436  1.1  riastrad 		ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
    437  1.1  riastrad 				       &modeset_ctx);
    438  1.1  riastrad 		if (ret == -EDEADLK)
    439  1.1  riastrad 			ret = drm_modeset_backoff(&modeset_ctx);
    440  1.1  riastrad 
    441  1.1  riastrad 		ww_acquire_init(&resv_ctx, &reservation_ww_class);
    442  1.1  riastrad 		ret = dma_resv_lock(&resv, &resv_ctx);
    443  1.1  riastrad 		if (ret == -EDEADLK)
    444  1.1  riastrad 			dma_resv_lock_slow(&resv, &resv_ctx);
    445  1.1  riastrad 
    446  1.1  riastrad 		dma_resv_unlock(&resv);
    447  1.1  riastrad 		ww_acquire_fini(&resv_ctx);
    448  1.1  riastrad 
    449  1.1  riastrad 		drm_modeset_drop_locks(&modeset_ctx);
    450  1.1  riastrad 		drm_modeset_acquire_fini(&modeset_ctx);
    451  1.1  riastrad 		dma_resv_fini(&resv);
    452  1.1  riastrad 	}
    453  1.1  riastrad }
    454  1.1  riastrad EXPORT_SYMBOL(drm_mode_config_init);
    455  1.1  riastrad 
    456  1.1  riastrad /**
    457  1.1  riastrad  * drm_mode_config_cleanup - free up DRM mode_config info
    458  1.1  riastrad  * @dev: DRM device
    459  1.1  riastrad  *
    460  1.1  riastrad  * Free up all the connectors and CRTCs associated with this DRM device, then
    461  1.1  riastrad  * free up the framebuffers and associated buffer objects.
    462  1.1  riastrad  *
    463  1.1  riastrad  * Note that since this /should/ happen single-threaded at driver/device
    464  1.1  riastrad  * teardown time, no locking is required. It's the driver's job to ensure that
    465  1.1  riastrad  * this guarantee actually holds true.
    466  1.1  riastrad  */
    467  1.1  riastrad void drm_mode_config_cleanup(struct drm_device *dev)
    468  1.1  riastrad {
    469  1.1  riastrad 	struct drm_connector *connector;
    470  1.1  riastrad 	struct drm_connector_list_iter conn_iter;
    471  1.1  riastrad 	struct drm_crtc *crtc, *ct;
    472  1.1  riastrad 	struct drm_encoder *encoder, *enct;
    473  1.1  riastrad 	struct drm_framebuffer *fb, *fbt;
    474  1.1  riastrad 	struct drm_property *property, *pt;
    475  1.1  riastrad 	struct drm_property_blob *blob, *bt;
    476  1.1  riastrad 	struct drm_plane *plane, *plt;
    477  1.1  riastrad 
    478  1.1  riastrad 	list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
    479  1.1  riastrad 				 head) {
    480  1.1  riastrad 		encoder->funcs->destroy(encoder);
    481  1.1  riastrad 	}
    482  1.1  riastrad 
    483  1.1  riastrad 	drm_connector_list_iter_begin(dev, &conn_iter);
    484  1.1  riastrad 	drm_for_each_connector_iter(connector, &conn_iter) {
    485  1.1  riastrad 		/* drm_connector_list_iter holds an full reference to the
    486  1.1  riastrad 		 * current connector itself, which means it is inherently safe
    487  1.1  riastrad 		 * against unreferencing the current connector - but not against
    488  1.1  riastrad 		 * deleting it right away. */
    489  1.1  riastrad 		drm_connector_put(connector);
    490  1.1  riastrad 	}
    491  1.1  riastrad 	drm_connector_list_iter_end(&conn_iter);
    492  1.1  riastrad 	/* connector_iter drops references in a work item. */
    493  1.1  riastrad 	flush_work(&dev->mode_config.connector_free_work);
    494  1.1  riastrad 	if (WARN_ON(!list_empty(&dev->mode_config.connector_list))) {
    495  1.1  riastrad 		drm_connector_list_iter_begin(dev, &conn_iter);
    496  1.1  riastrad 		drm_for_each_connector_iter(connector, &conn_iter)
    497  1.1  riastrad 			DRM_ERROR("connector %s leaked!\n", connector->name);
    498  1.1  riastrad 		drm_connector_list_iter_end(&conn_iter);
    499  1.1  riastrad 	}
    500  1.1  riastrad 
    501  1.1  riastrad 	list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
    502  1.1  riastrad 				 head) {
    503  1.1  riastrad 		drm_property_destroy(dev, property);
    504  1.1  riastrad 	}
    505  1.1  riastrad 
    506  1.1  riastrad 	list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
    507  1.1  riastrad 				 head) {
    508  1.1  riastrad 		plane->funcs->destroy(plane);
    509  1.1  riastrad 	}
    510  1.1  riastrad 
    511  1.1  riastrad 	list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
    512  1.1  riastrad 		crtc->funcs->destroy(crtc);
    513  1.1  riastrad 	}
    514  1.1  riastrad 
    515  1.1  riastrad 	list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
    516  1.1  riastrad 				 head_global) {
    517  1.1  riastrad 		drm_property_blob_put(blob);
    518  1.1  riastrad 	}
    519  1.1  riastrad 
    520  1.1  riastrad 	/*
    521  1.1  riastrad 	 * Single-threaded teardown context, so it's not required to grab the
    522  1.1  riastrad 	 * fb_lock to protect against concurrent fb_list access. Contrary, it
    523  1.1  riastrad 	 * would actually deadlock with the drm_framebuffer_cleanup function.
    524  1.1  riastrad 	 *
    525  1.1  riastrad 	 * Also, if there are any framebuffers left, that's a driver leak now,
    526  1.1  riastrad 	 * so politely WARN about this.
    527  1.1  riastrad 	 */
    528  1.1  riastrad 	WARN_ON(!list_empty(&dev->mode_config.fb_list));
    529  1.1  riastrad 	list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
    530  1.1  riastrad 		struct drm_printer p = drm_debug_printer("[leaked fb]");
    531  1.1  riastrad 		drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
    532  1.1  riastrad 		drm_framebuffer_print_info(&p, 1, fb);
    533  1.1  riastrad 		drm_framebuffer_free(&fb->base.refcount);
    534  1.1  riastrad 	}
    535  1.1  riastrad 
    536  1.5  riastrad 	spin_lock_destroy(&dev->mode_config.connector_list_lock);
    537  1.1  riastrad 	ida_destroy(&dev->mode_config.connector_ida);
    538  1.1  riastrad 	idr_destroy(&dev->mode_config.tile_idr);
    539  1.1  riastrad 	idr_destroy(&dev->mode_config.object_idr);
    540  1.5  riastrad 	mutex_destroy(&dev->mode_config.blob_lock);
    541  1.5  riastrad 	mutex_destroy(&dev->mode_config.fb_lock);
    542  1.5  riastrad 	mutex_destroy(&dev->mode_config.idr_mutex);
    543  1.1  riastrad 	drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
    544  1.5  riastrad 	mutex_destroy(&dev->mode_config.mutex);
    545  1.1  riastrad }
    546  1.1  riastrad EXPORT_SYMBOL(drm_mode_config_cleanup);
    547