aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2017-11-14 13:32:57 -0500
committerVille Syrjälä <ville.syrjala@linux.intel.com>2018-01-29 14:51:51 -0500
commit75a655e0a26cf0bfbaaa8df0ff5a9d1807bb1f4e (patch)
treedd77ee71b0813434e34d971aeaa1a64251a24545
parentb7245cc536b95167d67b53e27adff964400045f1 (diff)
drm/modes: Provide global mode_valid hook
Allow drivers to provide a device wide .mode_valid() hook in addition to the already existing crtc/encoder/bridge/connector hooks. This can be used to validate device/driver wide constraings without having to add those to the other hooks. And since we call this hook also for user modes later on in the modeset we don't have to worry about anything the hook has already rejected. I also have some further ideas for this hook. Eg. we could replace the drm_mode_set_crtcinfo(HALVE_V) call in drm_mode_convert_umode()/etc. with a driver specific variant via this hook. At least on i915 we would like to pass CRTC_STEREO_DOUBLE to that function instead, and then we could safely use the crtc_ timings in all our .mode_valid() hooks, which would allow us to reuse those hooks for validating the adjusted_mode during a modeset. v2: Fix the language fails in the kernel docs (Daniel) Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20171114183258.16976-10-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/drm_atomic.c2
-rw-r--r--drivers/gpu/drm/drm_crtc.c2
-rw-r--r--drivers/gpu/drm/drm_modes.c48
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c2
-rw-r--r--include/drm/drm_mode_config.h12
-rw-r--r--include/drm/drm_modes.h6
6 files changed, 53 insertions, 19 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index b76d49218cf1..51a848c553b9 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -390,7 +390,7 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
390 390
391 if (blob) { 391 if (blob) {
392 if (blob->length != sizeof(struct drm_mode_modeinfo) || 392 if (blob->length != sizeof(struct drm_mode_modeinfo) ||
393 drm_mode_convert_umode(&state->mode, 393 drm_mode_convert_umode(state->crtc->dev, &state->mode,
394 (const struct drm_mode_modeinfo *) 394 (const struct drm_mode_modeinfo *)
395 blob->data)) 395 blob->data))
396 return -EINVAL; 396 return -EINVAL;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 5b4be382a1d7..353e24fcde9e 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -614,7 +614,7 @@ retry:
614 goto out; 614 goto out;
615 } 615 }
616 616
617 ret = drm_mode_convert_umode(mode, &crtc_req->mode); 617 ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode);
618 if (ret) { 618 if (ret) {
619 DRM_DEBUG_KMS("Invalid mode\n"); 619 DRM_DEBUG_KMS("Invalid mode\n");
620 goto out; 620 goto out;
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index b35324a50fdf..c397b523c945 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1023,17 +1023,7 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
1023} 1023}
1024EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo); 1024EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
1025 1025
1026/** 1026static enum drm_mode_status
1027 * drm_mode_validate_basic - make sure the mode is somewhat sane
1028 * @mode: mode to check
1029 *
1030 * Check that the mode timings are at least somewhat reasonable.
1031 * Any hardware specific limits are left up for each driver to check.
1032 *
1033 * Returns:
1034 * The mode status
1035 */
1036enum drm_mode_status
1037drm_mode_validate_basic(const struct drm_display_mode *mode) 1027drm_mode_validate_basic(const struct drm_display_mode *mode)
1038{ 1028{
1039 if (mode->type & ~DRM_MODE_TYPE_ALL) 1029 if (mode->type & ~DRM_MODE_TYPE_ALL)
@@ -1062,7 +1052,35 @@ drm_mode_validate_basic(const struct drm_display_mode *mode)
1062 1052
1063 return MODE_OK; 1053 return MODE_OK;
1064} 1054}
1065EXPORT_SYMBOL(drm_mode_validate_basic); 1055
1056/**
1057 * drm_mode_validate_driver - make sure the mode is somewhat sane
1058 * @dev: drm device
1059 * @mode: mode to check
1060 *
1061 * First do basic validation on the mode, and then allow the driver
1062 * to check for device/driver specific limitations via the optional
1063 * &drm_mode_config_helper_funcs.mode_valid hook.
1064 *
1065 * Returns:
1066 * The mode status
1067 */
1068enum drm_mode_status
1069drm_mode_validate_driver(struct drm_device *dev,
1070 const struct drm_display_mode *mode)
1071{
1072 enum drm_mode_status status;
1073
1074 status = drm_mode_validate_basic(mode);
1075 if (status != MODE_OK)
1076 return status;
1077
1078 if (dev->mode_config.funcs->mode_valid)
1079 return dev->mode_config.funcs->mode_valid(dev, mode);
1080 else
1081 return MODE_OK;
1082}
1083EXPORT_SYMBOL(drm_mode_validate_driver);
1066 1084
1067/** 1085/**
1068 * drm_mode_validate_size - make sure modes adhere to size constraints 1086 * drm_mode_validate_size - make sure modes adhere to size constraints
@@ -1564,6 +1582,7 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
1564 1582
1565/** 1583/**
1566 * drm_crtc_convert_umode - convert a modeinfo into a drm_display_mode 1584 * drm_crtc_convert_umode - convert a modeinfo into a drm_display_mode
1585 * @dev: drm device
1567 * @out: drm_display_mode to return to the user 1586 * @out: drm_display_mode to return to the user
1568 * @in: drm_mode_modeinfo to use 1587 * @in: drm_mode_modeinfo to use
1569 * 1588 *
@@ -1573,7 +1592,8 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
1573 * Returns: 1592 * Returns:
1574 * Zero on success, negative errno on failure. 1593 * Zero on success, negative errno on failure.
1575 */ 1594 */
1576int drm_mode_convert_umode(struct drm_display_mode *out, 1595int drm_mode_convert_umode(struct drm_device *dev,
1596 struct drm_display_mode *out,
1577 const struct drm_mode_modeinfo *in) 1597 const struct drm_mode_modeinfo *in)
1578{ 1598{
1579 int ret = -EINVAL; 1599 int ret = -EINVAL;
@@ -1600,7 +1620,7 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
1600 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); 1620 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1601 out->name[DRM_DISPLAY_MODE_LEN-1] = 0; 1621 out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1602 1622
1603 out->status = drm_mode_validate_basic(out); 1623 out->status = drm_mode_validate_driver(dev, out);
1604 if (out->status != MODE_OK) 1624 if (out->status != MODE_OK)
1605 goto out; 1625 goto out;
1606 1626
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 555fbe54d6e2..2d1643bdae78 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -499,7 +499,7 @@ retry:
499 499
500 list_for_each_entry(mode, &connector->modes, head) { 500 list_for_each_entry(mode, &connector->modes, head) {
501 if (mode->status == MODE_OK) 501 if (mode->status == MODE_OK)
502 mode->status = drm_mode_validate_basic(mode); 502 mode->status = drm_mode_validate_driver(dev, mode);
503 503
504 if (mode->status == MODE_OK) 504 if (mode->status == MODE_OK)
505 mode->status = drm_mode_validate_size(mode, maxX, maxY); 505 mode->status = drm_mode_validate_size(mode, maxX, maxY);
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 2cb6f02df64a..7569f22ffef6 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -36,6 +36,7 @@ struct drm_device;
36struct drm_atomic_state; 36struct drm_atomic_state;
37struct drm_mode_fb_cmd2; 37struct drm_mode_fb_cmd2;
38struct drm_format_info; 38struct drm_format_info;
39struct drm_display_mode;
39 40
40/** 41/**
41 * struct drm_mode_config_funcs - basic driver provided mode setting functions 42 * struct drm_mode_config_funcs - basic driver provided mode setting functions
@@ -102,6 +103,17 @@ struct drm_mode_config_funcs {
102 void (*output_poll_changed)(struct drm_device *dev); 103 void (*output_poll_changed)(struct drm_device *dev);
103 104
104 /** 105 /**
106 * @mode_valid:
107 *
108 * Device specific validation of display modes. Can be used to reject
109 * modes that can never be supported. Only device wide constraints can
110 * be checked here. crtc/encoder/bridge/connector specific constraints
111 * should be checked in the .mode_valid() hook for each specific object.
112 */
113 enum drm_mode_status (*mode_valid)(struct drm_device *dev,
114 const struct drm_display_mode *mode);
115
116 /**
105 * @atomic_check: 117 * @atomic_check:
106 * 118 *
107 * This is the only hook to validate an atomic modeset update. This 119 * This is the only hook to validate an atomic modeset update. This
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index 71cbb10e22dc..0d310beae6af 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -444,7 +444,8 @@ struct drm_display_mode *drm_mode_create(struct drm_device *dev);
444void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode); 444void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode);
445void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, 445void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
446 const struct drm_display_mode *in); 446 const struct drm_display_mode *in);
447int drm_mode_convert_umode(struct drm_display_mode *out, 447int drm_mode_convert_umode(struct drm_device *dev,
448 struct drm_display_mode *out,
448 const struct drm_mode_modeinfo *in); 449 const struct drm_mode_modeinfo *in);
449void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode); 450void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
450void drm_mode_debug_printmodeline(const struct drm_display_mode *mode); 451void drm_mode_debug_printmodeline(const struct drm_display_mode *mode);
@@ -497,7 +498,8 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
497 const struct drm_display_mode *mode2); 498 const struct drm_display_mode *mode2);
498 499
499/* for use by the crtc helper probe functions */ 500/* for use by the crtc helper probe functions */
500enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode); 501enum drm_mode_status drm_mode_validate_driver(struct drm_device *dev,
502 const struct drm_display_mode *mode);
501enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode, 503enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode,
502 int maxX, int maxY); 504 int maxX, int maxY);
503enum drm_mode_status 505enum drm_mode_status