aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c717
1 files changed, 299 insertions, 418 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 0e3cc66aa8b7..f1d9f0569d7f 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -39,6 +39,7 @@
39#include <drm/drm_fourcc.h> 39#include <drm/drm_fourcc.h>
40#include <drm/drm_modeset_lock.h> 40#include <drm/drm_modeset_lock.h>
41#include <drm/drm_atomic.h> 41#include <drm/drm_atomic.h>
42#include <drm/drm_auth.h>
42 43
43#include "drm_crtc_internal.h" 44#include "drm_crtc_internal.h"
44#include "drm_internal.h" 45#include "drm_internal.h"
@@ -239,37 +240,6 @@ const char *drm_get_subpixel_order_name(enum subpixel_order order)
239} 240}
240EXPORT_SYMBOL(drm_get_subpixel_order_name); 241EXPORT_SYMBOL(drm_get_subpixel_order_name);
241 242
242static char printable_char(int c)
243{
244 return isascii(c) && isprint(c) ? c : '?';
245}
246
247/**
248 * drm_get_format_name - return a string for drm fourcc format
249 * @format: format to compute name of
250 *
251 * Note that the buffer used by this function is globally shared and owned by
252 * the function itself.
253 *
254 * FIXME: This isn't really multithreading safe.
255 */
256const char *drm_get_format_name(uint32_t format)
257{
258 static char buf[32];
259
260 snprintf(buf, sizeof(buf),
261 "%c%c%c%c %s-endian (0x%08x)",
262 printable_char(format & 0xff),
263 printable_char((format >> 8) & 0xff),
264 printable_char((format >> 16) & 0xff),
265 printable_char((format >> 24) & 0x7f),
266 format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
267 format);
268
269 return buf;
270}
271EXPORT_SYMBOL(drm_get_format_name);
272
273/* 243/*
274 * Internal function to assign a slot in the object idr and optionally 244 * Internal function to assign a slot in the object idr and optionally
275 * register the object into the idr. 245 * register the object into the idr.
@@ -426,6 +396,51 @@ void drm_mode_object_reference(struct drm_mode_object *obj)
426} 396}
427EXPORT_SYMBOL(drm_mode_object_reference); 397EXPORT_SYMBOL(drm_mode_object_reference);
428 398
399/**
400 * drm_crtc_force_disable - Forcibly turn off a CRTC
401 * @crtc: CRTC to turn off
402 *
403 * Returns:
404 * Zero on success, error code on failure.
405 */
406int drm_crtc_force_disable(struct drm_crtc *crtc)
407{
408 struct drm_mode_set set = {
409 .crtc = crtc,
410 };
411
412 return drm_mode_set_config_internal(&set);
413}
414EXPORT_SYMBOL(drm_crtc_force_disable);
415
416/**
417 * drm_crtc_force_disable_all - Forcibly turn off all enabled CRTCs
418 * @dev: DRM device whose CRTCs to turn off
419 *
420 * Drivers may want to call this on unload to ensure that all displays are
421 * unlit and the GPU is in a consistent, low power state. Takes modeset locks.
422 *
423 * Returns:
424 * Zero on success, error code on failure.
425 */
426int drm_crtc_force_disable_all(struct drm_device *dev)
427{
428 struct drm_crtc *crtc;
429 int ret = 0;
430
431 drm_modeset_lock_all(dev);
432 drm_for_each_crtc(crtc, dev)
433 if (crtc->enabled) {
434 ret = drm_crtc_force_disable(crtc);
435 if (ret)
436 goto out;
437 }
438out:
439 drm_modeset_unlock_all(dev);
440 return ret;
441}
442EXPORT_SYMBOL(drm_crtc_force_disable_all);
443
429static void drm_framebuffer_free(struct kref *kref) 444static void drm_framebuffer_free(struct kref *kref)
430{ 445{
431 struct drm_framebuffer *fb = 446 struct drm_framebuffer *fb =
@@ -535,7 +550,7 @@ EXPORT_SYMBOL(drm_framebuffer_unregister_private);
535 * 550 *
536 * Cleanup framebuffer. This function is intended to be used from the drivers 551 * Cleanup framebuffer. This function is intended to be used from the drivers
537 * ->destroy callback. It can also be used to clean up driver private 552 * ->destroy callback. It can also be used to clean up driver private
538 * framebuffers embedded into a larger structure. 553 * framebuffers embedded into a larger structure.
539 * 554 *
540 * Note that this function does not remove the fb from active usuage - if it is 555 * Note that this function does not remove the fb from active usuage - if it is
541 * still used anywhere, hilarity can ensue since userspace could call getfb on 556 * still used anywhere, hilarity can ensue since userspace could call getfb on
@@ -574,8 +589,6 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
574 struct drm_device *dev; 589 struct drm_device *dev;
575 struct drm_crtc *crtc; 590 struct drm_crtc *crtc;
576 struct drm_plane *plane; 591 struct drm_plane *plane;
577 struct drm_mode_set set;
578 int ret;
579 592
580 if (!fb) 593 if (!fb)
581 return; 594 return;
@@ -605,11 +618,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
605 drm_for_each_crtc(crtc, dev) { 618 drm_for_each_crtc(crtc, dev) {
606 if (crtc->primary->fb == fb) { 619 if (crtc->primary->fb == fb) {
607 /* should turn off the crtc */ 620 /* should turn off the crtc */
608 memset(&set, 0, sizeof(struct drm_mode_set)); 621 if (drm_crtc_force_disable(crtc))
609 set.crtc = crtc;
610 set.fb = NULL;
611 ret = drm_mode_set_config_internal(&set);
612 if (ret)
613 DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); 622 DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
614 } 623 }
615 } 624 }
@@ -639,6 +648,31 @@ static unsigned int drm_num_crtcs(struct drm_device *dev)
639 return num; 648 return num;
640} 649}
641 650
651static int drm_crtc_register_all(struct drm_device *dev)
652{
653 struct drm_crtc *crtc;
654 int ret = 0;
655
656 drm_for_each_crtc(crtc, dev) {
657 if (crtc->funcs->late_register)
658 ret = crtc->funcs->late_register(crtc);
659 if (ret)
660 return ret;
661 }
662
663 return 0;
664}
665
666static void drm_crtc_unregister_all(struct drm_device *dev)
667{
668 struct drm_crtc *crtc;
669
670 drm_for_each_crtc(crtc, dev) {
671 if (crtc->funcs->early_unregister)
672 crtc->funcs->early_unregister(crtc);
673 }
674}
675
642/** 676/**
643 * drm_crtc_init_with_planes - Initialise a new CRTC object with 677 * drm_crtc_init_with_planes - Initialise a new CRTC object with
644 * specified primary and cursor planes. 678 * specified primary and cursor planes.
@@ -669,6 +703,9 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
669 crtc->dev = dev; 703 crtc->dev = dev;
670 crtc->funcs = funcs; 704 crtc->funcs = funcs;
671 705
706 INIT_LIST_HEAD(&crtc->commit_list);
707 spin_lock_init(&crtc->commit_lock);
708
672 drm_modeset_lock_init(&crtc->mutex); 709 drm_modeset_lock_init(&crtc->mutex);
673 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); 710 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
674 if (ret) 711 if (ret)
@@ -692,7 +729,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
692 crtc->base.properties = &crtc->properties; 729 crtc->base.properties = &crtc->properties;
693 730
694 list_add_tail(&crtc->head, &config->crtc_list); 731 list_add_tail(&crtc->head, &config->crtc_list);
695 config->num_crtc++; 732 crtc->index = config->num_crtc++;
696 733
697 crtc->primary = primary; 734 crtc->primary = primary;
698 crtc->cursor = cursor; 735 crtc->cursor = cursor;
@@ -722,6 +759,11 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
722{ 759{
723 struct drm_device *dev = crtc->dev; 760 struct drm_device *dev = crtc->dev;
724 761
762 /* Note that the crtc_list is considered to be static; should we
763 * remove the drm_crtc at runtime we would have to decrement all
764 * the indices on the drm_crtc after us in the crtc_list.
765 */
766
725 kfree(crtc->gamma_store); 767 kfree(crtc->gamma_store);
726 crtc->gamma_store = NULL; 768 crtc->gamma_store = NULL;
727 769
@@ -741,29 +783,6 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
741} 783}
742EXPORT_SYMBOL(drm_crtc_cleanup); 784EXPORT_SYMBOL(drm_crtc_cleanup);
743 785
744/**
745 * drm_crtc_index - find the index of a registered CRTC
746 * @crtc: CRTC to find index for
747 *
748 * Given a registered CRTC, return the index of that CRTC within a DRM
749 * device's list of CRTCs.
750 */
751unsigned int drm_crtc_index(struct drm_crtc *crtc)
752{
753 unsigned int index = 0;
754 struct drm_crtc *tmp;
755
756 drm_for_each_crtc(tmp, crtc->dev) {
757 if (tmp == crtc)
758 return index;
759
760 index++;
761 }
762
763 BUG();
764}
765EXPORT_SYMBOL(drm_crtc_index);
766
767/* 786/*
768 * drm_mode_remove - remove and free a mode 787 * drm_mode_remove - remove and free a mode
769 * @connector: connector list to modify 788 * @connector: connector list to modify
@@ -909,11 +928,11 @@ int drm_connector_init(struct drm_device *dev,
909 connector->dev = dev; 928 connector->dev = dev;
910 connector->funcs = funcs; 929 connector->funcs = funcs;
911 930
912 connector->connector_id = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL); 931 ret = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL);
913 if (connector->connector_id < 0) { 932 if (ret < 0)
914 ret = connector->connector_id;
915 goto out_put; 933 goto out_put;
916 } 934 connector->index = ret;
935 ret = 0;
917 936
918 connector->connector_type = connector_type; 937 connector->connector_type = connector_type;
919 connector->connector_type_id = 938 connector->connector_type_id =
@@ -961,7 +980,7 @@ out_put_type_id:
961 ida_remove(connector_ida, connector->connector_type_id); 980 ida_remove(connector_ida, connector->connector_type_id);
962out_put_id: 981out_put_id:
963 if (ret) 982 if (ret)
964 ida_remove(&config->connector_ida, connector->connector_id); 983 ida_remove(&config->connector_ida, connector->index);
965out_put: 984out_put:
966 if (ret) 985 if (ret)
967 drm_mode_object_unregister(dev, &connector->base); 986 drm_mode_object_unregister(dev, &connector->base);
@@ -984,6 +1003,12 @@ void drm_connector_cleanup(struct drm_connector *connector)
984 struct drm_device *dev = connector->dev; 1003 struct drm_device *dev = connector->dev;
985 struct drm_display_mode *mode, *t; 1004 struct drm_display_mode *mode, *t;
986 1005
1006 /* The connector should have been removed from userspace long before
1007 * it is finally destroyed.
1008 */
1009 if (WARN_ON(connector->registered))
1010 drm_connector_unregister(connector);
1011
987 if (connector->tile_group) { 1012 if (connector->tile_group) {
988 drm_mode_put_tile_group(dev, connector->tile_group); 1013 drm_mode_put_tile_group(dev, connector->tile_group);
989 connector->tile_group = NULL; 1014 connector->tile_group = NULL;
@@ -999,7 +1024,7 @@ void drm_connector_cleanup(struct drm_connector *connector)
999 connector->connector_type_id); 1024 connector->connector_type_id);
1000 1025
1001 ida_remove(&dev->mode_config.connector_ida, 1026 ida_remove(&dev->mode_config.connector_ida,
1002 connector->connector_id); 1027 connector->index);
1003 1028
1004 kfree(connector->display_info.bus_formats); 1029 kfree(connector->display_info.bus_formats);
1005 drm_mode_object_unregister(dev, &connector->base); 1030 drm_mode_object_unregister(dev, &connector->base);
@@ -1030,19 +1055,34 @@ int drm_connector_register(struct drm_connector *connector)
1030{ 1055{
1031 int ret; 1056 int ret;
1032 1057
1058 if (connector->registered)
1059 return 0;
1060
1033 ret = drm_sysfs_connector_add(connector); 1061 ret = drm_sysfs_connector_add(connector);
1034 if (ret) 1062 if (ret)
1035 return ret; 1063 return ret;
1036 1064
1037 ret = drm_debugfs_connector_add(connector); 1065 ret = drm_debugfs_connector_add(connector);
1038 if (ret) { 1066 if (ret) {
1039 drm_sysfs_connector_remove(connector); 1067 goto err_sysfs;
1040 return ret; 1068 }
1069
1070 if (connector->funcs->late_register) {
1071 ret = connector->funcs->late_register(connector);
1072 if (ret)
1073 goto err_debugfs;
1041 } 1074 }
1042 1075
1043 drm_mode_object_register(connector->dev, &connector->base); 1076 drm_mode_object_register(connector->dev, &connector->base);
1044 1077
1078 connector->registered = true;
1045 return 0; 1079 return 0;
1080
1081err_debugfs:
1082 drm_debugfs_connector_remove(connector);
1083err_sysfs:
1084 drm_sysfs_connector_remove(connector);
1085 return ret;
1046} 1086}
1047EXPORT_SYMBOL(drm_connector_register); 1087EXPORT_SYMBOL(drm_connector_register);
1048 1088
@@ -1054,28 +1094,29 @@ EXPORT_SYMBOL(drm_connector_register);
1054 */ 1094 */
1055void drm_connector_unregister(struct drm_connector *connector) 1095void drm_connector_unregister(struct drm_connector *connector)
1056{ 1096{
1097 if (!connector->registered)
1098 return;
1099
1100 if (connector->funcs->early_unregister)
1101 connector->funcs->early_unregister(connector);
1102
1057 drm_sysfs_connector_remove(connector); 1103 drm_sysfs_connector_remove(connector);
1058 drm_debugfs_connector_remove(connector); 1104 drm_debugfs_connector_remove(connector);
1105
1106 connector->registered = false;
1059} 1107}
1060EXPORT_SYMBOL(drm_connector_unregister); 1108EXPORT_SYMBOL(drm_connector_unregister);
1061 1109
1062/** 1110static void drm_connector_unregister_all(struct drm_device *dev)
1063 * drm_connector_register_all - register all connectors 1111{
1064 * @dev: drm device 1112 struct drm_connector *connector;
1065 * 1113
1066 * This function registers all connectors in sysfs and other places so that 1114 /* FIXME: taking the mode config mutex ends up in a clash with sysfs */
1067 * userspace can start to access them. Drivers can call it after calling 1115 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
1068 * drm_dev_register() to complete the device registration, if they don't call 1116 drm_connector_unregister(connector);
1069 * drm_connector_register() on each connector individually. 1117}
1070 * 1118
1071 * When a device is unplugged and should be removed from userspace access, 1119static int drm_connector_register_all(struct drm_device *dev)
1072 * call drm_connector_unregister_all(), which is the inverse of this
1073 * function.
1074 *
1075 * Returns:
1076 * Zero on success, error code on failure.
1077 */
1078int drm_connector_register_all(struct drm_device *dev)
1079{ 1120{
1080 struct drm_connector *connector; 1121 struct drm_connector *connector;
1081 int ret; 1122 int ret;
@@ -1097,27 +1138,31 @@ err:
1097 drm_connector_unregister_all(dev); 1138 drm_connector_unregister_all(dev);
1098 return ret; 1139 return ret;
1099} 1140}
1100EXPORT_SYMBOL(drm_connector_register_all);
1101 1141
1102/** 1142static int drm_encoder_register_all(struct drm_device *dev)
1103 * drm_connector_unregister_all - unregister connector userspace interfaces
1104 * @dev: drm device
1105 *
1106 * This functions unregisters all connectors from sysfs and other places so
1107 * that userspace can no longer access them. Drivers should call this as the
1108 * first step tearing down the device instace, or when the underlying
1109 * physical device disappeared (e.g. USB unplug), right before calling
1110 * drm_dev_unregister().
1111 */
1112void drm_connector_unregister_all(struct drm_device *dev)
1113{ 1143{
1114 struct drm_connector *connector; 1144 struct drm_encoder *encoder;
1145 int ret = 0;
1115 1146
1116 /* FIXME: taking the mode config mutex ends up in a clash with sysfs */ 1147 drm_for_each_encoder(encoder, dev) {
1117 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 1148 if (encoder->funcs->late_register)
1118 drm_connector_unregister(connector); 1149 ret = encoder->funcs->late_register(encoder);
1150 if (ret)
1151 return ret;
1152 }
1153
1154 return 0;
1155}
1156
1157static void drm_encoder_unregister_all(struct drm_device *dev)
1158{
1159 struct drm_encoder *encoder;
1160
1161 drm_for_each_encoder(encoder, dev) {
1162 if (encoder->funcs->early_unregister)
1163 encoder->funcs->early_unregister(encoder);
1164 }
1119} 1165}
1120EXPORT_SYMBOL(drm_connector_unregister_all);
1121 1166
1122/** 1167/**
1123 * drm_encoder_init - Init a preallocated encoder 1168 * drm_encoder_init - Init a preallocated encoder
@@ -1166,7 +1211,7 @@ int drm_encoder_init(struct drm_device *dev,
1166 } 1211 }
1167 1212
1168 list_add_tail(&encoder->head, &dev->mode_config.encoder_list); 1213 list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
1169 dev->mode_config.num_encoder++; 1214 encoder->index = dev->mode_config.num_encoder++;
1170 1215
1171out_put: 1216out_put:
1172 if (ret) 1217 if (ret)
@@ -1180,29 +1225,6 @@ out_unlock:
1180EXPORT_SYMBOL(drm_encoder_init); 1225EXPORT_SYMBOL(drm_encoder_init);
1181 1226
1182/** 1227/**
1183 * drm_encoder_index - find the index of a registered encoder
1184 * @encoder: encoder to find index for
1185 *
1186 * Given a registered encoder, return the index of that encoder within a DRM
1187 * device's list of encoders.
1188 */
1189unsigned int drm_encoder_index(struct drm_encoder *encoder)
1190{
1191 unsigned int index = 0;
1192 struct drm_encoder *tmp;
1193
1194 drm_for_each_encoder(tmp, encoder->dev) {
1195 if (tmp == encoder)
1196 return index;
1197
1198 index++;
1199 }
1200
1201 BUG();
1202}
1203EXPORT_SYMBOL(drm_encoder_index);
1204
1205/**
1206 * drm_encoder_cleanup - cleans up an initialised encoder 1228 * drm_encoder_cleanup - cleans up an initialised encoder
1207 * @encoder: encoder to cleanup 1229 * @encoder: encoder to cleanup
1208 * 1230 *
@@ -1212,6 +1234,11 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
1212{ 1234{
1213 struct drm_device *dev = encoder->dev; 1235 struct drm_device *dev = encoder->dev;
1214 1236
1237 /* Note that the encoder_list is considered to be static; should we
1238 * remove the drm_encoder at runtime we would have to decrement all
1239 * the indices on the drm_encoder after us in the encoder_list.
1240 */
1241
1215 drm_modeset_lock_all(dev); 1242 drm_modeset_lock_all(dev);
1216 drm_mode_object_unregister(dev, &encoder->base); 1243 drm_mode_object_unregister(dev, &encoder->base);
1217 kfree(encoder->name); 1244 kfree(encoder->name);
@@ -1300,7 +1327,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
1300 plane->type = type; 1327 plane->type = type;
1301 1328
1302 list_add_tail(&plane->head, &config->plane_list); 1329 list_add_tail(&plane->head, &config->plane_list);
1303 config->num_total_plane++; 1330 plane->index = config->num_total_plane++;
1304 if (plane->type == DRM_PLANE_TYPE_OVERLAY) 1331 if (plane->type == DRM_PLANE_TYPE_OVERLAY)
1305 config->num_overlay_plane++; 1332 config->num_overlay_plane++;
1306 1333
@@ -1325,6 +1352,31 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
1325} 1352}
1326EXPORT_SYMBOL(drm_universal_plane_init); 1353EXPORT_SYMBOL(drm_universal_plane_init);
1327 1354
1355static int drm_plane_register_all(struct drm_device *dev)
1356{
1357 struct drm_plane *plane;
1358 int ret = 0;
1359
1360 drm_for_each_plane(plane, dev) {
1361 if (plane->funcs->late_register)
1362 ret = plane->funcs->late_register(plane);
1363 if (ret)
1364 return ret;
1365 }
1366
1367 return 0;
1368}
1369
1370static void drm_plane_unregister_all(struct drm_device *dev)
1371{
1372 struct drm_plane *plane;
1373
1374 drm_for_each_plane(plane, dev) {
1375 if (plane->funcs->early_unregister)
1376 plane->funcs->early_unregister(plane);
1377 }
1378}
1379
1328/** 1380/**
1329 * drm_plane_init - Initialize a legacy plane 1381 * drm_plane_init - Initialize a legacy plane
1330 * @dev: DRM device 1382 * @dev: DRM device
@@ -1374,6 +1426,11 @@ void drm_plane_cleanup(struct drm_plane *plane)
1374 1426
1375 BUG_ON(list_empty(&plane->head)); 1427 BUG_ON(list_empty(&plane->head));
1376 1428
1429 /* Note that the plane_list is considered to be static; should we
1430 * remove the drm_plane at runtime we would have to decrement all
1431 * the indices on the drm_plane after us in the plane_list.
1432 */
1433
1377 list_del(&plane->head); 1434 list_del(&plane->head);
1378 dev->mode_config.num_total_plane--; 1435 dev->mode_config.num_total_plane--;
1379 if (plane->type == DRM_PLANE_TYPE_OVERLAY) 1436 if (plane->type == DRM_PLANE_TYPE_OVERLAY)
@@ -1391,29 +1448,6 @@ void drm_plane_cleanup(struct drm_plane *plane)
1391EXPORT_SYMBOL(drm_plane_cleanup); 1448EXPORT_SYMBOL(drm_plane_cleanup);
1392 1449
1393/** 1450/**
1394 * drm_plane_index - find the index of a registered plane
1395 * @plane: plane to find index for
1396 *
1397 * Given a registered plane, return the index of that CRTC within a DRM
1398 * device's list of planes.
1399 */
1400unsigned int drm_plane_index(struct drm_plane *plane)
1401{
1402 unsigned int index = 0;
1403 struct drm_plane *tmp;
1404
1405 drm_for_each_plane(tmp, plane->dev) {
1406 if (tmp == plane)
1407 return index;
1408
1409 index++;
1410 }
1411
1412 BUG();
1413}
1414EXPORT_SYMBOL(drm_plane_index);
1415
1416/**
1417 * drm_plane_from_index - find the registered plane at an index 1451 * drm_plane_from_index - find the registered plane at an index
1418 * @dev: DRM device 1452 * @dev: DRM device
1419 * @idx: index of registered plane to find for 1453 * @idx: index of registered plane to find for
@@ -1425,13 +1459,11 @@ struct drm_plane *
1425drm_plane_from_index(struct drm_device *dev, int idx) 1459drm_plane_from_index(struct drm_device *dev, int idx)
1426{ 1460{
1427 struct drm_plane *plane; 1461 struct drm_plane *plane;
1428 unsigned int i = 0;
1429 1462
1430 drm_for_each_plane(plane, dev) { 1463 drm_for_each_plane(plane, dev)
1431 if (i == idx) 1464 if (idx == plane->index)
1432 return plane; 1465 return plane;
1433 i++; 1466
1434 }
1435 return NULL; 1467 return NULL;
1436} 1468}
1437EXPORT_SYMBOL(drm_plane_from_index); 1469EXPORT_SYMBOL(drm_plane_from_index);
@@ -1467,6 +1499,46 @@ void drm_plane_force_disable(struct drm_plane *plane)
1467} 1499}
1468EXPORT_SYMBOL(drm_plane_force_disable); 1500EXPORT_SYMBOL(drm_plane_force_disable);
1469 1501
1502int drm_modeset_register_all(struct drm_device *dev)
1503{
1504 int ret;
1505
1506 ret = drm_plane_register_all(dev);
1507 if (ret)
1508 goto err_plane;
1509
1510 ret = drm_crtc_register_all(dev);
1511 if (ret)
1512 goto err_crtc;
1513
1514 ret = drm_encoder_register_all(dev);
1515 if (ret)
1516 goto err_encoder;
1517
1518 ret = drm_connector_register_all(dev);
1519 if (ret)
1520 goto err_connector;
1521
1522 return 0;
1523
1524err_connector:
1525 drm_encoder_unregister_all(dev);
1526err_encoder:
1527 drm_crtc_unregister_all(dev);
1528err_crtc:
1529 drm_plane_unregister_all(dev);
1530err_plane:
1531 return ret;
1532}
1533
1534void drm_modeset_unregister_all(struct drm_device *dev)
1535{
1536 drm_connector_unregister_all(dev);
1537 drm_encoder_unregister_all(dev);
1538 drm_crtc_unregister_all(dev);
1539 drm_plane_unregister_all(dev);
1540}
1541
1470static int drm_mode_create_standard_properties(struct drm_device *dev) 1542static int drm_mode_create_standard_properties(struct drm_device *dev)
1471{ 1543{
1472 struct drm_property *prop; 1544 struct drm_property *prop;
@@ -2975,6 +3047,8 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
2975 DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n"); 3047 DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
2976 return PTR_ERR(fb); 3048 return PTR_ERR(fb);
2977 } 3049 }
3050 fb->hot_x = req->hot_x;
3051 fb->hot_y = req->hot_y;
2978 } else { 3052 } else {
2979 fb = NULL; 3053 fb = NULL;
2980 } 3054 }
@@ -3581,7 +3655,7 @@ int drm_mode_getfb(struct drm_device *dev,
3581 r->bpp = fb->bits_per_pixel; 3655 r->bpp = fb->bits_per_pixel;
3582 r->pitch = fb->pitches[0]; 3656 r->pitch = fb->pitches[0];
3583 if (fb->funcs->create_handle) { 3657 if (fb->funcs->create_handle) {
3584 if (file_priv->is_master || capable(CAP_SYS_ADMIN) || 3658 if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) ||
3585 drm_is_control_client(file_priv)) { 3659 drm_is_control_client(file_priv)) {
3586 ret = fb->funcs->create_handle(fb, file_priv, 3660 ret = fb->funcs->create_handle(fb, file_priv,
3587 &r->handle); 3661 &r->handle);
@@ -3738,6 +3812,13 @@ void drm_fb_release(struct drm_file *priv)
3738 } 3812 }
3739} 3813}
3740 3814
3815static bool drm_property_type_valid(struct drm_property *property)
3816{
3817 if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
3818 return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
3819 return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
3820}
3821
3741/** 3822/**
3742 * drm_property_create - create a new property type 3823 * drm_property_create - create a new property type
3743 * @dev: drm device 3824 * @dev: drm device
@@ -5138,6 +5219,9 @@ EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
5138int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, 5219int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
5139 int gamma_size) 5220 int gamma_size)
5140{ 5221{
5222 uint16_t *r_base, *g_base, *b_base;
5223 int i;
5224
5141 crtc->gamma_size = gamma_size; 5225 crtc->gamma_size = gamma_size;
5142 5226
5143 crtc->gamma_store = kcalloc(gamma_size, sizeof(uint16_t) * 3, 5227 crtc->gamma_store = kcalloc(gamma_size, sizeof(uint16_t) * 3,
@@ -5147,6 +5231,16 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
5147 return -ENOMEM; 5231 return -ENOMEM;
5148 } 5232 }
5149 5233
5234 r_base = crtc->gamma_store;
5235 g_base = r_base + gamma_size;
5236 b_base = g_base + gamma_size;
5237 for (i = 0; i < gamma_size; i++) {
5238 r_base[i] = i << 8;
5239 g_base[i] = i << 8;
5240 b_base[i] = i << 8;
5241 }
5242
5243
5150 return 0; 5244 return 0;
5151} 5245}
5152EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size); 5246EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
@@ -5214,7 +5308,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
5214 goto out; 5308 goto out;
5215 } 5309 }
5216 5310
5217 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); 5311 ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size);
5218 5312
5219out: 5313out:
5220 drm_modeset_unlock_all(dev); 5314 drm_modeset_unlock_all(dev);
@@ -5544,264 +5638,6 @@ int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
5544} 5638}
5545 5639
5546/** 5640/**
5547 * drm_fb_get_bpp_depth - get the bpp/depth values for format
5548 * @format: pixel format (DRM_FORMAT_*)
5549 * @depth: storage for the depth value
5550 * @bpp: storage for the bpp value
5551 *
5552 * This only supports RGB formats here for compat with code that doesn't use
5553 * pixel formats directly yet.
5554 */
5555void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
5556 int *bpp)
5557{
5558 switch (format) {
5559 case DRM_FORMAT_C8:
5560 case DRM_FORMAT_RGB332:
5561 case DRM_FORMAT_BGR233:
5562 *depth = 8;
5563 *bpp = 8;
5564 break;
5565 case DRM_FORMAT_XRGB1555:
5566 case DRM_FORMAT_XBGR1555:
5567 case DRM_FORMAT_RGBX5551:
5568 case DRM_FORMAT_BGRX5551:
5569 case DRM_FORMAT_ARGB1555:
5570 case DRM_FORMAT_ABGR1555:
5571 case DRM_FORMAT_RGBA5551:
5572 case DRM_FORMAT_BGRA5551:
5573 *depth = 15;
5574 *bpp = 16;
5575 break;
5576 case DRM_FORMAT_RGB565:
5577 case DRM_FORMAT_BGR565:
5578 *depth = 16;
5579 *bpp = 16;
5580 break;
5581 case DRM_FORMAT_RGB888:
5582 case DRM_FORMAT_BGR888:
5583 *depth = 24;
5584 *bpp = 24;
5585 break;
5586 case DRM_FORMAT_XRGB8888:
5587 case DRM_FORMAT_XBGR8888:
5588 case DRM_FORMAT_RGBX8888:
5589 case DRM_FORMAT_BGRX8888:
5590 *depth = 24;
5591 *bpp = 32;
5592 break;
5593 case DRM_FORMAT_XRGB2101010:
5594 case DRM_FORMAT_XBGR2101010:
5595 case DRM_FORMAT_RGBX1010102:
5596 case DRM_FORMAT_BGRX1010102:
5597 case DRM_FORMAT_ARGB2101010:
5598 case DRM_FORMAT_ABGR2101010:
5599 case DRM_FORMAT_RGBA1010102:
5600 case DRM_FORMAT_BGRA1010102:
5601 *depth = 30;
5602 *bpp = 32;
5603 break;
5604 case DRM_FORMAT_ARGB8888:
5605 case DRM_FORMAT_ABGR8888:
5606 case DRM_FORMAT_RGBA8888:
5607 case DRM_FORMAT_BGRA8888:
5608 *depth = 32;
5609 *bpp = 32;
5610 break;
5611 default:
5612 DRM_DEBUG_KMS("unsupported pixel format %s\n",
5613 drm_get_format_name(format));
5614 *depth = 0;
5615 *bpp = 0;
5616 break;
5617 }
5618}
5619EXPORT_SYMBOL(drm_fb_get_bpp_depth);
5620
5621/**
5622 * drm_format_num_planes - get the number of planes for format
5623 * @format: pixel format (DRM_FORMAT_*)
5624 *
5625 * Returns:
5626 * The number of planes used by the specified pixel format.
5627 */
5628int drm_format_num_planes(uint32_t format)
5629{
5630 switch (format) {
5631 case DRM_FORMAT_YUV410:
5632 case DRM_FORMAT_YVU410:
5633 case DRM_FORMAT_YUV411:
5634 case DRM_FORMAT_YVU411:
5635 case DRM_FORMAT_YUV420:
5636 case DRM_FORMAT_YVU420:
5637 case DRM_FORMAT_YUV422:
5638 case DRM_FORMAT_YVU422:
5639 case DRM_FORMAT_YUV444:
5640 case DRM_FORMAT_YVU444:
5641 return 3;
5642 case DRM_FORMAT_NV12:
5643 case DRM_FORMAT_NV21:
5644 case DRM_FORMAT_NV16:
5645 case DRM_FORMAT_NV61:
5646 case DRM_FORMAT_NV24:
5647 case DRM_FORMAT_NV42:
5648 return 2;
5649 default:
5650 return 1;
5651 }
5652}
5653EXPORT_SYMBOL(drm_format_num_planes);
5654
5655/**
5656 * drm_format_plane_cpp - determine the bytes per pixel value
5657 * @format: pixel format (DRM_FORMAT_*)
5658 * @plane: plane index
5659 *
5660 * Returns:
5661 * The bytes per pixel value for the specified plane.
5662 */
5663int drm_format_plane_cpp(uint32_t format, int plane)
5664{
5665 unsigned int depth;
5666 int bpp;
5667
5668 if (plane >= drm_format_num_planes(format))
5669 return 0;
5670
5671 switch (format) {
5672 case DRM_FORMAT_YUYV:
5673 case DRM_FORMAT_YVYU:
5674 case DRM_FORMAT_UYVY:
5675 case DRM_FORMAT_VYUY:
5676 return 2;
5677 case DRM_FORMAT_NV12:
5678 case DRM_FORMAT_NV21:
5679 case DRM_FORMAT_NV16:
5680 case DRM_FORMAT_NV61:
5681 case DRM_FORMAT_NV24:
5682 case DRM_FORMAT_NV42:
5683 return plane ? 2 : 1;
5684 case DRM_FORMAT_YUV410:
5685 case DRM_FORMAT_YVU410:
5686 case DRM_FORMAT_YUV411:
5687 case DRM_FORMAT_YVU411:
5688 case DRM_FORMAT_YUV420:
5689 case DRM_FORMAT_YVU420:
5690 case DRM_FORMAT_YUV422:
5691 case DRM_FORMAT_YVU422:
5692 case DRM_FORMAT_YUV444:
5693 case DRM_FORMAT_YVU444:
5694 return 1;
5695 default:
5696 drm_fb_get_bpp_depth(format, &depth, &bpp);
5697 return bpp >> 3;
5698 }
5699}
5700EXPORT_SYMBOL(drm_format_plane_cpp);
5701
5702/**
5703 * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
5704 * @format: pixel format (DRM_FORMAT_*)
5705 *
5706 * Returns:
5707 * The horizontal chroma subsampling factor for the
5708 * specified pixel format.
5709 */
5710int drm_format_horz_chroma_subsampling(uint32_t format)
5711{
5712 switch (format) {
5713 case DRM_FORMAT_YUV411:
5714 case DRM_FORMAT_YVU411:
5715 case DRM_FORMAT_YUV410:
5716 case DRM_FORMAT_YVU410:
5717 return 4;
5718 case DRM_FORMAT_YUYV:
5719 case DRM_FORMAT_YVYU:
5720 case DRM_FORMAT_UYVY:
5721 case DRM_FORMAT_VYUY:
5722 case DRM_FORMAT_NV12:
5723 case DRM_FORMAT_NV21:
5724 case DRM_FORMAT_NV16:
5725 case DRM_FORMAT_NV61:
5726 case DRM_FORMAT_YUV422:
5727 case DRM_FORMAT_YVU422:
5728 case DRM_FORMAT_YUV420:
5729 case DRM_FORMAT_YVU420:
5730 return 2;
5731 default:
5732 return 1;
5733 }
5734}
5735EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
5736
5737/**
5738 * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
5739 * @format: pixel format (DRM_FORMAT_*)
5740 *
5741 * Returns:
5742 * The vertical chroma subsampling factor for the
5743 * specified pixel format.
5744 */
5745int drm_format_vert_chroma_subsampling(uint32_t format)
5746{
5747 switch (format) {
5748 case DRM_FORMAT_YUV410:
5749 case DRM_FORMAT_YVU410:
5750 return 4;
5751 case DRM_FORMAT_YUV420:
5752 case DRM_FORMAT_YVU420:
5753 case DRM_FORMAT_NV12:
5754 case DRM_FORMAT_NV21:
5755 return 2;
5756 default:
5757 return 1;
5758 }
5759}
5760EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
5761
5762/**
5763 * drm_format_plane_width - width of the plane given the first plane
5764 * @width: width of the first plane
5765 * @format: pixel format
5766 * @plane: plane index
5767 *
5768 * Returns:
5769 * The width of @plane, given that the width of the first plane is @width.
5770 */
5771int drm_format_plane_width(int width, uint32_t format, int plane)
5772{
5773 if (plane >= drm_format_num_planes(format))
5774 return 0;
5775
5776 if (plane == 0)
5777 return width;
5778
5779 return width / drm_format_horz_chroma_subsampling(format);
5780}
5781EXPORT_SYMBOL(drm_format_plane_width);
5782
5783/**
5784 * drm_format_plane_height - height of the plane given the first plane
5785 * @height: height of the first plane
5786 * @format: pixel format
5787 * @plane: plane index
5788 *
5789 * Returns:
5790 * The height of @plane, given that the height of the first plane is @height.
5791 */
5792int drm_format_plane_height(int height, uint32_t format, int plane)
5793{
5794 if (plane >= drm_format_num_planes(format))
5795 return 0;
5796
5797 if (plane == 0)
5798 return height;
5799
5800 return height / drm_format_vert_chroma_subsampling(format);
5801}
5802EXPORT_SYMBOL(drm_format_plane_height);
5803
5804/**
5805 * drm_rotation_simplify() - Try to simplify the rotation 5641 * drm_rotation_simplify() - Try to simplify the rotation
5806 * @rotation: Rotation to be simplified 5642 * @rotation: Rotation to be simplified
5807 * @supported_rotations: Supported rotations 5643 * @supported_rotations: Supported rotations
@@ -6064,3 +5900,48 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
6064 return tg; 5900 return tg;
6065} 5901}
6066EXPORT_SYMBOL(drm_mode_create_tile_group); 5902EXPORT_SYMBOL(drm_mode_create_tile_group);
5903
5904/**
5905 * drm_crtc_enable_color_mgmt - enable color management properties
5906 * @crtc: DRM CRTC
5907 * @degamma_lut_size: the size of the degamma lut (before CSC)
5908 * @has_ctm: whether to attach ctm_property for CSC matrix
5909 * @gamma_lut_size: the size of the gamma lut (after CSC)
5910 *
5911 * This function lets the driver enable the color correction
5912 * properties on a CRTC. This includes 3 degamma, csc and gamma
5913 * properties that userspace can set and 2 size properties to inform
5914 * the userspace of the lut sizes. Each of the properties are
5915 * optional. The gamma and degamma properties are only attached if
5916 * their size is not 0 and ctm_property is only attached if has_ctm is
5917 * true.
5918 */
5919void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
5920 uint degamma_lut_size,
5921 bool has_ctm,
5922 uint gamma_lut_size)
5923{
5924 struct drm_device *dev = crtc->dev;
5925 struct drm_mode_config *config = &dev->mode_config;
5926
5927 if (degamma_lut_size) {
5928 drm_object_attach_property(&crtc->base,
5929 config->degamma_lut_property, 0);
5930 drm_object_attach_property(&crtc->base,
5931 config->degamma_lut_size_property,
5932 degamma_lut_size);
5933 }
5934
5935 if (has_ctm)
5936 drm_object_attach_property(&crtc->base,
5937 config->ctm_property, 0);
5938
5939 if (gamma_lut_size) {
5940 drm_object_attach_property(&crtc->base,
5941 config->gamma_lut_property, 0);
5942 drm_object_attach_property(&crtc->base,
5943 config->gamma_lut_size_property,
5944 gamma_lut_size);
5945 }
5946}
5947EXPORT_SYMBOL(drm_crtc_enable_color_mgmt);