.. | .. |
---|
20 | 20 | * OF THIS SOFTWARE. |
---|
21 | 21 | */ |
---|
22 | 22 | |
---|
23 | | -#include <drm/drmP.h> |
---|
24 | 23 | #include <drm/drm_connector.h> |
---|
25 | 24 | #include <drm/drm_edid.h> |
---|
26 | 25 | #include <drm/drm_encoder.h> |
---|
27 | 26 | #include <drm/drm_utils.h> |
---|
| 27 | +#include <drm/drm_print.h> |
---|
| 28 | +#include <drm/drm_drv.h> |
---|
| 29 | +#include <drm/drm_file.h> |
---|
| 30 | +#include <drm/drm_sysfs.h> |
---|
| 31 | + |
---|
| 32 | +#include <linux/uaccess.h> |
---|
28 | 33 | |
---|
29 | 34 | #include "drm_crtc_internal.h" |
---|
30 | 35 | #include "drm_internal.h" |
---|
.. | .. |
---|
33 | 38 | * DOC: overview |
---|
34 | 39 | * |
---|
35 | 40 | * In DRM connectors are the general abstraction for display sinks, and include |
---|
36 | | - * als fixed panels or anything else that can display pixels in some form. As |
---|
| 41 | + * also fixed panels or anything else that can display pixels in some form. As |
---|
37 | 42 | * opposed to all other KMS objects representing hardware (like CRTC, encoder or |
---|
38 | 43 | * plane abstractions) connectors can be hotplugged and unplugged at runtime. |
---|
39 | 44 | * Hence they are reference-counted using drm_connector_get() and |
---|
.. | .. |
---|
88 | 93 | { DRM_MODE_CONNECTOR_DSI, "DSI" }, |
---|
89 | 94 | { DRM_MODE_CONNECTOR_DPI, "DPI" }, |
---|
90 | 95 | { DRM_MODE_CONNECTOR_WRITEBACK, "Writeback" }, |
---|
| 96 | + { DRM_MODE_CONNECTOR_SPI, "SPI" }, |
---|
91 | 97 | }; |
---|
92 | | - |
---|
93 | | -DRM_ENUM_NAME_FN(drm_get_connector_name, drm_connector_enum_list) |
---|
94 | | -EXPORT_SYMBOL(drm_get_connector_name); |
---|
95 | 98 | |
---|
96 | 99 | void drm_connector_ida_init(void) |
---|
97 | 100 | { |
---|
.. | .. |
---|
110 | 113 | } |
---|
111 | 114 | |
---|
112 | 115 | /** |
---|
| 116 | + * drm_get_connector_type_name - return a string for connector type |
---|
| 117 | + * @type: The connector type (DRM_MODE_CONNECTOR_*) |
---|
| 118 | + * |
---|
| 119 | + * Returns: the name of the connector type, or NULL if the type is not valid. |
---|
| 120 | + */ |
---|
| 121 | +const char *drm_get_connector_type_name(unsigned int type) |
---|
| 122 | +{ |
---|
| 123 | + if (type < ARRAY_SIZE(drm_connector_enum_list)) |
---|
| 124 | + return drm_connector_enum_list[type].name; |
---|
| 125 | + |
---|
| 126 | + return NULL; |
---|
| 127 | +} |
---|
| 128 | +EXPORT_SYMBOL(drm_get_connector_type_name); |
---|
| 129 | + |
---|
| 130 | +/** |
---|
113 | 131 | * drm_connector_get_cmdline_mode - reads the user's cmdline mode |
---|
114 | | - * @connector: connector to quwery |
---|
| 132 | + * @connector: connector to query |
---|
115 | 133 | * |
---|
116 | 134 | * The kernel supports per-connector configuration of its consoles through |
---|
117 | 135 | * use of the video= parameter. This function parses that option and |
---|
.. | .. |
---|
138 | 156 | connector->force = mode->force; |
---|
139 | 157 | } |
---|
140 | 158 | |
---|
141 | | - DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", |
---|
142 | | - connector->name, |
---|
| 159 | + if (mode->panel_orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) { |
---|
| 160 | + DRM_INFO("cmdline forces connector %s panel_orientation to %d\n", |
---|
| 161 | + connector->name, mode->panel_orientation); |
---|
| 162 | + drm_connector_set_panel_orientation(connector, |
---|
| 163 | + mode->panel_orientation); |
---|
| 164 | + } |
---|
| 165 | + |
---|
| 166 | + DRM_DEBUG_KMS("cmdline mode for connector %s %s %dx%d@%dHz%s%s%s\n", |
---|
| 167 | + connector->name, mode->name, |
---|
143 | 168 | mode->xres, mode->yres, |
---|
144 | 169 | mode->refresh_specified ? mode->refresh : 60, |
---|
145 | 170 | mode->rb ? " reduced blanking" : "", |
---|
.. | .. |
---|
244 | 269 | INIT_LIST_HEAD(&connector->modes); |
---|
245 | 270 | mutex_init(&connector->mutex); |
---|
246 | 271 | connector->edid_blob_ptr = NULL; |
---|
| 272 | + connector->epoch_counter = 0; |
---|
| 273 | + connector->tile_blob_ptr = NULL; |
---|
247 | 274 | connector->status = connector_status_unknown; |
---|
248 | 275 | connector->display_info.panel_orientation = |
---|
249 | 276 | DRM_MODE_PANEL_ORIENTATION_UNKNOWN; |
---|
.. | .. |
---|
271 | 298 | drm_object_attach_property(&connector->base, |
---|
272 | 299 | config->non_desktop_property, |
---|
273 | 300 | 0); |
---|
| 301 | + drm_object_attach_property(&connector->base, |
---|
| 302 | + config->tile_property, |
---|
| 303 | + 0); |
---|
274 | 304 | |
---|
275 | 305 | if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { |
---|
276 | 306 | drm_object_attach_property(&connector->base, config->prop_crtc_id, 0); |
---|
.. | .. |
---|
290 | 320 | return ret; |
---|
291 | 321 | } |
---|
292 | 322 | EXPORT_SYMBOL(drm_connector_init); |
---|
| 323 | + |
---|
| 324 | +/** |
---|
| 325 | + * drm_connector_init_with_ddc - Init a preallocated connector |
---|
| 326 | + * @dev: DRM device |
---|
| 327 | + * @connector: the connector to init |
---|
| 328 | + * @funcs: callbacks for this connector |
---|
| 329 | + * @connector_type: user visible type of the connector |
---|
| 330 | + * @ddc: pointer to the associated ddc adapter |
---|
| 331 | + * |
---|
| 332 | + * Initialises a preallocated connector. Connectors should be |
---|
| 333 | + * subclassed as part of driver connector objects. |
---|
| 334 | + * |
---|
| 335 | + * Ensures that the ddc field of the connector is correctly set. |
---|
| 336 | + * |
---|
| 337 | + * Returns: |
---|
| 338 | + * Zero on success, error code on failure. |
---|
| 339 | + */ |
---|
| 340 | +int drm_connector_init_with_ddc(struct drm_device *dev, |
---|
| 341 | + struct drm_connector *connector, |
---|
| 342 | + const struct drm_connector_funcs *funcs, |
---|
| 343 | + int connector_type, |
---|
| 344 | + struct i2c_adapter *ddc) |
---|
| 345 | +{ |
---|
| 346 | + int ret; |
---|
| 347 | + |
---|
| 348 | + ret = drm_connector_init(dev, connector, funcs, connector_type); |
---|
| 349 | + if (ret) |
---|
| 350 | + return ret; |
---|
| 351 | + |
---|
| 352 | + /* provide ddc symlink in sysfs */ |
---|
| 353 | + connector->ddc = ddc; |
---|
| 354 | + |
---|
| 355 | + return ret; |
---|
| 356 | +} |
---|
| 357 | +EXPORT_SYMBOL(drm_connector_init_with_ddc); |
---|
293 | 358 | |
---|
294 | 359 | /** |
---|
295 | 360 | * drm_connector_attach_edid_property - attach edid property. |
---|
.. | .. |
---|
324 | 389 | int drm_connector_attach_encoder(struct drm_connector *connector, |
---|
325 | 390 | struct drm_encoder *encoder) |
---|
326 | 391 | { |
---|
327 | | - int i; |
---|
328 | | - |
---|
329 | 392 | /* |
---|
330 | 393 | * In the past, drivers have attempted to model the static association |
---|
331 | 394 | * of connector to encoder in simple connector/encoder devices using a |
---|
.. | .. |
---|
340 | 403 | if (WARN_ON(connector->encoder)) |
---|
341 | 404 | return -EINVAL; |
---|
342 | 405 | |
---|
343 | | - for (i = 0; i < ARRAY_SIZE(connector->encoder_ids); i++) { |
---|
344 | | - if (connector->encoder_ids[i] == 0) { |
---|
345 | | - connector->encoder_ids[i] = encoder->base.id; |
---|
346 | | - return 0; |
---|
347 | | - } |
---|
348 | | - } |
---|
349 | | - return -ENOMEM; |
---|
| 406 | + connector->possible_encoders |= drm_encoder_mask(encoder); |
---|
| 407 | + |
---|
| 408 | + return 0; |
---|
350 | 409 | } |
---|
351 | 410 | EXPORT_SYMBOL(drm_connector_attach_encoder); |
---|
352 | 411 | |
---|
353 | 412 | /** |
---|
354 | | - * drm_connector_has_possible_encoder - check if the connector and encoder are assosicated with each other |
---|
| 413 | + * drm_connector_has_possible_encoder - check if the connector and encoder are |
---|
| 414 | + * associated with each other |
---|
355 | 415 | * @connector: the connector |
---|
356 | 416 | * @encoder: the encoder |
---|
357 | 417 | * |
---|
.. | .. |
---|
361 | 421 | bool drm_connector_has_possible_encoder(struct drm_connector *connector, |
---|
362 | 422 | struct drm_encoder *encoder) |
---|
363 | 423 | { |
---|
364 | | - struct drm_encoder *enc; |
---|
365 | | - int i; |
---|
366 | | - |
---|
367 | | - drm_connector_for_each_possible_encoder(connector, enc, i) { |
---|
368 | | - if (enc == encoder) |
---|
369 | | - return true; |
---|
370 | | - } |
---|
371 | | - |
---|
372 | | - return false; |
---|
| 424 | + return connector->possible_encoders & drm_encoder_mask(encoder); |
---|
373 | 425 | } |
---|
374 | 426 | EXPORT_SYMBOL(drm_connector_has_possible_encoder); |
---|
375 | 427 | |
---|
.. | .. |
---|
432 | 484 | mutex_destroy(&connector->mutex); |
---|
433 | 485 | |
---|
434 | 486 | memset(connector, 0, sizeof(*connector)); |
---|
| 487 | + |
---|
| 488 | + if (dev->registered) |
---|
| 489 | + drm_sysfs_hotplug_event(dev); |
---|
435 | 490 | } |
---|
436 | 491 | EXPORT_SYMBOL(drm_connector_cleanup); |
---|
437 | 492 | |
---|
.. | .. |
---|
439 | 494 | * drm_connector_register - register a connector |
---|
440 | 495 | * @connector: the connector to register |
---|
441 | 496 | * |
---|
442 | | - * Register userspace interfaces for a connector |
---|
| 497 | + * Register userspace interfaces for a connector. Only call this for connectors |
---|
| 498 | + * which can be hotplugged after drm_dev_register() has been called already, |
---|
| 499 | + * e.g. DP MST connectors. All other connectors will be registered automatically |
---|
| 500 | + * when calling drm_dev_register(). |
---|
443 | 501 | * |
---|
444 | 502 | * Returns: |
---|
445 | 503 | * Zero on success, error code on failure. |
---|
.. | .. |
---|
459 | 517 | if (ret) |
---|
460 | 518 | goto unlock; |
---|
461 | 519 | |
---|
462 | | - ret = drm_debugfs_connector_add(connector); |
---|
463 | | - if (ret) { |
---|
464 | | - goto err_sysfs; |
---|
465 | | - } |
---|
| 520 | + drm_debugfs_connector_add(connector); |
---|
466 | 521 | |
---|
467 | 522 | if (connector->funcs->late_register) { |
---|
468 | 523 | ret = connector->funcs->late_register(connector); |
---|
.. | .. |
---|
473 | 528 | drm_mode_object_register(connector->dev, &connector->base); |
---|
474 | 529 | |
---|
475 | 530 | connector->registration_state = DRM_CONNECTOR_REGISTERED; |
---|
| 531 | + |
---|
| 532 | + /* Let userspace know we have a new connector */ |
---|
| 533 | + drm_sysfs_hotplug_event(connector->dev); |
---|
| 534 | + |
---|
476 | 535 | goto unlock; |
---|
477 | 536 | |
---|
478 | 537 | err_debugfs: |
---|
479 | 538 | drm_debugfs_connector_remove(connector); |
---|
480 | | -err_sysfs: |
---|
481 | 539 | drm_sysfs_connector_remove(connector); |
---|
482 | 540 | unlock: |
---|
483 | 541 | mutex_unlock(&connector->mutex); |
---|
.. | .. |
---|
489 | 547 | * drm_connector_unregister - unregister a connector |
---|
490 | 548 | * @connector: the connector to unregister |
---|
491 | 549 | * |
---|
492 | | - * Unregister userspace interfaces for a connector |
---|
| 550 | + * Unregister userspace interfaces for a connector. Only call this for |
---|
| 551 | + * connectors which have registered explicitly by calling drm_dev_register(), |
---|
| 552 | + * since connectors are unregistered automatically when drm_dev_unregister() is |
---|
| 553 | + * called. |
---|
493 | 554 | */ |
---|
494 | 555 | void drm_connector_unregister(struct drm_connector *connector) |
---|
495 | 556 | { |
---|
.. | .. |
---|
682 | 743 | __drm_connector_put_safe(iter->conn); |
---|
683 | 744 | spin_unlock_irqrestore(&config->connector_list_lock, flags); |
---|
684 | 745 | } |
---|
685 | | - lock_release(&connector_list_iter_dep_map, 0, _RET_IP_); |
---|
| 746 | + lock_release(&connector_list_iter_dep_map, _RET_IP_); |
---|
686 | 747 | } |
---|
687 | 748 | EXPORT_SYMBOL(drm_connector_list_iter_end); |
---|
688 | 749 | |
---|
.. | .. |
---|
792 | 853 | DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) |
---|
793 | 854 | |
---|
794 | 855 | static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { |
---|
795 | | - { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ |
---|
| 856 | + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I, TV-out and DP */ |
---|
796 | 857 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
---|
797 | 858 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ |
---|
798 | 859 | }; |
---|
.. | .. |
---|
809 | 870 | DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) |
---|
810 | 871 | |
---|
811 | 872 | static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { |
---|
812 | | - { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ |
---|
| 873 | + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I, TV-out and DP */ |
---|
813 | 874 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ |
---|
814 | 875 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ |
---|
815 | 876 | { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ |
---|
.. | .. |
---|
818 | 879 | DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, |
---|
819 | 880 | drm_tv_subconnector_enum_list) |
---|
820 | 881 | |
---|
821 | | -static struct drm_prop_enum_list drm_cp_enum_list[] = { |
---|
822 | | - { DRM_MODE_CONTENT_PROTECTION_UNDESIRED, "Undesired" }, |
---|
823 | | - { DRM_MODE_CONTENT_PROTECTION_DESIRED, "Desired" }, |
---|
824 | | - { DRM_MODE_CONTENT_PROTECTION_ENABLED, "Enabled" }, |
---|
| 882 | +static const struct drm_prop_enum_list drm_dp_subconnector_enum_list[] = { |
---|
| 883 | + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I, TV-out and DP */ |
---|
| 884 | + { DRM_MODE_SUBCONNECTOR_VGA, "VGA" }, /* DP */ |
---|
| 885 | + { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DP */ |
---|
| 886 | + { DRM_MODE_SUBCONNECTOR_HDMIA, "HDMI" }, /* DP */ |
---|
| 887 | + { DRM_MODE_SUBCONNECTOR_DisplayPort, "DP" }, /* DP */ |
---|
| 888 | + { DRM_MODE_SUBCONNECTOR_Wireless, "Wireless" }, /* DP */ |
---|
| 889 | + { DRM_MODE_SUBCONNECTOR_Native, "Native" }, /* DP */ |
---|
825 | 890 | }; |
---|
826 | | -DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list) |
---|
| 891 | + |
---|
| 892 | +DRM_ENUM_NAME_FN(drm_get_dp_subconnector_name, |
---|
| 893 | + drm_dp_subconnector_enum_list) |
---|
827 | 894 | |
---|
828 | 895 | static const struct drm_prop_enum_list hdmi_colorspaces[] = { |
---|
829 | 896 | /* For Default case, driver will set the colorspace */ |
---|
.. | .. |
---|
852 | 919 | { DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER, "DCI-P3_RGB_Theater" }, |
---|
853 | 920 | }; |
---|
854 | 921 | |
---|
| 922 | +/* |
---|
| 923 | + * As per DP 1.4a spec, 2.2.5.7.5 VSC SDP Payload for Pixel Encoding/Colorimetry |
---|
| 924 | + * Format Table 2-120 |
---|
| 925 | + */ |
---|
855 | 926 | static const struct drm_prop_enum_list dp_colorspaces[] = { |
---|
856 | 927 | /* For Default case, driver will set the colorspace */ |
---|
857 | 928 | { DRM_MODE_COLORIMETRY_DEFAULT, "Default" }, |
---|
| 929 | + { DRM_MODE_COLORIMETRY_RGB_WIDE_FIXED, "RGB_Wide_Gamut_Fixed_Point" }, |
---|
| 930 | + /* Colorimetry based on scRGB (IEC 61966-2-2) */ |
---|
| 931 | + { DRM_MODE_COLORIMETRY_RGB_WIDE_FLOAT, "RGB_Wide_Gamut_Floating_Point" }, |
---|
| 932 | + /* Colorimetry based on IEC 61966-2-5 */ |
---|
| 933 | + { DRM_MODE_COLORIMETRY_OPRGB, "opRGB" }, |
---|
| 934 | + /* Colorimetry based on SMPTE RP 431-2 */ |
---|
| 935 | + { DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65, "DCI-P3_RGB_D65" }, |
---|
| 936 | + /* Colorimetry based on ITU-R BT.2020 */ |
---|
| 937 | + { DRM_MODE_COLORIMETRY_BT2020_RGB, "BT2020_RGB" }, |
---|
| 938 | + { DRM_MODE_COLORIMETRY_BT601_YCC, "BT601_YCC" }, |
---|
| 939 | + { DRM_MODE_COLORIMETRY_BT709_YCC, "BT709_YCC" }, |
---|
858 | 940 | /* Standard Definition Colorimetry based on IEC 61966-2-4 */ |
---|
859 | 941 | { DRM_MODE_COLORIMETRY_XVYCC_601, "XVYCC_601" }, |
---|
860 | 942 | /* High Definition Colorimetry based on IEC 61966-2-4 */ |
---|
861 | 943 | { DRM_MODE_COLORIMETRY_XVYCC_709, "XVYCC_709" }, |
---|
862 | | - /* Colorimetry based on IEC 61966-2-5 */ |
---|
863 | | - { DRM_MODE_COLORIMETRY_OPRGB, "opRGB" }, |
---|
864 | | - { DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65, "DCI-P3_RGB_D65" }, |
---|
865 | | - /* DP MSA Colorimetry */ |
---|
866 | | - { DRM_MODE_DP_COLORIMETRY_BT601_YCC, "YCBCR_ITU_601" }, |
---|
867 | | - { DRM_MODE_DP_COLORIMETRY_BT709_YCC, "YCBCR_ITU_709" }, |
---|
868 | | - { DRM_MODE_DP_COLORIMETRY_SRGB, "sRGB" }, |
---|
869 | | - { DRM_MODE_DP_COLORIMETRY_RGB_WIDE_GAMUT, "RGB Wide Gamut" }, |
---|
870 | | - { DRM_MODE_DP_COLORIMETRY_SCRGB, "scRGB" }, |
---|
| 944 | + /* Colorimetry based on IEC 61966-2-1/Amendment 1 */ |
---|
| 945 | + { DRM_MODE_COLORIMETRY_SYCC_601, "SYCC_601" }, |
---|
| 946 | + /* Colorimetry based on IEC 61966-2-5 [33] */ |
---|
| 947 | + { DRM_MODE_COLORIMETRY_OPYCC_601, "opYCC_601" }, |
---|
871 | 948 | /* Colorimetry based on ITU-R BT.2020 */ |
---|
872 | | - { DRM_MODE_COLORIMETRY_BT2020_RGB, "BT2020_RGB" }, |
---|
| 949 | + { DRM_MODE_COLORIMETRY_BT2020_CYCC, "BT2020_CYCC" }, |
---|
873 | 950 | /* Colorimetry based on ITU-R BT.2020 */ |
---|
874 | 951 | { DRM_MODE_COLORIMETRY_BT2020_YCC, "BT2020_YCC" }, |
---|
875 | 952 | }; |
---|
.. | .. |
---|
893 | 970 | * connector is linked to. Drivers should never set this property directly, |
---|
894 | 971 | * it is handled by the DRM core by calling the &drm_connector_funcs.dpms |
---|
895 | 972 | * callback. For atomic drivers the remapping to the "ACTIVE" property is |
---|
896 | | - * implemented in the DRM core. This is the only standard connector |
---|
897 | | - * property that userspace can change. |
---|
| 973 | + * implemented in the DRM core. |
---|
898 | 974 | * |
---|
899 | 975 | * Note that this property cannot be set through the MODE_ATOMIC ioctl, |
---|
900 | 976 | * userspace must use "ACTIVE" on the CRTC instead. |
---|
.. | .. |
---|
931 | 1007 | * DP MST sinks), or high-res integrated panels (like dual-link DSI) which |
---|
932 | 1008 | * are not gen-locked. Note that for tiled panels which are genlocked, like |
---|
933 | 1009 | * dual-link LVDS or dual-link DSI, the driver should try to not expose the |
---|
934 | | - * tiling and virtualize both &drm_crtc and &drm_plane if needed. Drivers |
---|
| 1010 | + * tiling and virtualise both &drm_crtc and &drm_plane if needed. Drivers |
---|
935 | 1011 | * should update this value using drm_connector_set_tile_property(). |
---|
936 | 1012 | * Userspace cannot change this property. |
---|
937 | 1013 | * link-status: |
---|
.. | .. |
---|
940 | 1016 | * after modeset, the kernel driver may set this to "BAD" and issue a |
---|
941 | 1017 | * hotplug uevent. Drivers should update this value using |
---|
942 | 1018 | * drm_connector_set_link_status_property(). |
---|
| 1019 | + * |
---|
| 1020 | + * When user-space receives the hotplug uevent and detects a "BAD" |
---|
| 1021 | + * link-status, the sink doesn't receive pixels anymore (e.g. the screen |
---|
| 1022 | + * becomes completely black). The list of available modes may have |
---|
| 1023 | + * changed. User-space is expected to pick a new mode if the current one |
---|
| 1024 | + * has disappeared and perform a new modeset with link-status set to |
---|
| 1025 | + * "GOOD" to re-enable the connector. |
---|
| 1026 | + * |
---|
| 1027 | + * If multiple connectors share the same CRTC and one of them gets a "BAD" |
---|
| 1028 | + * link-status, the other are unaffected (ie. the sinks still continue to |
---|
| 1029 | + * receive pixels). |
---|
| 1030 | + * |
---|
| 1031 | + * When user-space performs an atomic commit on a connector with a "BAD" |
---|
| 1032 | + * link-status without resetting the property to "GOOD", the sink may |
---|
| 1033 | + * still not receive pixels. When user-space performs an atomic commit |
---|
| 1034 | + * which resets the link-status property to "GOOD" without the |
---|
| 1035 | + * ALLOW_MODESET flag set, it might fail because a modeset is required. |
---|
| 1036 | + * |
---|
| 1037 | + * User-space can only change link-status to "GOOD", changing it to "BAD" |
---|
| 1038 | + * is a no-op. |
---|
| 1039 | + * |
---|
| 1040 | + * For backwards compatibility with non-atomic userspace the kernel |
---|
| 1041 | + * tries to automatically set the link-status back to "GOOD" in the |
---|
| 1042 | + * SETCRTC IOCTL. This might fail if the mode is no longer valid, similar |
---|
| 1043 | + * to how it might fail if a different screen has been connected in the |
---|
| 1044 | + * interim. |
---|
943 | 1045 | * non_desktop: |
---|
944 | 1046 | * Indicates the output should be ignored for purposes of displaying a |
---|
945 | 1047 | * standard desktop environment or console. This is most likely because |
---|
.. | .. |
---|
975 | 1077 | * - If the state is DESIRED, kernel should attempt to re-authenticate the |
---|
976 | 1078 | * link whenever possible. This includes across disable/enable, dpms, |
---|
977 | 1079 | * hotplug, downstream device changes, link status failures, etc.. |
---|
978 | | - * - Userspace is responsible for polling the property to determine when |
---|
979 | | - * the value transitions from ENABLED to DESIRED. This signifies the link |
---|
980 | | - * is no longer protected and userspace should take appropriate action |
---|
981 | | - * (whatever that might be). |
---|
| 1080 | + * - Kernel sends uevent with the connector id and property id through |
---|
| 1081 | + * @drm_hdcp_update_content_protection, upon below kernel triggered |
---|
| 1082 | + * scenarios: |
---|
| 1083 | + * |
---|
| 1084 | + * - DESIRED -> ENABLED (authentication success) |
---|
| 1085 | + * - ENABLED -> DESIRED (termination of authentication) |
---|
| 1086 | + * - Please note no uevents for userspace triggered property state changes, |
---|
| 1087 | + * which can't fail such as |
---|
| 1088 | + * |
---|
| 1089 | + * - DESIRED/ENABLED -> UNDESIRED |
---|
| 1090 | + * - UNDESIRED -> DESIRED |
---|
| 1091 | + * - Userspace is responsible for polling the property or listen to uevents |
---|
| 1092 | + * to determine when the value transitions from ENABLED to DESIRED. |
---|
| 1093 | + * This signifies the link is no longer protected and userspace should |
---|
| 1094 | + * take appropriate action (whatever that might be). |
---|
| 1095 | + * |
---|
| 1096 | + * HDCP Content Type: |
---|
| 1097 | + * This Enum property is used by the userspace to declare the content type |
---|
| 1098 | + * of the display stream, to kernel. Here display stream stands for any |
---|
| 1099 | + * display content that userspace intended to display through HDCP |
---|
| 1100 | + * encryption. |
---|
| 1101 | + * |
---|
| 1102 | + * Content Type of a stream is decided by the owner of the stream, as |
---|
| 1103 | + * "HDCP Type0" or "HDCP Type1". |
---|
| 1104 | + * |
---|
| 1105 | + * The value of the property can be one of the below: |
---|
| 1106 | + * - "HDCP Type0": DRM_MODE_HDCP_CONTENT_TYPE0 = 0 |
---|
| 1107 | + * - "HDCP Type1": DRM_MODE_HDCP_CONTENT_TYPE1 = 1 |
---|
| 1108 | + * |
---|
| 1109 | + * When kernel starts the HDCP authentication (see "Content Protection" |
---|
| 1110 | + * for details), it uses the content type in "HDCP Content Type" |
---|
| 1111 | + * for performing the HDCP authentication with the display sink. |
---|
| 1112 | + * |
---|
| 1113 | + * Please note in HDCP spec versions, a link can be authenticated with |
---|
| 1114 | + * HDCP 2.2 for Content Type 0/Content Type 1. Where as a link can be |
---|
| 1115 | + * authenticated with HDCP1.4 only for Content Type 0(though it is implicit |
---|
| 1116 | + * in nature. As there is no reference for Content Type in HDCP1.4). |
---|
| 1117 | + * |
---|
| 1118 | + * HDCP2.2 authentication protocol itself takes the "Content Type" as a |
---|
| 1119 | + * parameter, which is a input for the DP HDCP2.2 encryption algo. |
---|
| 1120 | + * |
---|
| 1121 | + * In case of Type 0 content protection request, kernel driver can choose |
---|
| 1122 | + * either of HDCP spec versions 1.4 and 2.2. When HDCP2.2 is used for |
---|
| 1123 | + * "HDCP Type 0", a HDCP 2.2 capable repeater in the downstream can send |
---|
| 1124 | + * that content to a HDCP 1.4 authenticated HDCP sink (Type0 link). |
---|
| 1125 | + * But if the content is classified as "HDCP Type 1", above mentioned |
---|
| 1126 | + * HDCP 2.2 repeater wont send the content to the HDCP sink as it can't |
---|
| 1127 | + * authenticate the HDCP1.4 capable sink for "HDCP Type 1". |
---|
| 1128 | + * |
---|
| 1129 | + * Please note userspace can be ignorant of the HDCP versions used by the |
---|
| 1130 | + * kernel driver to achieve the "HDCP Content Type". |
---|
| 1131 | + * |
---|
| 1132 | + * At current scenario, classifying a content as Type 1 ensures that the |
---|
| 1133 | + * content will be displayed only through the HDCP2.2 encrypted link. |
---|
| 1134 | + * |
---|
| 1135 | + * Note that the HDCP Content Type property is introduced at HDCP 2.2, and |
---|
| 1136 | + * defaults to type 0. It is only exposed by drivers supporting HDCP 2.2 |
---|
| 1137 | + * (hence supporting Type 0 and Type 1). Based on how next versions of |
---|
| 1138 | + * HDCP specs are defined content Type could be used for higher versions |
---|
| 1139 | + * too. |
---|
| 1140 | + * |
---|
| 1141 | + * If content type is changed when "Content Protection" is not UNDESIRED, |
---|
| 1142 | + * then kernel will disable the HDCP and re-enable with new type in the |
---|
| 1143 | + * same atomic commit. And when "Content Protection" is ENABLED, it means |
---|
| 1144 | + * that link is HDCP authenticated and encrypted, for the transmission of |
---|
| 1145 | + * the Type of stream mentioned at "HDCP Content Type". |
---|
| 1146 | + * |
---|
| 1147 | + * HDR_OUTPUT_METADATA: |
---|
| 1148 | + * Connector property to enable userspace to send HDR Metadata to |
---|
| 1149 | + * driver. This metadata is based on the composition and blending |
---|
| 1150 | + * policies decided by user, taking into account the hardware and |
---|
| 1151 | + * sink capabilities. The driver gets this metadata and creates a |
---|
| 1152 | + * Dynamic Range and Mastering Infoframe (DRM) in case of HDMI, |
---|
| 1153 | + * SDP packet (Non-audio INFOFRAME SDP v1.3) for DP. This is then |
---|
| 1154 | + * sent to sink. This notifies the sink of the upcoming frame's Color |
---|
| 1155 | + * Encoding and Luminance parameters. |
---|
| 1156 | + * |
---|
| 1157 | + * Userspace first need to detect the HDR capabilities of sink by |
---|
| 1158 | + * reading and parsing the EDID. Details of HDR metadata for HDMI |
---|
| 1159 | + * are added in CTA 861.G spec. For DP , its defined in VESA DP |
---|
| 1160 | + * Standard v1.4. It needs to then get the metadata information |
---|
| 1161 | + * of the video/game/app content which are encoded in HDR (basically |
---|
| 1162 | + * using HDR transfer functions). With this information it needs to |
---|
| 1163 | + * decide on a blending policy and compose the relevant |
---|
| 1164 | + * layers/overlays into a common format. Once this blending is done, |
---|
| 1165 | + * userspace will be aware of the metadata of the composed frame to |
---|
| 1166 | + * be send to sink. It then uses this property to communicate this |
---|
| 1167 | + * metadata to driver which then make a Infoframe packet and sends |
---|
| 1168 | + * to sink based on the type of encoder connected. |
---|
| 1169 | + * |
---|
| 1170 | + * Userspace will be responsible to do Tone mapping operation in case: |
---|
| 1171 | + * - Some layers are HDR and others are SDR |
---|
| 1172 | + * - HDR layers luminance is not same as sink |
---|
| 1173 | + * |
---|
| 1174 | + * It will even need to do colorspace conversion and get all layers |
---|
| 1175 | + * to one common colorspace for blending. It can use either GL, Media |
---|
| 1176 | + * or display engine to get this done based on the capabilities of the |
---|
| 1177 | + * associated hardware. |
---|
| 1178 | + * |
---|
| 1179 | + * Driver expects metadata to be put in &struct hdr_output_metadata |
---|
| 1180 | + * structure from userspace. This is received as blob and stored in |
---|
| 1181 | + * &drm_connector_state.hdr_output_metadata. It parses EDID and saves the |
---|
| 1182 | + * sink metadata in &struct hdr_sink_metadata, as |
---|
| 1183 | + * &drm_connector.hdr_sink_metadata. Driver uses |
---|
| 1184 | + * drm_hdmi_infoframe_set_hdr_metadata() helper to set the HDR metadata, |
---|
| 1185 | + * hdmi_drm_infoframe_pack() to pack the infoframe as per spec, in case of |
---|
| 1186 | + * HDMI encoder. |
---|
| 1187 | + * |
---|
| 1188 | + * max bpc: |
---|
| 1189 | + * This range property is used by userspace to limit the bit depth. When |
---|
| 1190 | + * used the driver would limit the bpc in accordance with the valid range |
---|
| 1191 | + * supported by the hardware and sink. Drivers to use the function |
---|
| 1192 | + * drm_connector_attach_max_bpc_property() to create and attach the |
---|
| 1193 | + * property to the connector during initialization. |
---|
982 | 1194 | * |
---|
983 | 1195 | * Connectors also have one standardized atomic property: |
---|
984 | 1196 | * |
---|
.. | .. |
---|
996 | 1208 | * coordinates, so if userspace rotates the picture to adjust for |
---|
997 | 1209 | * the orientation it must also apply the same transformation to the |
---|
998 | 1210 | * touchscreen input coordinates. This property is initialized by calling |
---|
999 | | - * drm_connector_init_panel_orientation_property(). |
---|
| 1211 | + * drm_connector_set_panel_orientation() or |
---|
| 1212 | + * drm_connector_set_panel_orientation_with_quirk() |
---|
1000 | 1213 | * |
---|
1001 | 1214 | * scaling mode: |
---|
1002 | 1215 | * This property defines how a non-native mode is upscaled to the native |
---|
.. | .. |
---|
1020 | 1233 | * can also expose this property to external outputs, in which case they |
---|
1021 | 1234 | * must support "None", which should be the default (since external screens |
---|
1022 | 1235 | * have a built-in scaler). |
---|
| 1236 | + * |
---|
| 1237 | + * subconnector: |
---|
| 1238 | + * This property is used by DVI-I, TVout and DisplayPort to indicate different |
---|
| 1239 | + * connector subtypes. Enum values more or less match with those from main |
---|
| 1240 | + * connector types. |
---|
| 1241 | + * For DVI-I and TVout there is also a matching property "select subconnector" |
---|
| 1242 | + * allowing to switch between signal types. |
---|
| 1243 | + * DP subconnector corresponds to a downstream port. |
---|
1023 | 1244 | */ |
---|
1024 | 1245 | |
---|
1025 | 1246 | int drm_connector_create_standard_properties(struct drm_device *dev) |
---|
.. | .. |
---|
1109 | 1330 | EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); |
---|
1110 | 1331 | |
---|
1111 | 1332 | /** |
---|
| 1333 | + * drm_connector_attach_dp_subconnector_property - create subconnector property for DP |
---|
| 1334 | + * @connector: drm_connector to attach property |
---|
| 1335 | + * |
---|
| 1336 | + * Called by a driver when DP connector is created. |
---|
| 1337 | + */ |
---|
| 1338 | +void drm_connector_attach_dp_subconnector_property(struct drm_connector *connector) |
---|
| 1339 | +{ |
---|
| 1340 | + struct drm_mode_config *mode_config = &connector->dev->mode_config; |
---|
| 1341 | + |
---|
| 1342 | + if (!mode_config->dp_subconnector_property) |
---|
| 1343 | + mode_config->dp_subconnector_property = |
---|
| 1344 | + drm_property_create_enum(connector->dev, |
---|
| 1345 | + DRM_MODE_PROP_IMMUTABLE, |
---|
| 1346 | + "subconnector", |
---|
| 1347 | + drm_dp_subconnector_enum_list, |
---|
| 1348 | + ARRAY_SIZE(drm_dp_subconnector_enum_list)); |
---|
| 1349 | + |
---|
| 1350 | + drm_object_attach_property(&connector->base, |
---|
| 1351 | + mode_config->dp_subconnector_property, |
---|
| 1352 | + DRM_MODE_SUBCONNECTOR_Unknown); |
---|
| 1353 | +} |
---|
| 1354 | +EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property); |
---|
| 1355 | + |
---|
| 1356 | +/** |
---|
1112 | 1357 | * DOC: HDMI connector properties |
---|
1113 | 1358 | * |
---|
1114 | 1359 | * content type (HDMI specific): |
---|
1115 | 1360 | * Indicates content type setting to be used in HDMI infoframes to indicate |
---|
1116 | | - * content type for the external device, so that it adjusts it's display |
---|
| 1361 | + * content type for the external device, so that it adjusts its display |
---|
1117 | 1362 | * settings accordingly. |
---|
1118 | 1363 | * |
---|
1119 | 1364 | * The value of this property can be one of the following: |
---|
.. | .. |
---|
1185 | 1430 | EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type); |
---|
1186 | 1431 | |
---|
1187 | 1432 | /** |
---|
1188 | | - * drm_create_tv_properties - create TV specific connector properties |
---|
| 1433 | + * drm_mode_attach_tv_margin_properties - attach TV connector margin properties |
---|
| 1434 | + * @connector: DRM connector |
---|
| 1435 | + * |
---|
| 1436 | + * Called by a driver when it needs to attach TV margin props to a connector. |
---|
| 1437 | + * Typically used on SDTV and HDMI connectors. |
---|
| 1438 | + */ |
---|
| 1439 | +void drm_connector_attach_tv_margin_properties(struct drm_connector *connector) |
---|
| 1440 | +{ |
---|
| 1441 | + struct drm_device *dev = connector->dev; |
---|
| 1442 | + |
---|
| 1443 | + drm_object_attach_property(&connector->base, |
---|
| 1444 | + dev->mode_config.tv_left_margin_property, |
---|
| 1445 | + 0); |
---|
| 1446 | + drm_object_attach_property(&connector->base, |
---|
| 1447 | + dev->mode_config.tv_right_margin_property, |
---|
| 1448 | + 0); |
---|
| 1449 | + drm_object_attach_property(&connector->base, |
---|
| 1450 | + dev->mode_config.tv_top_margin_property, |
---|
| 1451 | + 0); |
---|
| 1452 | + drm_object_attach_property(&connector->base, |
---|
| 1453 | + dev->mode_config.tv_bottom_margin_property, |
---|
| 1454 | + 0); |
---|
| 1455 | +} |
---|
| 1456 | +EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties); |
---|
| 1457 | + |
---|
| 1458 | +/** |
---|
| 1459 | + * drm_mode_create_tv_margin_properties - create TV connector margin properties |
---|
| 1460 | + * @dev: DRM device |
---|
| 1461 | + * |
---|
| 1462 | + * Called by a driver's HDMI connector initialization routine, this function |
---|
| 1463 | + * creates the TV margin properties for a given device. No need to call this |
---|
| 1464 | + * function for an SDTV connector, it's already called from |
---|
| 1465 | + * drm_mode_create_tv_properties(). |
---|
| 1466 | + */ |
---|
| 1467 | +int drm_mode_create_tv_margin_properties(struct drm_device *dev) |
---|
| 1468 | +{ |
---|
| 1469 | + if (dev->mode_config.tv_left_margin_property) |
---|
| 1470 | + return 0; |
---|
| 1471 | + |
---|
| 1472 | + dev->mode_config.tv_left_margin_property = |
---|
| 1473 | + drm_property_create_range(dev, 0, "left margin", 0, 100); |
---|
| 1474 | + if (!dev->mode_config.tv_left_margin_property) |
---|
| 1475 | + return -ENOMEM; |
---|
| 1476 | + |
---|
| 1477 | + dev->mode_config.tv_right_margin_property = |
---|
| 1478 | + drm_property_create_range(dev, 0, "right margin", 0, 100); |
---|
| 1479 | + if (!dev->mode_config.tv_right_margin_property) |
---|
| 1480 | + return -ENOMEM; |
---|
| 1481 | + |
---|
| 1482 | + dev->mode_config.tv_top_margin_property = |
---|
| 1483 | + drm_property_create_range(dev, 0, "top margin", 0, 100); |
---|
| 1484 | + if (!dev->mode_config.tv_top_margin_property) |
---|
| 1485 | + return -ENOMEM; |
---|
| 1486 | + |
---|
| 1487 | + dev->mode_config.tv_bottom_margin_property = |
---|
| 1488 | + drm_property_create_range(dev, 0, "bottom margin", 0, 100); |
---|
| 1489 | + if (!dev->mode_config.tv_bottom_margin_property) |
---|
| 1490 | + return -ENOMEM; |
---|
| 1491 | + |
---|
| 1492 | + return 0; |
---|
| 1493 | +} |
---|
| 1494 | +EXPORT_SYMBOL(drm_mode_create_tv_margin_properties); |
---|
| 1495 | + |
---|
| 1496 | +/** |
---|
| 1497 | + * drm_mode_create_tv_properties - create TV specific connector properties |
---|
1189 | 1498 | * @dev: DRM device |
---|
1190 | 1499 | * @num_modes: number of different TV formats (modes) supported |
---|
1191 | 1500 | * @modes: array of pointers to strings containing name of each format |
---|
.. | .. |
---|
1230 | 1539 | /* |
---|
1231 | 1540 | * Other, TV specific properties: margins & TV modes. |
---|
1232 | 1541 | */ |
---|
1233 | | - dev->mode_config.tv_left_margin_property = |
---|
1234 | | - drm_property_create_range(dev, 0, "left margin", 0, 100); |
---|
1235 | | - if (!dev->mode_config.tv_left_margin_property) |
---|
1236 | | - goto nomem; |
---|
1237 | | - |
---|
1238 | | - dev->mode_config.tv_right_margin_property = |
---|
1239 | | - drm_property_create_range(dev, 0, "right margin", 0, 100); |
---|
1240 | | - if (!dev->mode_config.tv_right_margin_property) |
---|
1241 | | - goto nomem; |
---|
1242 | | - |
---|
1243 | | - dev->mode_config.tv_top_margin_property = |
---|
1244 | | - drm_property_create_range(dev, 0, "top margin", 0, 100); |
---|
1245 | | - if (!dev->mode_config.tv_top_margin_property) |
---|
1246 | | - goto nomem; |
---|
1247 | | - |
---|
1248 | | - dev->mode_config.tv_bottom_margin_property = |
---|
1249 | | - drm_property_create_range(dev, 0, "bottom margin", 0, 100); |
---|
1250 | | - if (!dev->mode_config.tv_bottom_margin_property) |
---|
| 1542 | + if (drm_mode_create_tv_margin_properties(dev)) |
---|
1251 | 1543 | goto nomem; |
---|
1252 | 1544 | |
---|
1253 | 1545 | dev->mode_config.tv_mode_property = |
---|
.. | .. |
---|
1326 | 1618 | EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); |
---|
1327 | 1619 | |
---|
1328 | 1620 | /** |
---|
| 1621 | + * DOC: Variable refresh properties |
---|
| 1622 | + * |
---|
| 1623 | + * Variable refresh rate capable displays can dynamically adjust their |
---|
| 1624 | + * refresh rate by extending the duration of their vertical front porch |
---|
| 1625 | + * until page flip or timeout occurs. This can reduce or remove stuttering |
---|
| 1626 | + * and latency in scenarios where the page flip does not align with the |
---|
| 1627 | + * vblank interval. |
---|
| 1628 | + * |
---|
| 1629 | + * An example scenario would be an application flipping at a constant rate |
---|
| 1630 | + * of 48Hz on a 60Hz display. The page flip will frequently miss the vblank |
---|
| 1631 | + * interval and the same contents will be displayed twice. This can be |
---|
| 1632 | + * observed as stuttering for content with motion. |
---|
| 1633 | + * |
---|
| 1634 | + * If variable refresh rate was active on a display that supported a |
---|
| 1635 | + * variable refresh range from 35Hz to 60Hz no stuttering would be observable |
---|
| 1636 | + * for the example scenario. The minimum supported variable refresh rate of |
---|
| 1637 | + * 35Hz is below the page flip frequency and the vertical front porch can |
---|
| 1638 | + * be extended until the page flip occurs. The vblank interval will be |
---|
| 1639 | + * directly aligned to the page flip rate. |
---|
| 1640 | + * |
---|
| 1641 | + * Not all userspace content is suitable for use with variable refresh rate. |
---|
| 1642 | + * Large and frequent changes in vertical front porch duration may worsen |
---|
| 1643 | + * perceived stuttering for input sensitive applications. |
---|
| 1644 | + * |
---|
| 1645 | + * Panel brightness will also vary with vertical front porch duration. Some |
---|
| 1646 | + * panels may have noticeable differences in brightness between the minimum |
---|
| 1647 | + * vertical front porch duration and the maximum vertical front porch duration. |
---|
| 1648 | + * Large and frequent changes in vertical front porch duration may produce |
---|
| 1649 | + * observable flickering for such panels. |
---|
| 1650 | + * |
---|
| 1651 | + * Userspace control for variable refresh rate is supported via properties |
---|
| 1652 | + * on the &drm_connector and &drm_crtc objects. |
---|
| 1653 | + * |
---|
| 1654 | + * "vrr_capable": |
---|
| 1655 | + * Optional &drm_connector boolean property that drivers should attach |
---|
| 1656 | + * with drm_connector_attach_vrr_capable_property() on connectors that |
---|
| 1657 | + * could support variable refresh rates. Drivers should update the |
---|
| 1658 | + * property value by calling drm_connector_set_vrr_capable_property(). |
---|
| 1659 | + * |
---|
| 1660 | + * Absence of the property should indicate absence of support. |
---|
| 1661 | + * |
---|
| 1662 | + * "VRR_ENABLED": |
---|
| 1663 | + * Default &drm_crtc boolean property that notifies the driver that the |
---|
| 1664 | + * content on the CRTC is suitable for variable refresh rate presentation. |
---|
| 1665 | + * The driver will take this property as a hint to enable variable |
---|
| 1666 | + * refresh rate support if the receiver supports it, ie. if the |
---|
| 1667 | + * "vrr_capable" property is true on the &drm_connector object. The |
---|
| 1668 | + * vertical front porch duration will be extended until page-flip or |
---|
| 1669 | + * timeout when enabled. |
---|
| 1670 | + * |
---|
| 1671 | + * The minimum vertical front porch duration is defined as the vertical |
---|
| 1672 | + * front porch duration for the current mode. |
---|
| 1673 | + * |
---|
| 1674 | + * The maximum vertical front porch duration is greater than or equal to |
---|
| 1675 | + * the minimum vertical front porch duration. The duration is derived |
---|
| 1676 | + * from the minimum supported variable refresh rate for the connector. |
---|
| 1677 | + * |
---|
| 1678 | + * The driver may place further restrictions within these minimum |
---|
| 1679 | + * and maximum bounds. |
---|
| 1680 | + */ |
---|
| 1681 | + |
---|
| 1682 | +/** |
---|
| 1683 | + * drm_connector_attach_vrr_capable_property - creates the |
---|
| 1684 | + * vrr_capable property |
---|
| 1685 | + * @connector: connector to create the vrr_capable property on. |
---|
| 1686 | + * |
---|
| 1687 | + * This is used by atomic drivers to add support for querying |
---|
| 1688 | + * variable refresh rate capability for a connector. |
---|
| 1689 | + * |
---|
| 1690 | + * Returns: |
---|
| 1691 | + * Zero on success, negative errno on failure. |
---|
| 1692 | + */ |
---|
| 1693 | +int drm_connector_attach_vrr_capable_property( |
---|
| 1694 | + struct drm_connector *connector) |
---|
| 1695 | +{ |
---|
| 1696 | + struct drm_device *dev = connector->dev; |
---|
| 1697 | + struct drm_property *prop; |
---|
| 1698 | + |
---|
| 1699 | + if (!connector->vrr_capable_property) { |
---|
| 1700 | + prop = drm_property_create_bool(dev, DRM_MODE_PROP_IMMUTABLE, |
---|
| 1701 | + "vrr_capable"); |
---|
| 1702 | + if (!prop) |
---|
| 1703 | + return -ENOMEM; |
---|
| 1704 | + |
---|
| 1705 | + connector->vrr_capable_property = prop; |
---|
| 1706 | + drm_object_attach_property(&connector->base, prop, 0); |
---|
| 1707 | + } |
---|
| 1708 | + |
---|
| 1709 | + return 0; |
---|
| 1710 | +} |
---|
| 1711 | +EXPORT_SYMBOL(drm_connector_attach_vrr_capable_property); |
---|
| 1712 | + |
---|
| 1713 | +/** |
---|
1329 | 1714 | * drm_connector_attach_scaling_mode_property - attach atomic scaling mode property |
---|
1330 | 1715 | * @connector: connector to attach scaling mode property on. |
---|
1331 | 1716 | * @scaling_mode_mask: or'ed mask of BIT(%DRM_MODE_SCALE_\*). |
---|
.. | .. |
---|
1386 | 1771 | EXPORT_SYMBOL(drm_connector_attach_scaling_mode_property); |
---|
1387 | 1772 | |
---|
1388 | 1773 | /** |
---|
1389 | | - * drm_connector_attach_content_protection_property - attach content protection |
---|
1390 | | - * property |
---|
1391 | | - * |
---|
1392 | | - * @connector: connector to attach CP property on. |
---|
1393 | | - * |
---|
1394 | | - * This is used to add support for content protection on select connectors. |
---|
1395 | | - * Content Protection is intentionally vague to allow for different underlying |
---|
1396 | | - * technologies, however it is most implemented by HDCP. |
---|
1397 | | - * |
---|
1398 | | - * The content protection will be set to &drm_connector_state.content_protection |
---|
1399 | | - * |
---|
1400 | | - * Returns: |
---|
1401 | | - * Zero on success, negative errno on failure. |
---|
1402 | | - */ |
---|
1403 | | -int drm_connector_attach_content_protection_property( |
---|
1404 | | - struct drm_connector *connector) |
---|
1405 | | -{ |
---|
1406 | | - struct drm_device *dev = connector->dev; |
---|
1407 | | - struct drm_property *prop; |
---|
1408 | | - |
---|
1409 | | - prop = drm_property_create_enum(dev, 0, "Content Protection", |
---|
1410 | | - drm_cp_enum_list, |
---|
1411 | | - ARRAY_SIZE(drm_cp_enum_list)); |
---|
1412 | | - if (!prop) |
---|
1413 | | - return -ENOMEM; |
---|
1414 | | - |
---|
1415 | | - drm_object_attach_property(&connector->base, prop, |
---|
1416 | | - DRM_MODE_CONTENT_PROTECTION_UNDESIRED); |
---|
1417 | | - |
---|
1418 | | - connector->content_protection_property = prop; |
---|
1419 | | - |
---|
1420 | | - return 0; |
---|
1421 | | -} |
---|
1422 | | -EXPORT_SYMBOL(drm_connector_attach_content_protection_property); |
---|
1423 | | - |
---|
1424 | | -/** |
---|
1425 | 1774 | * drm_mode_create_aspect_ratio_property - create aspect ratio property |
---|
1426 | 1775 | * @dev: DRM device |
---|
1427 | 1776 | * |
---|
.. | .. |
---|
1452 | 1801 | * DOC: standard connector properties |
---|
1453 | 1802 | * |
---|
1454 | 1803 | * Colorspace: |
---|
1455 | | - * drm_mode_create_colorspace_property - create colorspace property |
---|
1456 | 1804 | * This property helps select a suitable colorspace based on the sink |
---|
1457 | 1805 | * capability. Modern sink devices support wider gamut like BT2020. |
---|
1458 | 1806 | * This helps switch to BT2020 mode if the BT2020 encoded video stream |
---|
.. | .. |
---|
1472 | 1820 | * - This property is just to inform sink what colorspace |
---|
1473 | 1821 | * source is trying to drive. |
---|
1474 | 1822 | * |
---|
1475 | | - * Called by a driver the first time it's needed, must be attached to desired |
---|
1476 | | - * connectors. |
---|
| 1823 | + * Because between HDMI and DP have different colorspaces, |
---|
| 1824 | + * drm_mode_create_hdmi_colorspace_property() is used for HDMI connector and |
---|
| 1825 | + * drm_mode_create_dp_colorspace_property() is used for DP connector. |
---|
1477 | 1826 | */ |
---|
1478 | | -int drm_mode_create_colorspace_property(struct drm_connector *connector) |
---|
| 1827 | + |
---|
| 1828 | +/** |
---|
| 1829 | + * drm_mode_create_hdmi_colorspace_property - create hdmi colorspace property |
---|
| 1830 | + * @connector: connector to create the Colorspace property on. |
---|
| 1831 | + * |
---|
| 1832 | + * Called by a driver the first time it's needed, must be attached to desired |
---|
| 1833 | + * HDMI connectors. |
---|
| 1834 | + * |
---|
| 1835 | + * Returns: |
---|
| 1836 | + * Zero on success, negative errno on failure. |
---|
| 1837 | + */ |
---|
| 1838 | +int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector) |
---|
1479 | 1839 | { |
---|
1480 | 1840 | struct drm_device *dev = connector->dev; |
---|
1481 | | - struct drm_property *prop; |
---|
1482 | 1841 | |
---|
1483 | | - if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || |
---|
1484 | | - connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) { |
---|
1485 | | - prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, |
---|
1486 | | - "Colorspace", |
---|
1487 | | - hdmi_colorspaces, |
---|
1488 | | - ARRAY_SIZE(hdmi_colorspaces)); |
---|
1489 | | - if (!prop) |
---|
1490 | | - return -ENOMEM; |
---|
1491 | | - } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || |
---|
1492 | | - connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { |
---|
1493 | | - prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, |
---|
1494 | | - "Colorspace", dp_colorspaces, |
---|
1495 | | - ARRAY_SIZE(dp_colorspaces)); |
---|
1496 | | - |
---|
1497 | | - if (!prop) |
---|
1498 | | - return -ENOMEM; |
---|
1499 | | - } else { |
---|
1500 | | - DRM_DEBUG_KMS("Colorspace property not supported\n"); |
---|
| 1842 | + if (connector->colorspace_property) |
---|
1501 | 1843 | return 0; |
---|
1502 | | - } |
---|
1503 | 1844 | |
---|
1504 | | - connector->colorspace_property = prop; |
---|
| 1845 | + connector->colorspace_property = |
---|
| 1846 | + drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "Colorspace", |
---|
| 1847 | + hdmi_colorspaces, |
---|
| 1848 | + ARRAY_SIZE(hdmi_colorspaces)); |
---|
| 1849 | + |
---|
| 1850 | + if (!connector->colorspace_property) |
---|
| 1851 | + return -ENOMEM; |
---|
1505 | 1852 | |
---|
1506 | 1853 | return 0; |
---|
1507 | 1854 | } |
---|
1508 | | -EXPORT_SYMBOL(drm_mode_create_colorspace_property); |
---|
| 1855 | +EXPORT_SYMBOL(drm_mode_create_hdmi_colorspace_property); |
---|
| 1856 | + |
---|
| 1857 | +/** |
---|
| 1858 | + * drm_mode_create_dp_colorspace_property - create dp colorspace property |
---|
| 1859 | + * @connector: connector to create the Colorspace property on. |
---|
| 1860 | + * |
---|
| 1861 | + * Called by a driver the first time it's needed, must be attached to desired |
---|
| 1862 | + * DP connectors. |
---|
| 1863 | + * |
---|
| 1864 | + * Returns: |
---|
| 1865 | + * Zero on success, negative errno on failure. |
---|
| 1866 | + */ |
---|
| 1867 | +int drm_mode_create_dp_colorspace_property(struct drm_connector *connector) |
---|
| 1868 | +{ |
---|
| 1869 | + struct drm_device *dev = connector->dev; |
---|
| 1870 | + |
---|
| 1871 | + if (connector->colorspace_property) |
---|
| 1872 | + return 0; |
---|
| 1873 | + |
---|
| 1874 | + connector->colorspace_property = |
---|
| 1875 | + drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "Colorspace", |
---|
| 1876 | + dp_colorspaces, |
---|
| 1877 | + ARRAY_SIZE(dp_colorspaces)); |
---|
| 1878 | + |
---|
| 1879 | + if (!connector->colorspace_property) |
---|
| 1880 | + return -ENOMEM; |
---|
| 1881 | + |
---|
| 1882 | + return 0; |
---|
| 1883 | +} |
---|
| 1884 | +EXPORT_SYMBOL(drm_mode_create_dp_colorspace_property); |
---|
1509 | 1885 | |
---|
1510 | 1886 | /** |
---|
1511 | 1887 | * drm_mode_create_content_type_property - create content type property |
---|
.. | .. |
---|
1538 | 1914 | * drm_mode_create_suggested_offset_properties - create suggests offset properties |
---|
1539 | 1915 | * @dev: DRM device |
---|
1540 | 1916 | * |
---|
1541 | | - * Create the the suggested x/y offset property for connectors. |
---|
| 1917 | + * Create the suggested x/y offset property for connectors. |
---|
1542 | 1918 | */ |
---|
1543 | 1919 | int drm_mode_create_suggested_offset_properties(struct drm_device *dev) |
---|
1544 | 1920 | { |
---|
.. | .. |
---|
1594 | 1970 | * This looks up the tile information for a connector, and creates a |
---|
1595 | 1971 | * property for userspace to parse if it exists. The property is of |
---|
1596 | 1972 | * the form of 8 integers using ':' as a separator. |
---|
| 1973 | + * This is used for dual port tiled displays with DisplayPort SST |
---|
| 1974 | + * or DisplayPort MST connectors. |
---|
1597 | 1975 | * |
---|
1598 | 1976 | * Returns: |
---|
1599 | 1977 | * Zero on success, errno on failure. |
---|
.. | .. |
---|
1637 | 2015 | * |
---|
1638 | 2016 | * This function creates a new blob modeset object and assigns its id to the |
---|
1639 | 2017 | * connector's edid property. |
---|
| 2018 | + * Since we also parse tile information from EDID's displayID block, we also |
---|
| 2019 | + * set the connector's tile property here. See drm_connector_set_tile_property() |
---|
| 2020 | + * for more details. |
---|
1640 | 2021 | * |
---|
1641 | 2022 | * Returns: |
---|
1642 | 2023 | * Zero on success, negative errno on failure. |
---|
.. | .. |
---|
1647 | 2028 | struct drm_device *dev = connector->dev; |
---|
1648 | 2029 | size_t size = 0; |
---|
1649 | 2030 | int ret; |
---|
| 2031 | + const struct edid *old_edid; |
---|
1650 | 2032 | |
---|
1651 | 2033 | /* ignore requests to set edid when overridden */ |
---|
1652 | 2034 | if (connector->override_edid) |
---|
.. | .. |
---|
1656 | 2038 | size = EDID_LENGTH * (1 + edid->extensions); |
---|
1657 | 2039 | |
---|
1658 | 2040 | /* Set the display info, using edid if available, otherwise |
---|
1659 | | - * reseting the values to defaults. This duplicates the work |
---|
| 2041 | + * resetting the values to defaults. This duplicates the work |
---|
1660 | 2042 | * done in drm_add_edid_modes, but that function is not |
---|
1661 | 2043 | * consistently called before this one in all drivers and the |
---|
1662 | 2044 | * computation is cheap enough that it seems better to |
---|
.. | .. |
---|
1668 | 2050 | else |
---|
1669 | 2051 | drm_reset_display_info(connector); |
---|
1670 | 2052 | |
---|
| 2053 | + drm_update_tile_info(connector, edid); |
---|
| 2054 | + |
---|
| 2055 | + if (connector->edid_blob_ptr) { |
---|
| 2056 | + old_edid = (const struct edid *)connector->edid_blob_ptr->data; |
---|
| 2057 | + if (old_edid) { |
---|
| 2058 | + if (!drm_edid_are_equal(edid, old_edid)) { |
---|
| 2059 | + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Edid was changed.\n", |
---|
| 2060 | + connector->base.id, connector->name); |
---|
| 2061 | + |
---|
| 2062 | + connector->epoch_counter += 1; |
---|
| 2063 | + DRM_DEBUG_KMS("Updating change counter to %llu\n", |
---|
| 2064 | + connector->epoch_counter); |
---|
| 2065 | + } |
---|
| 2066 | + } |
---|
| 2067 | + } |
---|
| 2068 | + |
---|
1671 | 2069 | drm_object_property_set_value(&connector->base, |
---|
1672 | 2070 | dev->mode_config.non_desktop_property, |
---|
1673 | 2071 | connector->display_info.non_desktop); |
---|
.. | .. |
---|
1678 | 2076 | edid, |
---|
1679 | 2077 | &connector->base, |
---|
1680 | 2078 | dev->mode_config.edid_property); |
---|
1681 | | - return ret; |
---|
| 2079 | + if (ret) |
---|
| 2080 | + return ret; |
---|
| 2081 | + return drm_connector_set_tile_property(connector); |
---|
1682 | 2082 | } |
---|
1683 | 2083 | EXPORT_SYMBOL(drm_connector_update_edid_property); |
---|
1684 | 2084 | |
---|
.. | .. |
---|
1713 | 2113 | EXPORT_SYMBOL(drm_connector_set_link_status_property); |
---|
1714 | 2114 | |
---|
1715 | 2115 | /** |
---|
1716 | | - * drm_connector_init_panel_orientation_property - |
---|
1717 | | - * initialize the connecters panel_orientation property |
---|
1718 | | - * @connector: connector for which to init the panel-orientation property. |
---|
1719 | | - * @width: width in pixels of the panel, used for panel quirk detection |
---|
1720 | | - * @height: height in pixels of the panel, used for panel quirk detection |
---|
| 2116 | + * drm_connector_attach_max_bpc_property - attach "max bpc" property |
---|
| 2117 | + * @connector: connector to attach max bpc property on. |
---|
| 2118 | + * @min: The minimum bit depth supported by the connector. |
---|
| 2119 | + * @max: The maximum bit depth supported by the connector. |
---|
1721 | 2120 | * |
---|
1722 | | - * This function should only be called for built-in panels, after setting |
---|
1723 | | - * connector->display_info.panel_orientation first (if known). |
---|
1724 | | - * |
---|
1725 | | - * This function will check for platform specific (e.g. DMI based) quirks |
---|
1726 | | - * overriding display_info.panel_orientation first, then if panel_orientation |
---|
1727 | | - * is not DRM_MODE_PANEL_ORIENTATION_UNKNOWN it will attach the |
---|
1728 | | - * "panel orientation" property to the connector. |
---|
| 2121 | + * This is used to add support for limiting the bit depth on a connector. |
---|
1729 | 2122 | * |
---|
1730 | 2123 | * Returns: |
---|
1731 | 2124 | * Zero on success, negative errno on failure. |
---|
1732 | 2125 | */ |
---|
1733 | | -int drm_connector_init_panel_orientation_property( |
---|
1734 | | - struct drm_connector *connector, int width, int height) |
---|
| 2126 | +int drm_connector_attach_max_bpc_property(struct drm_connector *connector, |
---|
| 2127 | + int min, int max) |
---|
| 2128 | +{ |
---|
| 2129 | + struct drm_device *dev = connector->dev; |
---|
| 2130 | + struct drm_property *prop; |
---|
| 2131 | + |
---|
| 2132 | + prop = connector->max_bpc_property; |
---|
| 2133 | + if (!prop) { |
---|
| 2134 | + prop = drm_property_create_range(dev, 0, "max bpc", min, max); |
---|
| 2135 | + if (!prop) |
---|
| 2136 | + return -ENOMEM; |
---|
| 2137 | + |
---|
| 2138 | + connector->max_bpc_property = prop; |
---|
| 2139 | + } |
---|
| 2140 | + |
---|
| 2141 | + drm_object_attach_property(&connector->base, prop, max); |
---|
| 2142 | + connector->state->max_requested_bpc = max; |
---|
| 2143 | + connector->state->max_bpc = max; |
---|
| 2144 | + |
---|
| 2145 | + return 0; |
---|
| 2146 | +} |
---|
| 2147 | +EXPORT_SYMBOL(drm_connector_attach_max_bpc_property); |
---|
| 2148 | + |
---|
| 2149 | +/** |
---|
| 2150 | + * drm_connector_set_vrr_capable_property - sets the variable refresh rate |
---|
| 2151 | + * capable property for a connector |
---|
| 2152 | + * @connector: drm connector |
---|
| 2153 | + * @capable: True if the connector is variable refresh rate capable |
---|
| 2154 | + * |
---|
| 2155 | + * Should be used by atomic drivers to update the indicated support for |
---|
| 2156 | + * variable refresh rate over a connector. |
---|
| 2157 | + */ |
---|
| 2158 | +void drm_connector_set_vrr_capable_property( |
---|
| 2159 | + struct drm_connector *connector, bool capable) |
---|
| 2160 | +{ |
---|
| 2161 | + if (!connector->vrr_capable_property) |
---|
| 2162 | + return; |
---|
| 2163 | + |
---|
| 2164 | + drm_object_property_set_value(&connector->base, |
---|
| 2165 | + connector->vrr_capable_property, |
---|
| 2166 | + capable); |
---|
| 2167 | +} |
---|
| 2168 | +EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); |
---|
| 2169 | + |
---|
| 2170 | +/** |
---|
| 2171 | + * drm_connector_set_panel_orientation - sets the connector's panel_orientation |
---|
| 2172 | + * @connector: connector for which to set the panel-orientation property. |
---|
| 2173 | + * @panel_orientation: drm_panel_orientation value to set |
---|
| 2174 | + * |
---|
| 2175 | + * This function sets the connector's panel_orientation and attaches |
---|
| 2176 | + * a "panel orientation" property to the connector. |
---|
| 2177 | + * |
---|
| 2178 | + * Calling this function on a connector where the panel_orientation has |
---|
| 2179 | + * already been set is a no-op (e.g. the orientation has been overridden with |
---|
| 2180 | + * a kernel commandline option). |
---|
| 2181 | + * |
---|
| 2182 | + * It is allowed to call this function with a panel_orientation of |
---|
| 2183 | + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN, in which case it is a no-op. |
---|
| 2184 | + * |
---|
| 2185 | + * Returns: |
---|
| 2186 | + * Zero on success, negative errno on failure. |
---|
| 2187 | + */ |
---|
| 2188 | +int drm_connector_set_panel_orientation( |
---|
| 2189 | + struct drm_connector *connector, |
---|
| 2190 | + enum drm_panel_orientation panel_orientation) |
---|
1735 | 2191 | { |
---|
1736 | 2192 | struct drm_device *dev = connector->dev; |
---|
1737 | 2193 | struct drm_display_info *info = &connector->display_info; |
---|
1738 | 2194 | struct drm_property *prop; |
---|
1739 | | - int orientation_quirk; |
---|
1740 | 2195 | |
---|
1741 | | - orientation_quirk = drm_get_panel_orientation_quirk(width, height); |
---|
1742 | | - if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) |
---|
1743 | | - info->panel_orientation = orientation_quirk; |
---|
1744 | | - |
---|
1745 | | - if (info->panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) |
---|
| 2196 | + /* Already set? */ |
---|
| 2197 | + if (info->panel_orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) |
---|
1746 | 2198 | return 0; |
---|
| 2199 | + |
---|
| 2200 | + /* Don't attach the property if the orientation is unknown */ |
---|
| 2201 | + if (panel_orientation == DRM_MODE_PANEL_ORIENTATION_UNKNOWN) |
---|
| 2202 | + return 0; |
---|
| 2203 | + |
---|
| 2204 | + info->panel_orientation = panel_orientation; |
---|
1747 | 2205 | |
---|
1748 | 2206 | prop = dev->mode_config.panel_orientation_property; |
---|
1749 | 2207 | if (!prop) { |
---|
.. | .. |
---|
1761 | 2219 | info->panel_orientation); |
---|
1762 | 2220 | return 0; |
---|
1763 | 2221 | } |
---|
1764 | | -EXPORT_SYMBOL(drm_connector_init_panel_orientation_property); |
---|
| 2222 | +EXPORT_SYMBOL(drm_connector_set_panel_orientation); |
---|
| 2223 | + |
---|
| 2224 | +/** |
---|
| 2225 | + * drm_connector_set_panel_orientation_with_quirk - |
---|
| 2226 | + * set the connector's panel_orientation after checking for quirks |
---|
| 2227 | + * @connector: connector for which to init the panel-orientation property. |
---|
| 2228 | + * @panel_orientation: drm_panel_orientation value to set |
---|
| 2229 | + * @width: width in pixels of the panel, used for panel quirk detection |
---|
| 2230 | + * @height: height in pixels of the panel, used for panel quirk detection |
---|
| 2231 | + * |
---|
| 2232 | + * Like drm_connector_set_panel_orientation(), but with a check for platform |
---|
| 2233 | + * specific (e.g. DMI based) quirks overriding the passed in panel_orientation. |
---|
| 2234 | + * |
---|
| 2235 | + * Returns: |
---|
| 2236 | + * Zero on success, negative errno on failure. |
---|
| 2237 | + */ |
---|
| 2238 | +int drm_connector_set_panel_orientation_with_quirk( |
---|
| 2239 | + struct drm_connector *connector, |
---|
| 2240 | + enum drm_panel_orientation panel_orientation, |
---|
| 2241 | + int width, int height) |
---|
| 2242 | +{ |
---|
| 2243 | + int orientation_quirk; |
---|
| 2244 | + |
---|
| 2245 | + orientation_quirk = drm_get_panel_orientation_quirk(width, height); |
---|
| 2246 | + if (orientation_quirk != DRM_MODE_PANEL_ORIENTATION_UNKNOWN) |
---|
| 2247 | + panel_orientation = orientation_quirk; |
---|
| 2248 | + |
---|
| 2249 | + return drm_connector_set_panel_orientation(connector, |
---|
| 2250 | + panel_orientation); |
---|
| 2251 | +} |
---|
| 2252 | +EXPORT_SYMBOL(drm_connector_set_panel_orientation_with_quirk); |
---|
1765 | 2253 | |
---|
1766 | 2254 | int drm_connector_set_obj_prop(struct drm_mode_object *obj, |
---|
1767 | 2255 | struct drm_property *property, |
---|
.. | .. |
---|
1807 | 2295 | |
---|
1808 | 2296 | static bool |
---|
1809 | 2297 | drm_mode_expose_to_userspace(const struct drm_display_mode *mode, |
---|
1810 | | - const struct list_head *export_list, |
---|
| 2298 | + const struct list_head *modes, |
---|
1811 | 2299 | const struct drm_file *file_priv) |
---|
1812 | 2300 | { |
---|
1813 | 2301 | /* |
---|
.. | .. |
---|
1823 | 2311 | * while preparing the list of user-modes. |
---|
1824 | 2312 | */ |
---|
1825 | 2313 | if (!file_priv->aspect_ratio_allowed) { |
---|
1826 | | - struct drm_display_mode *mode_itr; |
---|
| 2314 | + const struct drm_display_mode *mode_itr; |
---|
1827 | 2315 | |
---|
1828 | | - list_for_each_entry(mode_itr, export_list, export_head) |
---|
1829 | | - if (drm_mode_match(mode_itr, mode, |
---|
| 2316 | + list_for_each_entry(mode_itr, modes, head) { |
---|
| 2317 | + if (mode_itr->expose_to_userspace && |
---|
| 2318 | + drm_mode_match(mode_itr, mode, |
---|
1830 | 2319 | DRM_MODE_MATCH_TIMINGS | |
---|
1831 | 2320 | DRM_MODE_MATCH_CLOCK | |
---|
1832 | 2321 | DRM_MODE_MATCH_FLAGS | |
---|
1833 | 2322 | DRM_MODE_MATCH_3D_FLAGS)) |
---|
1834 | 2323 | return false; |
---|
| 2324 | + } |
---|
1835 | 2325 | } |
---|
1836 | 2326 | |
---|
1837 | 2327 | return true; |
---|
.. | .. |
---|
1848 | 2338 | int encoders_count = 0; |
---|
1849 | 2339 | int ret = 0; |
---|
1850 | 2340 | int copied = 0; |
---|
1851 | | - int i; |
---|
1852 | 2341 | struct drm_mode_modeinfo u_mode; |
---|
1853 | 2342 | struct drm_mode_modeinfo __user *mode_ptr; |
---|
1854 | 2343 | uint32_t __user *encoder_ptr; |
---|
1855 | | - LIST_HEAD(export_list); |
---|
1856 | 2344 | |
---|
1857 | 2345 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
---|
1858 | | - return -EINVAL; |
---|
| 2346 | + return -EOPNOTSUPP; |
---|
1859 | 2347 | |
---|
1860 | 2348 | memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); |
---|
1861 | 2349 | |
---|
.. | .. |
---|
1863 | 2351 | if (!connector) |
---|
1864 | 2352 | return -ENOENT; |
---|
1865 | 2353 | |
---|
1866 | | - drm_connector_for_each_possible_encoder(connector, encoder, i) |
---|
1867 | | - encoders_count++; |
---|
| 2354 | + encoders_count = hweight32(connector->possible_encoders); |
---|
1868 | 2355 | |
---|
1869 | 2356 | if ((out_resp->count_encoders >= encoders_count) && encoders_count) { |
---|
1870 | 2357 | copied = 0; |
---|
1871 | 2358 | encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr); |
---|
1872 | 2359 | |
---|
1873 | | - drm_connector_for_each_possible_encoder(connector, encoder, i) { |
---|
| 2360 | + drm_connector_for_each_possible_encoder(connector, encoder) { |
---|
1874 | 2361 | if (put_user(encoder->base.id, encoder_ptr + copied)) { |
---|
1875 | 2362 | ret = -EFAULT; |
---|
1876 | 2363 | goto out; |
---|
.. | .. |
---|
1897 | 2384 | out_resp->connection = connector->status; |
---|
1898 | 2385 | |
---|
1899 | 2386 | /* delayed so we get modes regardless of pre-fill_modes state */ |
---|
1900 | | - list_for_each_entry(mode, &connector->modes, head) |
---|
1901 | | - if (drm_mode_expose_to_userspace(mode, &export_list, |
---|
| 2387 | + list_for_each_entry(mode, &connector->modes, head) { |
---|
| 2388 | + WARN_ON(mode->expose_to_userspace); |
---|
| 2389 | + |
---|
| 2390 | + if (drm_mode_expose_to_userspace(mode, &connector->modes, |
---|
1902 | 2391 | file_priv)) { |
---|
1903 | | - list_add_tail(&mode->export_head, &export_list); |
---|
| 2392 | + mode->expose_to_userspace = true; |
---|
1904 | 2393 | mode_count++; |
---|
1905 | 2394 | } |
---|
| 2395 | + } |
---|
1906 | 2396 | |
---|
1907 | 2397 | /* |
---|
1908 | 2398 | * This ioctl is called twice, once to determine how much space is |
---|
1909 | 2399 | * needed, and the 2nd time to fill it. |
---|
1910 | | - * The modes that need to be exposed to the user are maintained in the |
---|
1911 | | - * 'export_list'. When the ioctl is called first time to determine the, |
---|
1912 | | - * space, the export_list gets filled, to find the no.of modes. In the |
---|
1913 | | - * 2nd time, the user modes are filled, one by one from the export_list. |
---|
1914 | 2400 | */ |
---|
1915 | 2401 | if ((out_resp->count_modes >= mode_count) && mode_count) { |
---|
1916 | 2402 | copied = 0; |
---|
1917 | 2403 | mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; |
---|
1918 | | - list_for_each_entry(mode, &export_list, export_head) { |
---|
| 2404 | + list_for_each_entry(mode, &connector->modes, head) { |
---|
| 2405 | + if (!mode->expose_to_userspace) |
---|
| 2406 | + continue; |
---|
| 2407 | + |
---|
| 2408 | + /* Clear the tag for the next time around */ |
---|
| 2409 | + mode->expose_to_userspace = false; |
---|
| 2410 | + |
---|
1919 | 2411 | drm_mode_convert_to_umode(&u_mode, mode); |
---|
1920 | 2412 | /* |
---|
1921 | 2413 | * Reset aspect ratio flags of user-mode, if modes with |
---|
.. | .. |
---|
1926 | 2418 | if (copy_to_user(mode_ptr + copied, |
---|
1927 | 2419 | &u_mode, sizeof(u_mode))) { |
---|
1928 | 2420 | ret = -EFAULT; |
---|
| 2421 | + |
---|
| 2422 | + /* |
---|
| 2423 | + * Clear the tag for the rest of |
---|
| 2424 | + * the modes for the next time around. |
---|
| 2425 | + */ |
---|
| 2426 | + list_for_each_entry_continue(mode, &connector->modes, head) |
---|
| 2427 | + mode->expose_to_userspace = false; |
---|
| 2428 | + |
---|
1929 | 2429 | mutex_unlock(&dev->mode_config.mutex); |
---|
1930 | 2430 | |
---|
1931 | 2431 | goto out; |
---|
1932 | 2432 | } |
---|
1933 | 2433 | copied++; |
---|
1934 | 2434 | } |
---|
| 2435 | + } else { |
---|
| 2436 | + /* Clear the tag for the next time around */ |
---|
| 2437 | + list_for_each_entry(mode, &connector->modes, head) |
---|
| 2438 | + mode->expose_to_userspace = false; |
---|
1935 | 2439 | } |
---|
| 2440 | + |
---|
1936 | 2441 | out_resp->count_modes = mode_count; |
---|
1937 | 2442 | mutex_unlock(&dev->mode_config.mutex); |
---|
1938 | 2443 | |
---|
.. | .. |
---|
1974 | 2479 | { |
---|
1975 | 2480 | struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount); |
---|
1976 | 2481 | struct drm_device *dev = tg->dev; |
---|
| 2482 | + |
---|
1977 | 2483 | mutex_lock(&dev->mode_config.idr_mutex); |
---|
1978 | 2484 | idr_remove(&dev->mode_config.tile_idr, tg->id); |
---|
1979 | 2485 | mutex_unlock(&dev->mode_config.idr_mutex); |
---|
.. | .. |
---|
2005 | 2511 | * tile group or NULL if not found. |
---|
2006 | 2512 | */ |
---|
2007 | 2513 | struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev, |
---|
2008 | | - char topology[8]) |
---|
| 2514 | + const char topology[8]) |
---|
2009 | 2515 | { |
---|
2010 | 2516 | struct drm_tile_group *tg; |
---|
2011 | 2517 | int id; |
---|
| 2518 | + |
---|
2012 | 2519 | mutex_lock(&dev->mode_config.idr_mutex); |
---|
2013 | 2520 | idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) { |
---|
2014 | 2521 | if (!memcmp(tg->group_data, topology, 8)) { |
---|
.. | .. |
---|
2032 | 2539 | * identifier for the tile group. |
---|
2033 | 2540 | * |
---|
2034 | 2541 | * RETURNS: |
---|
2035 | | - * new tile group or error. |
---|
| 2542 | + * new tile group or NULL. |
---|
2036 | 2543 | */ |
---|
2037 | 2544 | struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, |
---|
2038 | | - char topology[8]) |
---|
| 2545 | + const char topology[8]) |
---|
2039 | 2546 | { |
---|
2040 | 2547 | struct drm_tile_group *tg; |
---|
2041 | 2548 | int ret; |
---|
2042 | 2549 | |
---|
2043 | 2550 | tg = kzalloc(sizeof(*tg), GFP_KERNEL); |
---|
2044 | 2551 | if (!tg) |
---|
2045 | | - return ERR_PTR(-ENOMEM); |
---|
| 2552 | + return NULL; |
---|
2046 | 2553 | |
---|
2047 | 2554 | kref_init(&tg->refcount); |
---|
2048 | 2555 | memcpy(tg->group_data, topology, 8); |
---|
.. | .. |
---|
2054 | 2561 | tg->id = ret; |
---|
2055 | 2562 | } else { |
---|
2056 | 2563 | kfree(tg); |
---|
2057 | | - tg = ERR_PTR(ret); |
---|
| 2564 | + tg = NULL; |
---|
2058 | 2565 | } |
---|
2059 | 2566 | |
---|
2060 | 2567 | mutex_unlock(&dev->mode_config.idr_mutex); |
---|