All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/6] Introduce new mode validation callbacks
@ 2017-05-11  9:05 Jose Abreu
  2017-05-11  9:05 ` [PATCH v3 1/6] drm: Add crtc/encoder/bridge->mode_valid() callbacks Jose Abreu
                   ` (6 more replies)
  0 siblings, 7 replies; 46+ messages in thread
From: Jose Abreu @ 2017-05-11  9:05 UTC (permalink / raw)
  To: dri-devel, linux-kernel
  Cc: Jose Abreu, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Andrzej Hajda, Archit Taneja

This series is a follow up from the discussion at [1]. We start by
introducing crtc->mode_valid(), encoder->mode_valid() and
bridge->mode_valid() callbacks which will be used in followup
patches and also by cleaning the documentation a little bit.

We proceed by introducing new helpers to call this new callbacks
at 2/6.

At 3/6 a helper function is introduced that calls all mode_valid()
from a set of bridges.

Next, at 4/6 we modify the connector probe helper so that only modes
which are supported by a given bridge+encoder+crtc combination are
probbed.

At 5/6 we call all the mode_valid() callbacks for a given pipeline,
except the connector->mode_valid one, so that the mode is validated.
This is done before calling mode_fixup().

Finally, at 6/6 we use the new crtc->mode_valid() callback in arcpgu
and remove the atomic_check() callback.

[1] https://patchwork.kernel.org/patch/9702233/

Jose Abreu (6):
  drm: Add crtc/encoder/bridge->mode_valid() callbacks
  drm: Add drm_{crtc/encoder/connector}_mode_valid()
  drm: Introduce drm_bridge_mode_valid()
  drm: Use new mode_valid() helpers in connector probe helper
  drm: Use mode_valid() in atomic modeset
  drm: arc: Use crtc->mode_valid() callback

Cc: Carlos Palminha <palminha@synopsys.com>
Cc: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Airlie <airlied@linux.ie>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Archit Taneja <architt@codeaurora.org>

 drivers/gpu/drm/arc/arcpgu_crtc.c          |  39 ++++++----
 drivers/gpu/drm/drm_atomic_helper.c        |  76 +++++++++++++++++++-
 drivers/gpu/drm/drm_bridge.c               |  33 +++++++++
 drivers/gpu/drm/drm_crtc_helper_internal.h |  13 ++++
 drivers/gpu/drm/drm_probe_helper.c         | 103 ++++++++++++++++++++++++++-
 include/drm/drm_bridge.h                   |  22 ++++++
 include/drm/drm_modeset_helper_vtables.h   | 110 ++++++++++++++++++++++-------
 7 files changed, 348 insertions(+), 48 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v3 1/6] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-11  9:05 [PATCH v3 0/6] Introduce new mode validation callbacks Jose Abreu
@ 2017-05-11  9:05 ` Jose Abreu
  2017-05-12  7:00     ` Daniel Vetter
  2017-05-12  7:31   ` [PATCH] " Daniel Vetter
  2017-05-11  9:05 ` [PATCH v3 2/6] drm: Add drm_{crtc/encoder/connector}_mode_valid() Jose Abreu
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 46+ messages in thread
From: Jose Abreu @ 2017-05-11  9:05 UTC (permalink / raw)
  To: dri-devel, linux-kernel
  Cc: Jose Abreu, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Andrzej Hajda, Archit Taneja

This adds a new callback to crtc, encoder and bridge helper functions
called mode_valid(). This callback shall be implemented if the
corresponding component has some sort of restriction in the modes
that can be displayed. A NULL callback implicates that the component
can display all the modes.

We also change the documentation so that the new and old callbacks
are correctly documented.

Only the callbacks were implemented to simplify review process,
following patches will make use of them.

Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: Carlos Palminha <palminha@synopsys.com>
Cc: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Airlie <airlied@linux.ie>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Archit Taneja <architt@codeaurora.org>
---

Changes v2->v3:
	- Try to document the callbacks a little bit better and
	review current documentation (Daniel)
Changes v1->v2:
	- Change description of connector->mode_valid() (Daniel)

 include/drm/drm_bridge.h                 |  20 ++++++
 include/drm/drm_modeset_helper_vtables.h | 110 +++++++++++++++++++++++--------
 2 files changed, 103 insertions(+), 27 deletions(-)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index fdd82fc..00c6c36 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -59,6 +59,26 @@ struct drm_bridge_funcs {
 	void (*detach)(struct drm_bridge *bridge);
 
 	/**
+	 * @mode_valid:
+	 *
+	 * This callback is used to check if a specific mode is valid in this
+	 * bridge. This should be implemented if the bridge has some sort of
+	 * restriction in the modes it can display. For example, a given bridge
+	 * may be responsible to set a clock value. If the clock can not
+	 * produce all the values for the available modes then this callback
+	 * can be used to restrict the number of modes to only the ones that
+	 * can be displayed.
+	 *
+	 * This is called at mode probe and at atomic check phase.
+	 *
+	 * RETURNS:
+	 *
+	 * drm_mode_status Enum
+	 */
+	enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc,
+					   const struct drm_display_mode *mode);
+
+	/**
 	 * @mode_fixup:
 	 *
 	 * This callback is used to validate and adjust a mode. The paramater
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index c01c328..b07b7cd 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -106,14 +106,37 @@ struct drm_crtc_helper_funcs {
 	void (*commit)(struct drm_crtc *crtc);
 
 	/**
+	 * @mode_valid:
+	 *
+	 * This callback is used to check if a specific mode is valid in this
+	 * crtc. This should be implemented if the crtc has some sort of
+	 * restriction in the modes it can display. For example, a given crtc
+	 * may be responsible to set a clock value. If the clock can not
+	 * produce all the values for the available modes then this callback
+	 * can be used to restrict the number of modes to only the ones that
+	 * can be displayed.
+	 *
+	 * This is called at mode probe and at atomic check phase.
+	 *
+	 * RETURNS:
+	 *
+	 * drm_mode_status Enum
+	 */
+	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
+					   const struct drm_display_mode *mode);
+
+	/**
 	 * @mode_fixup:
 	 *
-	 * This callback is used to validate a mode. The parameter mode is the
-	 * display mode that userspace requested, adjusted_mode is the mode the
-	 * encoders need to be fed with. Note that this is the inverse semantics
-	 * of the meaning for the &drm_encoder and &drm_bridge_funcs.mode_fixup
-	 * vfunc. If the CRTC cannot support the requested conversion from mode
-	 * to adjusted_mode it should reject the modeset.
+	 * This callback is used to do the validation of an adjusted mode in the
+	 * crtc. The parameter mode is the display mode that userspace requested,
+	 * adjusted_mode is the mode the encoders need to be fed with. Note that
+	 * this is the inverse semantics of the meaning for the &drm_encoder and
+	 * &drm_bridge_funcs.mode_fixup vfunc. If the CRTC cannot support the
+	 * requested conversion from mode to adjusted_mode it should reject the
+	 * modeset. Also note that initial validation of a mode supplied by
+	 * userspace should be done in &drm_crtc_helper_funcs.mode_valid and not
+	 * in this callback.
 	 *
 	 * This function is used by both legacy CRTC helpers and atomic helpers.
 	 * With atomic helpers it is optional.
@@ -135,17 +158,19 @@ struct drm_crtc_helper_funcs {
 	 * Also beware that neither core nor helpers filter modes before
 	 * passing them to the driver: While the list of modes that is
 	 * advertised to userspace is filtered using the
-	 * &drm_connector.mode_valid callback, neither the core nor the helpers
-	 * do any filtering on modes passed in from userspace when setting a
-	 * mode. It is therefore possible for userspace to pass in a mode that
-	 * was previously filtered out using &drm_connector.mode_valid or add a
-	 * custom mode that wasn't probed from EDID or similar to begin with.
-	 * Even though this is an advanced feature and rarely used nowadays,
-	 * some users rely on being able to specify modes manually so drivers
-	 * must be prepared to deal with it. Specifically this means that all
-	 * drivers need not only validate modes in &drm_connector.mode_valid but
-	 * also in this or in the &drm_encoder_helper_funcs.mode_fixup callback
-	 * to make sure invalid modes passed in from userspace are rejected.
+	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
+	 * the helpers do any filtering on modes passed in from userspace when
+	 * setting a mode. It is therefore possible for userspace to pass in a
+	 * mode that was previously filtered out using
+	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
+	 * wasn't probed from EDID or similar to begin with. Even though this
+	 * is an advanced feature and rarely used nowadays, some users rely on
+	 * being able to specify modes manually so drivers must be prepared to
+	 * deal with it. Specifically this means that all drivers need not only
+	 * validate modes in &drm_connector.mode_valid but also in this or in
+	 * the &drm_crtc_helper_funcs.mode_valid,
+	 * &drm_encoder_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid
+	 * callbacks, where applicable.
 	 *
 	 * RETURNS:
 	 *
@@ -457,11 +482,31 @@ struct drm_encoder_helper_funcs {
 	void (*dpms)(struct drm_encoder *encoder, int mode);
 
 	/**
+	 * @mode_valid:
+	 *
+	 * This callback is used to check if a specific mode is valid in this
+	 * encoder. This should be implemented if the encoder has some sort
+	 * of restriction in the modes it can display. For example, a given
+	 * encoder may be responsible to set a clock value. If the clock can
+	 * not produce all the values for the available modes then this callback
+	 * can be used to restrict the number of modes to only the ones that
+	 * can be displayed.
+	 *
+	 * This is called at mode probe and at atomic check phase.
+	 *
+	 * RETURNS:
+	 *
+	 * drm_mode_status Enum
+	 */
+	enum drm_mode_status (*mode_valid)(struct drm_encoder *crtc,
+					   const struct drm_display_mode *mode);
+
+	/**
 	 * @mode_fixup:
 	 *
-	 * This callback is used to validate and adjust a mode. The parameter
-	 * mode is the display mode that should be fed to the next element in
-	 * the display chain, either the final &drm_connector or a &drm_bridge.
+	 * This callback is used to adjust a mode. The parameter mode is the
+	 * display mode that should be fed to the next element in the display
+	 * chain, either the final &drm_connector or a &drm_bridge.
 	 * The parameter adjusted_mode is the input mode the encoder requires. It
 	 * can be modified by this callback and does not need to match mode.
 	 *
@@ -484,19 +529,20 @@ struct drm_encoder_helper_funcs {
 	 *
 	 * Also beware that neither core nor helpers filter modes before
 	 * passing them to the driver: While the list of modes that is
-	 * advertised to userspace is filtered using the connector's
+	 * advertised to userspace is filtered using the
 	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
 	 * the helpers do any filtering on modes passed in from userspace when
 	 * setting a mode. It is therefore possible for userspace to pass in a
 	 * mode that was previously filtered out using
 	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
-	 * wasn't probed from EDID or similar to begin with.  Even though this
+	 * wasn't probed from EDID or similar to begin with. Even though this
 	 * is an advanced feature and rarely used nowadays, some users rely on
 	 * being able to specify modes manually so drivers must be prepared to
 	 * deal with it. Specifically this means that all drivers need not only
 	 * validate modes in &drm_connector.mode_valid but also in this or in
-	 * the &drm_crtc_helper_funcs.mode_fixup callback to make sure
-	 * invalid modes passed in from userspace are rejected.
+	 * the &drm_crtc_helper_funcs.mode_valid,
+	 * &drm_encoder_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid
+	 * callbacks, where applicable.
 	 *
 	 * RETURNS:
 	 *
@@ -795,13 +841,23 @@ struct drm_connector_helper_funcs {
 	 * (which is usually derived from the EDID data block from the sink).
 	 * See e.g. drm_helper_probe_single_connector_modes().
 	 *
+	 * This callback is never called in atomic check phase so that userspace
+	 * can override kernel sink checks in case of broken EDID with wrong
+	 * limits from the sink. You can use the remaining mode_valid()
+	 * callbacks to validate the mode against your video path.
+	 *
 	 * NOTE:
 	 *
 	 * This only filters the mode list supplied to userspace in the
-	 * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and
+	 * GETCONNECTOR IOCTL. Userspace is free to create modes of its own and
 	 * ask the kernel to use them. It this case the atomic helpers or legacy
-	 * CRTC helpers will not call this function. Drivers therefore must
-	 * still fully validate any mode passed in in a modeset request.
+	 * CRTC helpers will not call this function but the mode will be
+	 * validated in atomic check phase using the mode_valid() callbacks
+	 * (&drm_crtc_helper_funcs.mode_valid, &drm_encoder_helper_funcs.mode_valid
+	 * and &drm_bridge_funcs.mode_valid).
+	 * Drivers therefore must implement the mode_valid() callbacks if the
+	 * video pipeline has some sort of restrictions in the modes that can
+	 * be displayed.
 	 *
 	 * To avoid races with concurrent connector state updates, the helper
 	 * libraries always call this with the &drm_mode_config.connection_mutex
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 2/6] drm: Add drm_{crtc/encoder/connector}_mode_valid()
  2017-05-11  9:05 [PATCH v3 0/6] Introduce new mode validation callbacks Jose Abreu
  2017-05-11  9:05 ` [PATCH v3 1/6] drm: Add crtc/encoder/bridge->mode_valid() callbacks Jose Abreu
@ 2017-05-11  9:05 ` Jose Abreu
  2017-05-15  8:27     ` Andrzej Hajda
  2017-05-11  9:05 ` [PATCH v3 3/6] drm: Introduce drm_bridge_mode_valid() Jose Abreu
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 46+ messages in thread
From: Jose Abreu @ 2017-05-11  9:05 UTC (permalink / raw)
  To: dri-devel, linux-kernel
  Cc: Jose Abreu, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Andrzej Hajda, Archit Taneja

Add a new helper to call crtc->mode_valid, connector->mode_valid
and encoder->mode_valid callbacks.

Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: Carlos Palminha <palminha@synopsys.com>
Cc: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Airlie <airlied@linux.ie>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Archit Taneja <architt@codeaurora.org>
---

Changes v2->v3:
	- Move helpers to drm_probe_helper.c (Daniel)
	- Squeeze patches that introduce the helpers into a single
	one (Daniel)

 drivers/gpu/drm/drm_crtc_helper_internal.h | 13 ++++++++++
 drivers/gpu/drm/drm_probe_helper.c         | 38 ++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+)

diff --git a/drivers/gpu/drm/drm_crtc_helper_internal.h b/drivers/gpu/drm/drm_crtc_helper_internal.h
index 28295e5..97dfe20 100644
--- a/drivers/gpu/drm/drm_crtc_helper_internal.h
+++ b/drivers/gpu/drm/drm_crtc_helper_internal.h
@@ -26,7 +26,11 @@
  * implementation details and are not exported to drivers.
  */
 
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
 #include <drm/drm_dp_helper.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_modes.h>
 
 /* drm_fb_helper.c */
 #ifdef CONFIG_DRM_FBDEV_EMULATION
@@ -62,4 +66,13 @@ static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
 static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
 {
 }
+
+/* drm_probe_helper.c */
+enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
+					 const struct drm_display_mode *mode);
+enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder,
+					    const struct drm_display_mode *mode);
+enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
+					      struct drm_display_mode *mode);
+
 #endif
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 1b0c14a..f01abdc 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -38,6 +38,9 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_modeset_helper_vtables.h>
+
+#include "drm_crtc_helper_internal.h"
 
 /**
  * DOC: output probing helper overview
@@ -113,6 +116,41 @@ static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
 	return 1;
 }
 
+enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
+					 const struct drm_display_mode *mode)
+{
+	const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+
+	if (!crtc_funcs || !crtc_funcs->mode_valid)
+		return MODE_OK;
+
+	return crtc_funcs->mode_valid(crtc, mode);
+}
+
+enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder,
+					    const struct drm_display_mode *mode)
+{
+	const struct drm_encoder_helper_funcs *encoder_funcs =
+		encoder->helper_private;
+
+	if (!encoder_funcs || !encoder_funcs->mode_valid)
+		return MODE_OK;
+
+	return encoder_funcs->mode_valid(encoder, mode);
+}
+
+enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
+					      struct drm_display_mode *mode)
+{
+	const struct drm_connector_helper_funcs *connector_funcs =
+		connector->helper_private;
+
+	if (!connector_funcs || !connector_funcs->mode_valid)
+		return MODE_OK;
+
+	return connector_funcs->mode_valid(connector, mode);
+}
+
 #define DRM_OUTPUT_POLL_PERIOD (10*HZ)
 /**
  * drm_kms_helper_poll_enable - re-enable output polling.
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 3/6] drm: Introduce drm_bridge_mode_valid()
  2017-05-11  9:05 [PATCH v3 0/6] Introduce new mode validation callbacks Jose Abreu
  2017-05-11  9:05 ` [PATCH v3 1/6] drm: Add crtc/encoder/bridge->mode_valid() callbacks Jose Abreu
  2017-05-11  9:05 ` [PATCH v3 2/6] drm: Add drm_{crtc/encoder/connector}_mode_valid() Jose Abreu
@ 2017-05-11  9:05 ` Jose Abreu
  2017-05-11  9:06 ` [PATCH v3 4/6] drm: Use new mode_valid() helpers in connector probe helper Jose Abreu
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 46+ messages in thread
From: Jose Abreu @ 2017-05-11  9:05 UTC (permalink / raw)
  To: dri-devel, linux-kernel
  Cc: Jose Abreu, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Andrzej Hajda, Archit Taneja

Introduce a new helper function which calls mode_valid() callback
for all bridges in an encoder chain.

Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: Carlos Palminha <palminha@synopsys.com>
Cc: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Airlie <airlied@linux.ie>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/drm_bridge.c | 33 +++++++++++++++++++++++++++++++++
 include/drm/drm_bridge.h     |  2 ++
 2 files changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 86a7637..dc8cdfe 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -206,6 +206,39 @@ bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
 EXPORT_SYMBOL(drm_bridge_mode_fixup);
 
 /**
+ * drm_bridge_mode_valid - validate the mode against all bridges in the
+ * 			   encoder chain.
+ * @bridge: bridge control structure
+ * @mode: desired mode to be validated
+ *
+ * Calls &drm_bridge_funcs.mode_valid for all the bridges in the encoder
+ * chain, starting from the first bridge to the last. If at least one bridge
+ * does not accept the mode the function returns the error code.
+ *
+ * Note: the bridge passed should be the one closest to the encoder.
+ *
+ * RETURNS:
+ * MODE_OK on success, drm_mode_status Enum error code on failure
+ */
+enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge,
+					   const struct drm_display_mode *mode)
+{
+	enum drm_mode_status ret = MODE_OK;
+
+	if (!bridge)
+		return ret;
+
+	if (bridge->funcs->mode_valid)
+		ret = bridge->funcs->mode_valid(bridge, mode);
+
+	if (ret != MODE_OK)
+		return ret;
+
+	return drm_bridge_mode_valid(bridge->next, mode);
+}
+EXPORT_SYMBOL(drm_bridge_mode_valid);
+
+/**
  * drm_bridge_disable - disables all bridges in the encoder chain
  * @bridge: bridge control structure
  *
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 00c6c36..8358eb3 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -233,6 +233,8 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
 bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
 			const struct drm_display_mode *mode,
 			struct drm_display_mode *adjusted_mode);
+enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge,
+					   const struct drm_display_mode *mode);
 void drm_bridge_disable(struct drm_bridge *bridge);
 void drm_bridge_post_disable(struct drm_bridge *bridge);
 void drm_bridge_mode_set(struct drm_bridge *bridge,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 4/6] drm: Use new mode_valid() helpers in connector probe helper
  2017-05-11  9:05 [PATCH v3 0/6] Introduce new mode validation callbacks Jose Abreu
                   ` (2 preceding siblings ...)
  2017-05-11  9:05 ` [PATCH v3 3/6] drm: Introduce drm_bridge_mode_valid() Jose Abreu
@ 2017-05-11  9:06 ` Jose Abreu
  2017-05-15  8:39     ` Andrzej Hajda
  2017-05-11  9:06 ` [PATCH v3 5/6] drm: Use mode_valid() in atomic modeset Jose Abreu
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 46+ messages in thread
From: Jose Abreu @ 2017-05-11  9:06 UTC (permalink / raw)
  To: dri-devel, linux-kernel
  Cc: Jose Abreu, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Andrzej Hajda, Archit Taneja

This changes the connector probe helper function to use the new
encoder->mode_valid(), bridge->mode_valid() and crtc->mode_valid()
helper callbacks to validate the modes.

The new callbacks are optional so the behaviour remains the same
if they are not implemented. If they are, then the code loops
through all the connector's encodersXbridgesXcrtcs and calls the
callback.

If at least a valid encoderXbridgeXcrtc combination is found which
accepts the mode then the function returns MODE_OK.

Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: Carlos Palminha <palminha@synopsys.com>
Cc: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Airlie <airlied@linux.ie>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Archit Taneja <architt@codeaurora.org>
---

Changes v2->v3:
	- Call also bridge->mode_valid (Daniel)
Changes v1->v2:
	- Use new helpers suggested by Ville
	- Change documentation (Daniel)

 drivers/gpu/drm/drm_probe_helper.c | 65 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 62 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index f01abdc..84d660e 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -83,6 +83,61 @@
 	return MODE_OK;
 }
 
+static enum drm_mode_status
+drm_mode_validate_connector(struct drm_connector *connector,
+			    struct drm_display_mode *mode)
+{
+	struct drm_device *dev = connector->dev;
+	uint32_t *ids = connector->encoder_ids;
+	enum drm_mode_status ret = MODE_OK;
+	unsigned int i;
+
+	/* Step 1: Validate against connector */
+	ret = drm_connector_mode_valid(connector, mode);
+	if (ret != MODE_OK)
+		return ret;
+
+	/* Step 2: Validate against encoders and crtcs */
+	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+		struct drm_encoder *encoder = drm_encoder_find(dev, ids[i]);
+		struct drm_crtc *crtc;
+
+		if (!encoder)
+			continue;
+
+		ret = drm_encoder_mode_valid(encoder, mode);
+		if (ret != MODE_OK) {
+			/* No point in continuing for crtc check as this encoder
+			 * will not accept the mode anyway. If all encoders
+			 * reject the mode then, at exit, ret will not be
+			 * MODE_OK. */
+			continue;
+		}
+
+		ret = drm_bridge_mode_valid(encoder->bridge, mode);
+		if (ret != MODE_OK) {
+			/* There is also no point in continuing for crtc check
+			 * here. */
+			continue;
+		}
+
+		drm_for_each_crtc(crtc, dev) {
+			if (!drm_encoder_crtc_ok(encoder, crtc))
+				continue;
+
+			ret = drm_crtc_mode_valid(crtc, mode);
+			if (ret == MODE_OK) {
+				/* If we get to this point there is at least
+				 * one combination of encoder+crtc that works
+				 * for this mode. Lets return now. */
+				return ret;
+			}
+		}
+	}
+
+	return ret;
+}
+
 static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
 {
 	struct drm_cmdline_mode *cmdline_mode;
@@ -322,7 +377,11 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
  *    - drm_mode_validate_flag() checks the modes against basic connector
  *      capabilities (interlace_allowed,doublescan_allowed,stereo_allowed)
  *    - the optional &drm_connector_helper_funcs.mode_valid helper can perform
- *      driver and/or hardware specific checks
+ *      driver and/or sink specific checks
+ *    - the optional &drm_crtc_helper_funcs.mode_valid,
+ *      &drm_bridge_funcs.mode_valid and &drm_encoder_helper_funcs.mode_valid
+ *      helpers can perform driver and/or source specific checks which are also
+ *      enforced by the modeset/atomic helpers
  *
  * 5. Any mode whose status is not OK is pruned from the connector's modes list,
  *    accompanied by a debug message indicating the reason for the mode's
@@ -466,8 +525,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
 		if (mode->status == MODE_OK)
 			mode->status = drm_mode_validate_flag(mode, mode_flags);
 
-		if (mode->status == MODE_OK && connector_funcs->mode_valid)
-			mode->status = connector_funcs->mode_valid(connector,
+		if (mode->status == MODE_OK)
+			mode->status = drm_mode_validate_connector(connector,
 								   mode);
 	}
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 5/6] drm: Use mode_valid() in atomic modeset
  2017-05-11  9:05 [PATCH v3 0/6] Introduce new mode validation callbacks Jose Abreu
                   ` (3 preceding siblings ...)
  2017-05-11  9:06 ` [PATCH v3 4/6] drm: Use new mode_valid() helpers in connector probe helper Jose Abreu
@ 2017-05-11  9:06 ` Jose Abreu
  2017-05-15  8:45   ` Andrzej Hajda
  2017-05-11  9:06 ` [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback Jose Abreu
  2017-05-12  7:32   ` Daniel Vetter
  6 siblings, 1 reply; 46+ messages in thread
From: Jose Abreu @ 2017-05-11  9:06 UTC (permalink / raw)
  To: dri-devel, linux-kernel
  Cc: Jose Abreu, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Andrzej Hajda, Archit Taneja

This patches makes use of the new mode_valid() callbacks introduced
previously to validate the full video pipeline when modesetting.

This calls the encoder->mode_valid(), bridge->mode_valid() and
crtc->mode_valid() so that we can make sure that the mode will
be accepted in every components.

Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: Carlos Palminha <palminha@synopsys.com>
Cc: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Airlie <airlied@linux.ie>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Archit Taneja <architt@codeaurora.org>
---

Changes v1->v2:
	- Removed call to connector->mode_valid (Ville, Daniel)
	- Change function name (Ville)
	- Use for_each_new_connector_in_state (Ville)
	- Do not validate if connector and mode didn't change (Ville)
	- Use new helpers to call mode_valid

 drivers/gpu/drm/drm_atomic_helper.c | 76 +++++++++++++++++++++++++++++++++++--
 1 file changed, 73 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 8be9719..5a3c458 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -32,6 +32,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <linux/dma-fence.h>
 
+#include "drm_crtc_helper_internal.h"
 #include "drm_crtc_internal.h"
 
 /**
@@ -452,6 +453,69 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
 	return 0;
 }
 
+static enum drm_mode_status mode_valid_path(struct drm_connector *connector,
+					    struct drm_encoder *encoder,
+					    struct drm_crtc *crtc,
+					    struct drm_display_mode *mode)
+{
+	enum drm_mode_status ret;
+
+	ret = drm_encoder_mode_valid(encoder, mode);
+	if (ret != MODE_OK) {
+		DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] mode_valid() failed\n",
+				encoder->base.id, encoder->name);
+		return ret;
+	}
+
+	ret = drm_bridge_mode_valid(encoder->bridge, mode);
+	if (ret != MODE_OK) {
+		DRM_DEBUG_ATOMIC("[BRIDGE] mode_valid() failed\n");
+		return ret;
+	}
+
+	ret = drm_crtc_mode_valid(crtc, mode);
+	if (ret != MODE_OK) {
+		DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode_valid() failed\n",
+				crtc->base.id, crtc->name);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int
+mode_valid(struct drm_atomic_state *state)
+{
+	struct drm_connector_state *conn_state;
+	struct drm_connector *connector;
+	int i;
+
+	for_each_new_connector_in_state(state, connector, conn_state, i) {
+		struct drm_encoder *encoder = conn_state->best_encoder;
+		struct drm_crtc *crtc = conn_state->crtc;
+		struct drm_crtc_state *crtc_state;
+		enum drm_mode_status mode_status;
+		struct drm_display_mode *mode;
+
+		if (!crtc || !encoder)
+			continue;
+
+		crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+		if (!crtc_state)
+			continue;
+		if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
+			continue;
+
+		mode = &crtc_state->mode;
+
+		mode_status = mode_valid_path(connector, encoder, crtc, mode);
+		if (mode_status != MODE_OK)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 /**
  * drm_atomic_helper_check_modeset - validate state object for modeset changes
  * @dev: DRM device
@@ -466,13 +530,15 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
  * 2. &drm_connector_helper_funcs.atomic_check to validate the connector state.
  * 3. If it's determined a modeset is needed then all connectors on the affected crtc
  *    crtc are added and &drm_connector_helper_funcs.atomic_check is run on them.
- * 4. &drm_bridge_funcs.mode_fixup is called on all encoder bridges.
- * 5. &drm_encoder_helper_funcs.atomic_check is called to validate any encoder state.
+ * 4. &drm_encoder_helper_funcs.mode_valid, &drm_bridge_funcs.mode_valid and
+ *    &drm_crtc_helper_funcs.mode_valid are called on the affected components.
+ * 5. &drm_bridge_funcs.mode_fixup is called on all encoder bridges.
+ * 6. &drm_encoder_helper_funcs.atomic_check is called to validate any encoder state.
  *    This function is only called when the encoder will be part of a configured crtc,
  *    it must not be used for implementing connector property validation.
  *    If this function is NULL, &drm_atomic_encoder_helper_funcs.mode_fixup is called
  *    instead.
- * 6. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with crtc constraints.
+ * 7. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with crtc constraints.
  *
  * &drm_crtc_state.mode_changed is set when the input mode is changed.
  * &drm_crtc_state.connectors_changed is set when a connector is added or
@@ -617,6 +683,10 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state,
 			return ret;
 	}
 
+	ret = mode_valid(state);
+	if (ret)
+		return ret;
+
 	return mode_fixup(state);
 }
 EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback
  2017-05-11  9:05 [PATCH v3 0/6] Introduce new mode validation callbacks Jose Abreu
                   ` (4 preceding siblings ...)
  2017-05-11  9:06 ` [PATCH v3 5/6] drm: Use mode_valid() in atomic modeset Jose Abreu
@ 2017-05-11  9:06 ` Jose Abreu
  2017-05-15  8:53     ` Daniel Vetter
  2017-05-15  8:54     ` Andrzej Hajda
  2017-05-12  7:32   ` Daniel Vetter
  6 siblings, 2 replies; 46+ messages in thread
From: Jose Abreu @ 2017-05-11  9:06 UTC (permalink / raw)
  To: dri-devel, linux-kernel
  Cc: Jose Abreu, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Andrzej Hajda, Archit Taneja

Now that we have a callback to check if crtc supports a given mode
we can use it in arcpgu so that we restrict the number of probbed
modes to the ones we can actually display.

This is specially useful because arcpgu crtc is responsible to set
a clock value in the commit() stage but unfortunatelly this clock
does not support all the needed ranges.

Also, remove the atomic_check() callback as mode_valid() callback
will be called before.

Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: Carlos Palminha <palminha@synopsys.com>
Cc: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Airlie <airlied@linux.ie>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/arc/arcpgu_crtc.c | 39 ++++++++++++++++++++++++---------------
 1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
index ad9a959..01cae0a 100644
--- a/drivers/gpu/drm/arc/arcpgu_crtc.c
+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
@@ -32,6 +32,18 @@
 	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
 };
 
+static bool arc_pgu_is_mode_valid(struct arcpgu_drm_private *arcpgu,
+				  const struct drm_display_mode *mode)
+{
+	long rate, clk_rate = mode->clock * 1000;
+
+	rate = clk_round_rate(arcpgu->clk, clk_rate);
+	if (rate != clk_rate)
+		return false;
+
+	return true;
+}
+
 static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
 {
 	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
@@ -64,6 +76,17 @@ static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
 	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 };
 
+enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc,
+					     const struct drm_display_mode *mode)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+
+	if (!arc_pgu_is_mode_valid(arcpgu, mode))
+		return MODE_NOCLOCK;
+
+	return MODE_OK;
+}
+
 static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
 	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
@@ -129,20 +152,6 @@ static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
 			      ~ARCPGU_CTRL_ENABLE_MASK);
 }
 
-static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
-				     struct drm_crtc_state *state)
-{
-	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
-	struct drm_display_mode *mode = &state->adjusted_mode;
-	long rate, clk_rate = mode->clock * 1000;
-
-	rate = clk_round_rate(arcpgu->clk, clk_rate);
-	if (rate != clk_rate)
-		return -EINVAL;
-
-	return 0;
-}
-
 static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
 				      struct drm_crtc_state *state)
 {
@@ -158,6 +167,7 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
 }
 
 static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
+	.mode_valid	= arc_pgu_crtc_mode_valid,
 	.mode_set	= drm_helper_crtc_mode_set,
 	.mode_set_base	= drm_helper_crtc_mode_set_base,
 	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
@@ -165,7 +175,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
 	.disable	= arc_pgu_crtc_disable,
 	.prepare	= arc_pgu_crtc_disable,
 	.commit		= arc_pgu_crtc_enable,
-	.atomic_check	= arc_pgu_crtc_atomic_check,
 	.atomic_begin	= arc_pgu_crtc_atomic_begin,
 };
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 1/6] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-11  9:05 ` [PATCH v3 1/6] drm: Add crtc/encoder/bridge->mode_valid() callbacks Jose Abreu
@ 2017-05-12  7:00     ` Daniel Vetter
  2017-05-12  7:31   ` [PATCH] " Daniel Vetter
  1 sibling, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-12  7:00 UTC (permalink / raw)
  To: Jose Abreu
  Cc: dri-devel, linux-kernel, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Andrzej Hajda, Archit Taneja

On Thu, May 11, 2017 at 10:05:57AM +0100, Jose Abreu wrote:
> This adds a new callback to crtc, encoder and bridge helper functions
> called mode_valid(). This callback shall be implemented if the
> corresponding component has some sort of restriction in the modes
> that can be displayed. A NULL callback implicates that the component
> can display all the modes.
> 
> We also change the documentation so that the new and old callbacks
> are correctly documented.
> 
> Only the callbacks were implemented to simplify review process,
> following patches will make use of them.
> 
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> ---
> 
> Changes v2->v3:
> 	- Try to document the callbacks a little bit better and
> 	review current documentation (Daniel)

Not quite what I had in mind, all the language about "Please be aware that
neither core nor helper filter modes" is still there. And that was added
to explain the difference between mode_valid and mode_fixup.

Since all the other patches look good I'll take  stab at a v3 myself.
-Daniel

> Changes v1->v2:
> 	- Change description of connector->mode_valid() (Daniel)
> 
>  include/drm/drm_bridge.h                 |  20 ++++++
>  include/drm/drm_modeset_helper_vtables.h | 110 +++++++++++++++++++++++--------
>  2 files changed, 103 insertions(+), 27 deletions(-)
> 
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index fdd82fc..00c6c36 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -59,6 +59,26 @@ struct drm_bridge_funcs {
>  	void (*detach)(struct drm_bridge *bridge);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * bridge. This should be implemented if the bridge has some sort of
> +	 * restriction in the modes it can display. For example, a given bridge
> +	 * may be responsible to set a clock value. If the clock can not
> +	 * produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This is called at mode probe and at atomic check phase.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc,
> +					   const struct drm_display_mode *mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
>  	 * This callback is used to validate and adjust a mode. The paramater
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index c01c328..b07b7cd 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -106,14 +106,37 @@ struct drm_crtc_helper_funcs {
>  	void (*commit)(struct drm_crtc *crtc);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * crtc. This should be implemented if the crtc has some sort of
> +	 * restriction in the modes it can display. For example, a given crtc
> +	 * may be responsible to set a clock value. If the clock can not
> +	 * produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This is called at mode probe and at atomic check phase.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
> +					   const struct drm_display_mode *mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
> -	 * This callback is used to validate a mode. The parameter mode is the
> -	 * display mode that userspace requested, adjusted_mode is the mode the
> -	 * encoders need to be fed with. Note that this is the inverse semantics
> -	 * of the meaning for the &drm_encoder and &drm_bridge_funcs.mode_fixup
> -	 * vfunc. If the CRTC cannot support the requested conversion from mode
> -	 * to adjusted_mode it should reject the modeset.
> +	 * This callback is used to do the validation of an adjusted mode in the
> +	 * crtc. The parameter mode is the display mode that userspace requested,
> +	 * adjusted_mode is the mode the encoders need to be fed with. Note that
> +	 * this is the inverse semantics of the meaning for the &drm_encoder and
> +	 * &drm_bridge_funcs.mode_fixup vfunc. If the CRTC cannot support the
> +	 * requested conversion from mode to adjusted_mode it should reject the
> +	 * modeset. Also note that initial validation of a mode supplied by
> +	 * userspace should be done in &drm_crtc_helper_funcs.mode_valid and not
> +	 * in this callback.
>  	 *
>  	 * This function is used by both legacy CRTC helpers and atomic helpers.
>  	 * With atomic helpers it is optional.
> @@ -135,17 +158,19 @@ struct drm_crtc_helper_funcs {
>  	 * Also beware that neither core nor helpers filter modes before
>  	 * passing them to the driver: While the list of modes that is
>  	 * advertised to userspace is filtered using the
> -	 * &drm_connector.mode_valid callback, neither the core nor the helpers
> -	 * do any filtering on modes passed in from userspace when setting a
> -	 * mode. It is therefore possible for userspace to pass in a mode that
> -	 * was previously filtered out using &drm_connector.mode_valid or add a
> -	 * custom mode that wasn't probed from EDID or similar to begin with.
> -	 * Even though this is an advanced feature and rarely used nowadays,
> -	 * some users rely on being able to specify modes manually so drivers
> -	 * must be prepared to deal with it. Specifically this means that all
> -	 * drivers need not only validate modes in &drm_connector.mode_valid but
> -	 * also in this or in the &drm_encoder_helper_funcs.mode_fixup callback
> -	 * to make sure invalid modes passed in from userspace are rejected.
> +	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
> +	 * the helpers do any filtering on modes passed in from userspace when
> +	 * setting a mode. It is therefore possible for userspace to pass in a
> +	 * mode that was previously filtered out using
> +	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
> +	 * wasn't probed from EDID or similar to begin with. Even though this
> +	 * is an advanced feature and rarely used nowadays, some users rely on
> +	 * being able to specify modes manually so drivers must be prepared to
> +	 * deal with it. Specifically this means that all drivers need not only
> +	 * validate modes in &drm_connector.mode_valid but also in this or in
> +	 * the &drm_crtc_helper_funcs.mode_valid,
> +	 * &drm_encoder_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid
> +	 * callbacks, where applicable.
>  	 *
>  	 * RETURNS:
>  	 *
> @@ -457,11 +482,31 @@ struct drm_encoder_helper_funcs {
>  	void (*dpms)(struct drm_encoder *encoder, int mode);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * encoder. This should be implemented if the encoder has some sort
> +	 * of restriction in the modes it can display. For example, a given
> +	 * encoder may be responsible to set a clock value. If the clock can
> +	 * not produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This is called at mode probe and at atomic check phase.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_encoder *crtc,
> +					   const struct drm_display_mode *mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
> -	 * This callback is used to validate and adjust a mode. The parameter
> -	 * mode is the display mode that should be fed to the next element in
> -	 * the display chain, either the final &drm_connector or a &drm_bridge.
> +	 * This callback is used to adjust a mode. The parameter mode is the
> +	 * display mode that should be fed to the next element in the display
> +	 * chain, either the final &drm_connector or a &drm_bridge.
>  	 * The parameter adjusted_mode is the input mode the encoder requires. It
>  	 * can be modified by this callback and does not need to match mode.
>  	 *
> @@ -484,19 +529,20 @@ struct drm_encoder_helper_funcs {
>  	 *
>  	 * Also beware that neither core nor helpers filter modes before
>  	 * passing them to the driver: While the list of modes that is
> -	 * advertised to userspace is filtered using the connector's
> +	 * advertised to userspace is filtered using the
>  	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
>  	 * the helpers do any filtering on modes passed in from userspace when
>  	 * setting a mode. It is therefore possible for userspace to pass in a
>  	 * mode that was previously filtered out using
>  	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
> -	 * wasn't probed from EDID or similar to begin with.  Even though this
> +	 * wasn't probed from EDID or similar to begin with. Even though this
>  	 * is an advanced feature and rarely used nowadays, some users rely on
>  	 * being able to specify modes manually so drivers must be prepared to
>  	 * deal with it. Specifically this means that all drivers need not only
>  	 * validate modes in &drm_connector.mode_valid but also in this or in
> -	 * the &drm_crtc_helper_funcs.mode_fixup callback to make sure
> -	 * invalid modes passed in from userspace are rejected.
> +	 * the &drm_crtc_helper_funcs.mode_valid,
> +	 * &drm_encoder_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid
> +	 * callbacks, where applicable.
>  	 *
>  	 * RETURNS:
>  	 *
> @@ -795,13 +841,23 @@ struct drm_connector_helper_funcs {
>  	 * (which is usually derived from the EDID data block from the sink).
>  	 * See e.g. drm_helper_probe_single_connector_modes().
>  	 *
> +	 * This callback is never called in atomic check phase so that userspace
> +	 * can override kernel sink checks in case of broken EDID with wrong
> +	 * limits from the sink. You can use the remaining mode_valid()
> +	 * callbacks to validate the mode against your video path.
> +	 *
>  	 * NOTE:
>  	 *
>  	 * This only filters the mode list supplied to userspace in the
> -	 * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and
> +	 * GETCONNECTOR IOCTL. Userspace is free to create modes of its own and
>  	 * ask the kernel to use them. It this case the atomic helpers or legacy
> -	 * CRTC helpers will not call this function. Drivers therefore must
> -	 * still fully validate any mode passed in in a modeset request.
> +	 * CRTC helpers will not call this function but the mode will be
> +	 * validated in atomic check phase using the mode_valid() callbacks
> +	 * (&drm_crtc_helper_funcs.mode_valid, &drm_encoder_helper_funcs.mode_valid
> +	 * and &drm_bridge_funcs.mode_valid).
> +	 * Drivers therefore must implement the mode_valid() callbacks if the
> +	 * video pipeline has some sort of restrictions in the modes that can
> +	 * be displayed.
>  	 *
>  	 * To avoid races with concurrent connector state updates, the helper
>  	 * libraries always call this with the &drm_mode_config.connection_mutex
> -- 
> 1.9.1
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 1/6] drm: Add crtc/encoder/bridge->mode_valid() callbacks
@ 2017-05-12  7:00     ` Daniel Vetter
  0 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-12  7:00 UTC (permalink / raw)
  To: Jose Abreu
  Cc: Daniel Vetter, Alexey Brodkin, linux-kernel, dri-devel, Carlos Palminha

On Thu, May 11, 2017 at 10:05:57AM +0100, Jose Abreu wrote:
> This adds a new callback to crtc, encoder and bridge helper functions
> called mode_valid(). This callback shall be implemented if the
> corresponding component has some sort of restriction in the modes
> that can be displayed. A NULL callback implicates that the component
> can display all the modes.
> 
> We also change the documentation so that the new and old callbacks
> are correctly documented.
> 
> Only the callbacks were implemented to simplify review process,
> following patches will make use of them.
> 
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> ---
> 
> Changes v2->v3:
> 	- Try to document the callbacks a little bit better and
> 	review current documentation (Daniel)

Not quite what I had in mind, all the language about "Please be aware that
neither core nor helper filter modes" is still there. And that was added
to explain the difference between mode_valid and mode_fixup.

Since all the other patches look good I'll take  stab at a v3 myself.
-Daniel

> Changes v1->v2:
> 	- Change description of connector->mode_valid() (Daniel)
> 
>  include/drm/drm_bridge.h                 |  20 ++++++
>  include/drm/drm_modeset_helper_vtables.h | 110 +++++++++++++++++++++++--------
>  2 files changed, 103 insertions(+), 27 deletions(-)
> 
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index fdd82fc..00c6c36 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -59,6 +59,26 @@ struct drm_bridge_funcs {
>  	void (*detach)(struct drm_bridge *bridge);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * bridge. This should be implemented if the bridge has some sort of
> +	 * restriction in the modes it can display. For example, a given bridge
> +	 * may be responsible to set a clock value. If the clock can not
> +	 * produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This is called at mode probe and at atomic check phase.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc,
> +					   const struct drm_display_mode *mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
>  	 * This callback is used to validate and adjust a mode. The paramater
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index c01c328..b07b7cd 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -106,14 +106,37 @@ struct drm_crtc_helper_funcs {
>  	void (*commit)(struct drm_crtc *crtc);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * crtc. This should be implemented if the crtc has some sort of
> +	 * restriction in the modes it can display. For example, a given crtc
> +	 * may be responsible to set a clock value. If the clock can not
> +	 * produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This is called at mode probe and at atomic check phase.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
> +					   const struct drm_display_mode *mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
> -	 * This callback is used to validate a mode. The parameter mode is the
> -	 * display mode that userspace requested, adjusted_mode is the mode the
> -	 * encoders need to be fed with. Note that this is the inverse semantics
> -	 * of the meaning for the &drm_encoder and &drm_bridge_funcs.mode_fixup
> -	 * vfunc. If the CRTC cannot support the requested conversion from mode
> -	 * to adjusted_mode it should reject the modeset.
> +	 * This callback is used to do the validation of an adjusted mode in the
> +	 * crtc. The parameter mode is the display mode that userspace requested,
> +	 * adjusted_mode is the mode the encoders need to be fed with. Note that
> +	 * this is the inverse semantics of the meaning for the &drm_encoder and
> +	 * &drm_bridge_funcs.mode_fixup vfunc. If the CRTC cannot support the
> +	 * requested conversion from mode to adjusted_mode it should reject the
> +	 * modeset. Also note that initial validation of a mode supplied by
> +	 * userspace should be done in &drm_crtc_helper_funcs.mode_valid and not
> +	 * in this callback.
>  	 *
>  	 * This function is used by both legacy CRTC helpers and atomic helpers.
>  	 * With atomic helpers it is optional.
> @@ -135,17 +158,19 @@ struct drm_crtc_helper_funcs {
>  	 * Also beware that neither core nor helpers filter modes before
>  	 * passing them to the driver: While the list of modes that is
>  	 * advertised to userspace is filtered using the
> -	 * &drm_connector.mode_valid callback, neither the core nor the helpers
> -	 * do any filtering on modes passed in from userspace when setting a
> -	 * mode. It is therefore possible for userspace to pass in a mode that
> -	 * was previously filtered out using &drm_connector.mode_valid or add a
> -	 * custom mode that wasn't probed from EDID or similar to begin with.
> -	 * Even though this is an advanced feature and rarely used nowadays,
> -	 * some users rely on being able to specify modes manually so drivers
> -	 * must be prepared to deal with it. Specifically this means that all
> -	 * drivers need not only validate modes in &drm_connector.mode_valid but
> -	 * also in this or in the &drm_encoder_helper_funcs.mode_fixup callback
> -	 * to make sure invalid modes passed in from userspace are rejected.
> +	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
> +	 * the helpers do any filtering on modes passed in from userspace when
> +	 * setting a mode. It is therefore possible for userspace to pass in a
> +	 * mode that was previously filtered out using
> +	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
> +	 * wasn't probed from EDID or similar to begin with. Even though this
> +	 * is an advanced feature and rarely used nowadays, some users rely on
> +	 * being able to specify modes manually so drivers must be prepared to
> +	 * deal with it. Specifically this means that all drivers need not only
> +	 * validate modes in &drm_connector.mode_valid but also in this or in
> +	 * the &drm_crtc_helper_funcs.mode_valid,
> +	 * &drm_encoder_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid
> +	 * callbacks, where applicable.
>  	 *
>  	 * RETURNS:
>  	 *
> @@ -457,11 +482,31 @@ struct drm_encoder_helper_funcs {
>  	void (*dpms)(struct drm_encoder *encoder, int mode);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * encoder. This should be implemented if the encoder has some sort
> +	 * of restriction in the modes it can display. For example, a given
> +	 * encoder may be responsible to set a clock value. If the clock can
> +	 * not produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This is called at mode probe and at atomic check phase.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_encoder *crtc,
> +					   const struct drm_display_mode *mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
> -	 * This callback is used to validate and adjust a mode. The parameter
> -	 * mode is the display mode that should be fed to the next element in
> -	 * the display chain, either the final &drm_connector or a &drm_bridge.
> +	 * This callback is used to adjust a mode. The parameter mode is the
> +	 * display mode that should be fed to the next element in the display
> +	 * chain, either the final &drm_connector or a &drm_bridge.
>  	 * The parameter adjusted_mode is the input mode the encoder requires. It
>  	 * can be modified by this callback and does not need to match mode.
>  	 *
> @@ -484,19 +529,20 @@ struct drm_encoder_helper_funcs {
>  	 *
>  	 * Also beware that neither core nor helpers filter modes before
>  	 * passing them to the driver: While the list of modes that is
> -	 * advertised to userspace is filtered using the connector's
> +	 * advertised to userspace is filtered using the
>  	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
>  	 * the helpers do any filtering on modes passed in from userspace when
>  	 * setting a mode. It is therefore possible for userspace to pass in a
>  	 * mode that was previously filtered out using
>  	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
> -	 * wasn't probed from EDID or similar to begin with.  Even though this
> +	 * wasn't probed from EDID or similar to begin with. Even though this
>  	 * is an advanced feature and rarely used nowadays, some users rely on
>  	 * being able to specify modes manually so drivers must be prepared to
>  	 * deal with it. Specifically this means that all drivers need not only
>  	 * validate modes in &drm_connector.mode_valid but also in this or in
> -	 * the &drm_crtc_helper_funcs.mode_fixup callback to make sure
> -	 * invalid modes passed in from userspace are rejected.
> +	 * the &drm_crtc_helper_funcs.mode_valid,
> +	 * &drm_encoder_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid
> +	 * callbacks, where applicable.
>  	 *
>  	 * RETURNS:
>  	 *
> @@ -795,13 +841,23 @@ struct drm_connector_helper_funcs {
>  	 * (which is usually derived from the EDID data block from the sink).
>  	 * See e.g. drm_helper_probe_single_connector_modes().
>  	 *
> +	 * This callback is never called in atomic check phase so that userspace
> +	 * can override kernel sink checks in case of broken EDID with wrong
> +	 * limits from the sink. You can use the remaining mode_valid()
> +	 * callbacks to validate the mode against your video path.
> +	 *
>  	 * NOTE:
>  	 *
>  	 * This only filters the mode list supplied to userspace in the
> -	 * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and
> +	 * GETCONNECTOR IOCTL. Userspace is free to create modes of its own and
>  	 * ask the kernel to use them. It this case the atomic helpers or legacy
> -	 * CRTC helpers will not call this function. Drivers therefore must
> -	 * still fully validate any mode passed in in a modeset request.
> +	 * CRTC helpers will not call this function but the mode will be
> +	 * validated in atomic check phase using the mode_valid() callbacks
> +	 * (&drm_crtc_helper_funcs.mode_valid, &drm_encoder_helper_funcs.mode_valid
> +	 * and &drm_bridge_funcs.mode_valid).
> +	 * Drivers therefore must implement the mode_valid() callbacks if the
> +	 * video pipeline has some sort of restrictions in the modes that can
> +	 * be displayed.
>  	 *
>  	 * To avoid races with concurrent connector state updates, the helper
>  	 * libraries always call this with the &drm_mode_config.connection_mutex
> -- 
> 1.9.1
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-11  9:05 ` [PATCH v3 1/6] drm: Add crtc/encoder/bridge->mode_valid() callbacks Jose Abreu
  2017-05-12  7:00     ` Daniel Vetter
@ 2017-05-12  7:31   ` Daniel Vetter
  2017-05-12 11:29     ` Laurent Pinchart
                       ` (4 more replies)
  1 sibling, 5 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-12  7:31 UTC (permalink / raw)
  To: DRI Development
  Cc: Jose Abreu, Daniel Vetter, Alexey Brodkin, Jose Abreu, Carlos Palminha

From: Jose Abreu <Jose.Abreu@synopsys.com>

This adds a new callback to crtc, encoder and bridge helper functions
called mode_valid(). This callback shall be implemented if the
corresponding component has some sort of restriction in the modes
that can be displayed. A NULL callback implicates that the component
can display all the modes.

We also change the documentation so that the new and old callbacks
are correctly documented.

Only the callbacks were implemented to simplify review process,
following patches will make use of them.

Changes in v2 from Daniel:
- Update the warning about how modes aren't filtered in atomic_check -
  the heleprs help out a lot more now.
- Consistenly roll out that warning, crtc/encoder's atomic_check
  missed it.
- Sprinkle more links all over the place, so it's easier to see where
  this stuff is used and how the differen hooks are related.
- Note that ->mode_valid is optional everywhere.
- Explain why the connector's mode_valid is special and does _not_ get
  called in atomic_check.

Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: Jose Abreu <joabreu@synopsys.com>
Cc: Carlos Palminha <palminha@synopsys.com>
Cc: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Airlie <airlied@linux.ie>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2)
---
 include/drm/drm_bridge.h                 |  31 +++++++++
 include/drm/drm_modeset_helper_vtables.h | 116 ++++++++++++++++++++++---------
 2 files changed, 114 insertions(+), 33 deletions(-)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index fdd82fcbf168..f694de756ecf 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -59,6 +59,31 @@ struct drm_bridge_funcs {
 	void (*detach)(struct drm_bridge *bridge);
 
 	/**
+	 * @mode_valid:
+	 *
+	 * This callback is used to check if a specific mode is valid in this
+	 * bridge. This should be implemented if the bridge has some sort of
+	 * restriction in the modes it can display. For example, a given bridge
+	 * may be responsible to set a clock value. If the clock can not
+	 * produce all the values for the available modes then this callback
+	 * can be used to restrict the number of modes to only the ones that
+	 * can be displayed.
+	 *
+	 * This hook is used by the probe helpers to filter the mode list in
+	 * drm_helper_probe_single_connector_modes(), and it is used by the
+	 * atomic helpers to validate modes supplied by userspace in
+	 * drm_atomic_helper_check_modeset().
+	 *
+	 * This function is optional.
+	 *
+	 * RETURNS:
+	 *
+	 * drm_mode_status Enum
+	 */
+	enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc,
+					   const struct drm_display_mode *mode);
+
+	/**
 	 * @mode_fixup:
 	 *
 	 * This callback is used to validate and adjust a mode. The paramater
@@ -82,6 +107,12 @@ struct drm_bridge_funcs {
 	 * NOT touch any persistent state (hardware or software) or data
 	 * structures except the passed in @state parameter.
 	 *
+	 * Also beware that userspace can request its own custom modes, neither
+	 * core nor helpers filter modes to the list of probe modes reported by
+	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
+	 * that modes are filtered consistently put any bridge constraints and
+	 * limits checks into @mode_valid.
+	 *
 	 * RETURNS:
 	 *
 	 * True if an acceptable configuration is possible, false if the modeset
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index c01c328f6cc8..91d071ff1232 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -106,6 +106,31 @@ struct drm_crtc_helper_funcs {
 	void (*commit)(struct drm_crtc *crtc);
 
 	/**
+	 * @mode_valid:
+	 *
+	 * This callback is used to check if a specific mode is valid in this
+	 * crtc. This should be implemented if the crtc has some sort of
+	 * restriction in the modes it can display. For example, a given crtc
+	 * may be responsible to set a clock value. If the clock can not
+	 * produce all the values for the available modes then this callback
+	 * can be used to restrict the number of modes to only the ones that
+	 * can be displayed.
+	 *
+	 * This hook is used by the probe helpers to filter the mode list in
+	 * drm_helper_probe_single_connector_modes(), and it is used by the
+	 * atomic helpers to validate modes supplied by userspace in
+	 * drm_atomic_helper_check_modeset().
+	 *
+	 * This function is optional.
+	 *
+	 * RETURNS:
+	 *
+	 * drm_mode_status Enum
+	 */
+	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
+					   const struct drm_display_mode *mode);
+
+	/**
 	 * @mode_fixup:
 	 *
 	 * This callback is used to validate a mode. The parameter mode is the
@@ -132,20 +157,11 @@ struct drm_crtc_helper_funcs {
 	 * Atomic drivers which need to inspect and adjust more state should
 	 * instead use the @atomic_check callback.
 	 *
-	 * Also beware that neither core nor helpers filter modes before
-	 * passing them to the driver: While the list of modes that is
-	 * advertised to userspace is filtered using the
-	 * &drm_connector.mode_valid callback, neither the core nor the helpers
-	 * do any filtering on modes passed in from userspace when setting a
-	 * mode. It is therefore possible for userspace to pass in a mode that
-	 * was previously filtered out using &drm_connector.mode_valid or add a
-	 * custom mode that wasn't probed from EDID or similar to begin with.
-	 * Even though this is an advanced feature and rarely used nowadays,
-	 * some users rely on being able to specify modes manually so drivers
-	 * must be prepared to deal with it. Specifically this means that all
-	 * drivers need not only validate modes in &drm_connector.mode_valid but
-	 * also in this or in the &drm_encoder_helper_funcs.mode_fixup callback
-	 * to make sure invalid modes passed in from userspace are rejected.
+	 * Also beware that userspace can request its own custom modes, neither
+	 * core nor helpers filter modes to the list of probe modes reported by
+	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
+	 * that modes are filtered consistently put any CRTC constraints and
+	 * limits checks into @mode_valid.
 	 *
 	 * RETURNS:
 	 *
@@ -341,6 +357,12 @@ struct drm_crtc_helper_funcs {
 	 * state objects passed-in or assembled in the overall &drm_atomic_state
 	 * update tracking structure.
 	 *
+	 * Also beware that userspace can request its own custom modes, neither
+	 * core nor helpers filter modes to the list of probe modes reported by
+	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
+	 * that modes are filtered consistently put any CRTC constraints and
+	 * limits checks into @mode_valid.
+	 *
 	 * RETURNS:
 	 *
 	 * 0 on success, -EINVAL if the state or the transition can't be
@@ -457,6 +479,31 @@ struct drm_encoder_helper_funcs {
 	void (*dpms)(struct drm_encoder *encoder, int mode);
 
 	/**
+	 * @mode_valid:
+	 *
+	 * This callback is used to check if a specific mode is valid in this
+	 * encoder. This should be implemented if the encoder has some sort
+	 * of restriction in the modes it can display. For example, a given
+	 * encoder may be responsible to set a clock value. If the clock can
+	 * not produce all the values for the available modes then this callback
+	 * can be used to restrict the number of modes to only the ones that
+	 * can be displayed.
+	 *
+	 * This hook is used by the probe helpers to filter the mode list in
+	 * drm_helper_probe_single_connector_modes(), and it is used by the
+	 * atomic helpers to validate modes supplied by userspace in
+	 * drm_atomic_helper_check_modeset().
+	 *
+	 * This function is optional.
+	 *
+	 * RETURNS:
+	 *
+	 * drm_mode_status Enum
+	 */
+	enum drm_mode_status (*mode_valid)(struct drm_encoder *crtc,
+					   const struct drm_display_mode *mode);
+
+	/**
 	 * @mode_fixup:
 	 *
 	 * This callback is used to validate and adjust a mode. The parameter
@@ -482,21 +529,11 @@ struct drm_encoder_helper_funcs {
 	 * Atomic drivers which need to inspect and adjust more state should
 	 * instead use the @atomic_check callback.
 	 *
-	 * Also beware that neither core nor helpers filter modes before
-	 * passing them to the driver: While the list of modes that is
-	 * advertised to userspace is filtered using the connector's
-	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
-	 * the helpers do any filtering on modes passed in from userspace when
-	 * setting a mode. It is therefore possible for userspace to pass in a
-	 * mode that was previously filtered out using
-	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
-	 * wasn't probed from EDID or similar to begin with.  Even though this
-	 * is an advanced feature and rarely used nowadays, some users rely on
-	 * being able to specify modes manually so drivers must be prepared to
-	 * deal with it. Specifically this means that all drivers need not only
-	 * validate modes in &drm_connector.mode_valid but also in this or in
-	 * the &drm_crtc_helper_funcs.mode_fixup callback to make sure
-	 * invalid modes passed in from userspace are rejected.
+	 * Also beware that userspace can request its own custom modes, neither
+	 * core nor helpers filter modes to the list of probe modes reported by
+	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
+	 * that modes are filtered consistently put any encoder constraints and
+	 * limits checks into @mode_valid.
 	 *
 	 * RETURNS:
 	 *
@@ -686,6 +723,12 @@ struct drm_encoder_helper_funcs {
 	 * state objects passed-in or assembled in the overall &drm_atomic_state
 	 * update tracking structure.
 	 *
+	 * Also beware that userspace can request its own custom modes, neither
+	 * core nor helpers filter modes to the list of probe modes reported by
+	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
+	 * that modes are filtered consistently put any encoder constraints and
+	 * limits checks into @mode_valid.
+	 *
 	 * RETURNS:
 	 *
 	 * 0 on success, -EINVAL if the state or the transition can't be
@@ -795,13 +838,20 @@ struct drm_connector_helper_funcs {
 	 * (which is usually derived from the EDID data block from the sink).
 	 * See e.g. drm_helper_probe_single_connector_modes().
 	 *
+	 * This function is optional.
+	 *
 	 * NOTE:
 	 *
 	 * This only filters the mode list supplied to userspace in the
-	 * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and
-	 * ask the kernel to use them. It this case the atomic helpers or legacy
-	 * CRTC helpers will not call this function. Drivers therefore must
-	 * still fully validate any mode passed in in a modeset request.
+	 * GETCONNECTOR IOCTL. Compared to &drm_encoder_helper_funcs.mode_valid,
+	 * &drm_crtc_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid,
+	 * which are also called by the atomic helpers from
+	 * drm_atomic_helper_check_modeset(). This allows userspace to force and
+	 * ignore sink constraint (like the pixel clock limits in the screen's
+	 * EDID), which is useful for e.g. testing, or working around a broken
+	 * EDID. Any source hardware constraint (which always need to be
+	 * enforced) therefore should be checked in one of the above callbacks,
+	 * and not this one here.
 	 *
 	 * To avoid races with concurrent connector state updates, the helper
 	 * libraries always call this with the &drm_mode_config.connection_mutex
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 0/6] Introduce new mode validation callbacks
  2017-05-11  9:05 [PATCH v3 0/6] Introduce new mode validation callbacks Jose Abreu
@ 2017-05-12  7:32   ` Daniel Vetter
  2017-05-11  9:05 ` [PATCH v3 2/6] drm: Add drm_{crtc/encoder/connector}_mode_valid() Jose Abreu
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-12  7:32 UTC (permalink / raw)
  To: Jose Abreu
  Cc: dri-devel, linux-kernel, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Andrzej Hajda, Archit Taneja

On Thu, May 11, 2017 at 10:05:56AM +0100, Jose Abreu wrote:
> This series is a follow up from the discussion at [1]. We start by
> introducing crtc->mode_valid(), encoder->mode_valid() and
> bridge->mode_valid() callbacks which will be used in followup
> patches and also by cleaning the documentation a little bit.
> 
> We proceed by introducing new helpers to call this new callbacks
> at 2/6.
> 
> At 3/6 a helper function is introduced that calls all mode_valid()
> from a set of bridges.
> 
> Next, at 4/6 we modify the connector probe helper so that only modes
> which are supported by a given bridge+encoder+crtc combination are
> probbed.
> 
> At 5/6 we call all the mode_valid() callbacks for a given pipeline,
> except the connector->mode_valid one, so that the mode is validated.
> This is done before calling mode_fixup().
> 
> Finally, at 6/6 we use the new crtc->mode_valid() callback in arcpgu
> and remove the atomic_check() callback.
> 
> [1] https://patchwork.kernel.org/patch/9702233/
> 
> Jose Abreu (6):
>   drm: Add crtc/encoder/bridge->mode_valid() callbacks
>   drm: Add drm_{crtc/encoder/connector}_mode_valid()
>   drm: Introduce drm_bridge_mode_valid()
>   drm: Use new mode_valid() helpers in connector probe helper
>   drm: Use mode_valid() in atomic modeset
>   drm: arc: Use crtc->mode_valid() callback
> 
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>

Commented with an entire patch on patch 1, patches 2-5 are all

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

But I think some more acks/r-bs would be really good, since this is quite
a bit change in the helper infrastructure. But otherwise ready for merging
imo. Can you pls also review my proposal for patch 1?

Thanks, Daniel

> 
>  drivers/gpu/drm/arc/arcpgu_crtc.c          |  39 ++++++----
>  drivers/gpu/drm/drm_atomic_helper.c        |  76 +++++++++++++++++++-
>  drivers/gpu/drm/drm_bridge.c               |  33 +++++++++
>  drivers/gpu/drm/drm_crtc_helper_internal.h |  13 ++++
>  drivers/gpu/drm/drm_probe_helper.c         | 103 ++++++++++++++++++++++++++-
>  include/drm/drm_bridge.h                   |  22 ++++++
>  include/drm/drm_modeset_helper_vtables.h   | 110 ++++++++++++++++++++++-------
>  7 files changed, 348 insertions(+), 48 deletions(-)
> 
> -- 
> 1.9.1
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 0/6] Introduce new mode validation callbacks
@ 2017-05-12  7:32   ` Daniel Vetter
  0 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-12  7:32 UTC (permalink / raw)
  To: Jose Abreu
  Cc: Daniel Vetter, Alexey Brodkin, linux-kernel, dri-devel, Carlos Palminha

On Thu, May 11, 2017 at 10:05:56AM +0100, Jose Abreu wrote:
> This series is a follow up from the discussion at [1]. We start by
> introducing crtc->mode_valid(), encoder->mode_valid() and
> bridge->mode_valid() callbacks which will be used in followup
> patches and also by cleaning the documentation a little bit.
> 
> We proceed by introducing new helpers to call this new callbacks
> at 2/6.
> 
> At 3/6 a helper function is introduced that calls all mode_valid()
> from a set of bridges.
> 
> Next, at 4/6 we modify the connector probe helper so that only modes
> which are supported by a given bridge+encoder+crtc combination are
> probbed.
> 
> At 5/6 we call all the mode_valid() callbacks for a given pipeline,
> except the connector->mode_valid one, so that the mode is validated.
> This is done before calling mode_fixup().
> 
> Finally, at 6/6 we use the new crtc->mode_valid() callback in arcpgu
> and remove the atomic_check() callback.
> 
> [1] https://patchwork.kernel.org/patch/9702233/
> 
> Jose Abreu (6):
>   drm: Add crtc/encoder/bridge->mode_valid() callbacks
>   drm: Add drm_{crtc/encoder/connector}_mode_valid()
>   drm: Introduce drm_bridge_mode_valid()
>   drm: Use new mode_valid() helpers in connector probe helper
>   drm: Use mode_valid() in atomic modeset
>   drm: arc: Use crtc->mode_valid() callback
> 
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>

Commented with an entire patch on patch 1, patches 2-5 are all

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

But I think some more acks/r-bs would be really good, since this is quite
a bit change in the helper infrastructure. But otherwise ready for merging
imo. Can you pls also review my proposal for patch 1?

Thanks, Daniel

> 
>  drivers/gpu/drm/arc/arcpgu_crtc.c          |  39 ++++++----
>  drivers/gpu/drm/drm_atomic_helper.c        |  76 +++++++++++++++++++-
>  drivers/gpu/drm/drm_bridge.c               |  33 +++++++++
>  drivers/gpu/drm/drm_crtc_helper_internal.h |  13 ++++
>  drivers/gpu/drm/drm_probe_helper.c         | 103 ++++++++++++++++++++++++++-
>  include/drm/drm_bridge.h                   |  22 ++++++
>  include/drm/drm_modeset_helper_vtables.h   | 110 ++++++++++++++++++++++-------
>  7 files changed, 348 insertions(+), 48 deletions(-)
> 
> -- 
> 1.9.1
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-12  7:31   ` [PATCH] " Daniel Vetter
@ 2017-05-12 11:29     ` Laurent Pinchart
  2017-05-15  6:50       ` Daniel Vetter
  2017-05-12 12:37     ` Andrzej Hajda
                       ` (3 subsequent siblings)
  4 siblings, 1 reply; 46+ messages in thread
From: Laurent Pinchart @ 2017-05-12 11:29 UTC (permalink / raw)
  To: dri-devel
  Cc: Jose Abreu, Daniel Vetter, Jose Abreu, Alexey Brodkin, Carlos Palminha

Hi Daniel,

On Friday 12 May 2017 09:31:00 Daniel Vetter wrote:
> From: Jose Abreu <Jose.Abreu@synopsys.com>
> 
> This adds a new callback to crtc, encoder and bridge helper functions
> called mode_valid(). This callback shall be implemented if the
> corresponding component has some sort of restriction in the modes
> that can be displayed. A NULL callback implicates that the component
> can display all the modes.
> 
> We also change the documentation so that the new and old callbacks
> are correctly documented.
> 
> Only the callbacks were implemented to simplify review process,
> following patches will make use of them.
> 
> Changes in v2 from Daniel:
> - Update the warning about how modes aren't filtered in atomic_check -
>   the heleprs help out a lot more now.
> - Consistenly roll out that warning, crtc/encoder's atomic_check
>   missed it.
> - Sprinkle more links all over the place, so it's easier to see where
>   this stuff is used and how the differen hooks are related.
> - Note that ->mode_valid is optional everywhere.
> - Explain why the connector's mode_valid is special and does _not_ get
>   called in atomic_check.

As commented on v2 (but after you sent this patch), I think we need to 
document clearly how mode_valid and mode_fixup should interact. It's very 
confusing for driver authors at the moment.

> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2)
> ---
>  include/drm/drm_bridge.h                 |  31 +++++++++
>  include/drm/drm_modeset_helper_vtables.h | 116
> ++++++++++++++++++++++--------- 2 files changed, 114 insertions(+), 33
> deletions(-)
> 
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index fdd82fcbf168..f694de756ecf 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -59,6 +59,31 @@ struct drm_bridge_funcs {
>  	void (*detach)(struct drm_bridge *bridge);
> 
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * bridge. This should be implemented if the bridge has some sort of
> +	 * restriction in the modes it can display. For example, a given 
bridge
> +	 * may be responsible to set a clock value. If the clock can not
> +	 * produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This hook is used by the probe helpers to filter the mode list in
> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> +	 * atomic helpers to validate modes supplied by userspace in
> +	 * drm_atomic_helper_check_modeset().
> +	 *
> +	 * This function is optional.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc,
> +					   const struct drm_display_mode 
*mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
>  	 * This callback is used to validate and adjust a mode. The paramater
> @@ -82,6 +107,12 @@ struct drm_bridge_funcs {
>  	 * NOT touch any persistent state (hardware or software) or data
>  	 * structures except the passed in @state parameter.
>  	 *
> +	 * Also beware that userspace can request its own custom modes, 
neither
> +	 * core nor helpers filter modes to the list of probe modes reported 
by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To 
ensure
> +	 * that modes are filtered consistently put any bridge constraints and
> +	 * limits checks into @mode_valid.
> +	 *
>  	 * RETURNS:
>  	 *
>  	 * True if an acceptable configuration is possible, false if the 
modeset
> diff --git a/include/drm/drm_modeset_helper_vtables.h
> b/include/drm/drm_modeset_helper_vtables.h index c01c328f6cc8..91d071ff1232
> 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -106,6 +106,31 @@ struct drm_crtc_helper_funcs {
>  	void (*commit)(struct drm_crtc *crtc);
> 
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * crtc. This should be implemented if the crtc has some sort of
> +	 * restriction in the modes it can display. For example, a given crtc
> +	 * may be responsible to set a clock value. If the clock can not
> +	 * produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This hook is used by the probe helpers to filter the mode list in
> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> +	 * atomic helpers to validate modes supplied by userspace in
> +	 * drm_atomic_helper_check_modeset().
> +	 *
> +	 * This function is optional.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
> +					   const struct drm_display_mode 
*mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
>  	 * This callback is used to validate a mode. The parameter mode is the
> @@ -132,20 +157,11 @@ struct drm_crtc_helper_funcs {
>  	 * Atomic drivers which need to inspect and adjust more state should
>  	 * instead use the @atomic_check callback.
>  	 *
> -	 * Also beware that neither core nor helpers filter modes before
> -	 * passing them to the driver: While the list of modes that is
> -	 * advertised to userspace is filtered using the
> -	 * &drm_connector.mode_valid callback, neither the core nor the 
helpers
> -	 * do any filtering on modes passed in from userspace when setting a
> -	 * mode. It is therefore possible for userspace to pass in a mode that
> -	 * was previously filtered out using &drm_connector.mode_valid or add 
a
> -	 * custom mode that wasn't probed from EDID or similar to begin with.
> -	 * Even though this is an advanced feature and rarely used nowadays,
> -	 * some users rely on being able to specify modes manually so drivers
> -	 * must be prepared to deal with it. Specifically this means that all
> -	 * drivers need not only validate modes in &drm_connector.mode_valid 
but
> -	 * also in this or in the &drm_encoder_helper_funcs.mode_fixup 
callback
> -	 * to make sure invalid modes passed in from userspace are rejected.
> +	 * Also beware that userspace can request its own custom modes, 
neither
> +	 * core nor helpers filter modes to the list of probe modes reported 
by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To 
ensure
> +	 * that modes are filtered consistently put any CRTC constraints and
> +	 * limits checks into @mode_valid.
>  	 *
>  	 * RETURNS:
>  	 *
> @@ -341,6 +357,12 @@ struct drm_crtc_helper_funcs {
>  	 * state objects passed-in or assembled in the overall 
&drm_atomic_state
>  	 * update tracking structure.
>  	 *
> +	 * Also beware that userspace can request its own custom modes, 
neither
> +	 * core nor helpers filter modes to the list of probe modes reported 
by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To 
ensure
> +	 * that modes are filtered consistently put any CRTC constraints and
> +	 * limits checks into @mode_valid.
> +	 *
>  	 * RETURNS:
>  	 *
>  	 * 0 on success, -EINVAL if the state or the transition can't be
> @@ -457,6 +479,31 @@ struct drm_encoder_helper_funcs {
>  	void (*dpms)(struct drm_encoder *encoder, int mode);
> 
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * encoder. This should be implemented if the encoder has some sort
> +	 * of restriction in the modes it can display. For example, a given
> +	 * encoder may be responsible to set a clock value. If the clock can
> +	 * not produce all the values for the available modes then this 
callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This hook is used by the probe helpers to filter the mode list in
> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> +	 * atomic helpers to validate modes supplied by userspace in
> +	 * drm_atomic_helper_check_modeset().
> +	 *
> +	 * This function is optional.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_encoder *crtc,
> +					   const struct drm_display_mode 
*mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
>  	 * This callback is used to validate and adjust a mode. The parameter
> @@ -482,21 +529,11 @@ struct drm_encoder_helper_funcs {
>  	 * Atomic drivers which need to inspect and adjust more state should
>  	 * instead use the @atomic_check callback.
>  	 *
> -	 * Also beware that neither core nor helpers filter modes before
> -	 * passing them to the driver: While the list of modes that is
> -	 * advertised to userspace is filtered using the connector's
> -	 * &drm_connector_helper_funcs.mode_valid callback, neither the core 
nor
> -	 * the helpers do any filtering on modes passed in from userspace when
> -	 * setting a mode. It is therefore possible for userspace to pass in a
> -	 * mode that was previously filtered out using
> -	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
> -	 * wasn't probed from EDID or similar to begin with.  Even though this
> -	 * is an advanced feature and rarely used nowadays, some users rely on
> -	 * being able to specify modes manually so drivers must be prepared to
> -	 * deal with it. Specifically this means that all drivers need not 
only
> -	 * validate modes in &drm_connector.mode_valid but also in this or in
> -	 * the &drm_crtc_helper_funcs.mode_fixup callback to make sure
> -	 * invalid modes passed in from userspace are rejected.
> +	 * Also beware that userspace can request its own custom modes, 
neither
> +	 * core nor helpers filter modes to the list of probe modes reported 
by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To 
ensure
> +	 * that modes are filtered consistently put any encoder constraints 
and
> +	 * limits checks into @mode_valid.
>  	 *
>  	 * RETURNS:
>  	 *
> @@ -686,6 +723,12 @@ struct drm_encoder_helper_funcs {
>  	 * state objects passed-in or assembled in the overall 
&drm_atomic_state
>  	 * update tracking structure.
>  	 *
> +	 * Also beware that userspace can request its own custom modes, 
neither
> +	 * core nor helpers filter modes to the list of probe modes reported 
by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To 
ensure
> +	 * that modes are filtered consistently put any encoder constraints 
and
> +	 * limits checks into @mode_valid.
> +	 *
>  	 * RETURNS:
>  	 *
>  	 * 0 on success, -EINVAL if the state or the transition can't be
> @@ -795,13 +838,20 @@ struct drm_connector_helper_funcs {
>  	 * (which is usually derived from the EDID data block from the sink).
>  	 * See e.g. drm_helper_probe_single_connector_modes().
>  	 *
> +	 * This function is optional.
> +	 *
>  	 * NOTE:
>  	 *
>  	 * This only filters the mode list supplied to userspace in the
> -	 * GETCONNECOTR IOCTL. Userspace is free to create modes of its own 
and
> -	 * ask the kernel to use them. It this case the atomic helpers or 
legacy
> -	 * CRTC helpers will not call this function. Drivers therefore must
> -	 * still fully validate any mode passed in in a modeset request.
> +	 * GETCONNECTOR IOCTL. Compared to 
&drm_encoder_helper_funcs.mode_valid,
> +	 * &drm_crtc_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid,
> +	 * which are also called by the atomic helpers from
> +	 * drm_atomic_helper_check_modeset(). This allows userspace to force 
and
> +	 * ignore sink constraint (like the pixel clock limits in the screen's
> +	 * EDID), which is useful for e.g. testing, or working around a broken
> +	 * EDID. Any source hardware constraint (which always need to be
> +	 * enforced) therefore should be checked in one of the above 
callbacks,
> +	 * and not this one here.
>  	 *
>  	 * To avoid races with concurrent connector state updates, the helper
>  	 * libraries always call this with the 
&drm_mode_config.connection_mutex

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-12  7:31   ` [PATCH] " Daniel Vetter
  2017-05-12 11:29     ` Laurent Pinchart
@ 2017-05-12 12:37     ` Andrzej Hajda
  2017-05-15  6:56       ` Daniel Vetter
  2017-05-12 15:59     ` Jose Abreu
                       ` (2 subsequent siblings)
  4 siblings, 1 reply; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-12 12:37 UTC (permalink / raw)
  To: Daniel Vetter, DRI Development
  Cc: Jose Abreu, Alexey Brodkin, Jose Abreu, Carlos Palminha

On 12.05.2017 09:31, Daniel Vetter wrote:
> From: Jose Abreu <Jose.Abreu@synopsys.com>
>
> This adds a new callback to crtc, encoder and bridge helper functions
> called mode_valid(). This callback shall be implemented if the
> corresponding component has some sort of restriction in the modes
> that can be displayed. A NULL callback implicates that the component
> can display all the modes.
>
> We also change the documentation so that the new and old callbacks
> are correctly documented.
>
> Only the callbacks were implemented to simplify review process,
> following patches will make use of them.
>
> Changes in v2 from Daniel:
> - Update the warning about how modes aren't filtered in atomic_check -
>   the heleprs help out a lot more now.
> - Consistenly roll out that warning, crtc/encoder's atomic_check
>   missed it.
> - Sprinkle more links all over the place, so it's easier to see where
>   this stuff is used and how the differen hooks are related.
> - Note that ->mode_valid is optional everywhere.
> - Explain why the connector's mode_valid is special and does _not_ get
>   called in atomic_check.
>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2)
> ---
>  include/drm/drm_bridge.h                 |  31 +++++++++
>  include/drm/drm_modeset_helper_vtables.h | 116 ++++++++++++++++++++++---------
>  2 files changed, 114 insertions(+), 33 deletions(-)
>
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index fdd82fcbf168..f694de756ecf 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -59,6 +59,31 @@ struct drm_bridge_funcs {
>  	void (*detach)(struct drm_bridge *bridge);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * bridge. This should be implemented if the bridge has some sort of
> +	 * restriction in the modes it can display. For example, a given bridge
> +	 * may be responsible to set a clock value. If the clock can not
> +	 * produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This hook is used by the probe helpers to filter the mode list in
> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> +	 * atomic helpers to validate modes supplied by userspace in
> +	 * drm_atomic_helper_check_modeset().
> +	 *
> +	 * This function is optional.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc,
> +					   const struct drm_display_mode *mode);

I have put my concerns here but it touches all mode_valid callbacks.
As the callback can be called in mode probe and atomic check it could
only inspect common set of properties for both contexts, for example
crtc cannot check to which encoder it is connected, am I right?
Maybe it would be good to emphasize it here, as it is emphasized in case
of mode_fixup callbacks.

> +
> +	/**
>  	 * @mode_fixup:
>  	 *
>  	 * This callback is used to validate and adjust a mode. The paramater
> @@ -82,6 +107,12 @@ struct drm_bridge_funcs {
>  	 * NOT touch any persistent state (hardware or software) or data
>  	 * structures except the passed in @state parameter.
>  	 *
> +	 * Also beware that userspace can request its own custom modes, neither
> +	 * core nor helpers filter modes to the list of probe modes reported by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> +	 * that modes are filtered consistently put any bridge constraints and
> +	 * limits checks into @mode_valid.
> +	 *
>  	 * RETURNS:
>  	 *
>  	 * True if an acceptable configuration is possible, false if the modeset
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index c01c328f6cc8..91d071ff1232 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -106,6 +106,31 @@ struct drm_crtc_helper_funcs {
>  	void (*commit)(struct drm_crtc *crtc);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * crtc. This should be implemented if the crtc has some sort of
> +	 * restriction in the modes it can display. For example, a given crtc
> +	 * may be responsible to set a clock value. If the clock can not
> +	 * produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This hook is used by the probe helpers to filter the mode list in
> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> +	 * atomic helpers to validate modes supplied by userspace in
> +	 * drm_atomic_helper_check_modeset().
> +	 *
> +	 * This function is optional.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
> +					   const struct drm_display_mode *mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
>  	 * This callback is used to validate a mode. The parameter mode is the
> @@ -132,20 +157,11 @@ struct drm_crtc_helper_funcs {
>  	 * Atomic drivers which need to inspect and adjust more state should
>  	 * instead use the @atomic_check callback.
>  	 *
> -	 * Also beware that neither core nor helpers filter modes before
> -	 * passing them to the driver: While the list of modes that is
> -	 * advertised to userspace is filtered using the
> -	 * &drm_connector.mode_valid callback, neither the core nor the helpers
> -	 * do any filtering on modes passed in from userspace when setting a
> -	 * mode. It is therefore possible for userspace to pass in a mode that
> -	 * was previously filtered out using &drm_connector.mode_valid or add a
> -	 * custom mode that wasn't probed from EDID or similar to begin with.
> -	 * Even though this is an advanced feature and rarely used nowadays,
> -	 * some users rely on being able to specify modes manually so drivers
> -	 * must be prepared to deal with it. Specifically this means that all
> -	 * drivers need not only validate modes in &drm_connector.mode_valid but
> -	 * also in this or in the &drm_encoder_helper_funcs.mode_fixup callback
> -	 * to make sure invalid modes passed in from userspace are rejected.
> +	 * Also beware that userspace can request its own custom modes, neither
> +	 * core nor helpers filter modes to the list of probe modes reported by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> +	 * that modes are filtered consistently put any CRTC constraints and
> +	 * limits checks into @mode_valid.

Why we do not make mode_fixup obsolete for atomic drivers as
atomic_check can do the same and is more powerful, this way we could
avoid the overlapped functionality of mode_valid and mode_fixup.


>  	 *
>  	 * RETURNS:
>  	 *
> @@ -341,6 +357,12 @@ struct drm_crtc_helper_funcs {
>  	 * state objects passed-in or assembled in the overall &drm_atomic_state
>  	 * update tracking structure.
>  	 *
> +	 * Also beware that userspace can request its own custom modes, neither
> +	 * core nor helpers filter modes to the list of probe modes reported by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> +	 * that modes are filtered consistently put any CRTC constraints and
> +	 * limits checks into @mode_valid.
> +	 *
>  	 * RETURNS:
>  	 *
>  	 * 0 on success, -EINVAL if the state or the transition can't be
> @@ -457,6 +479,31 @@ struct drm_encoder_helper_funcs {
>  	void (*dpms)(struct drm_encoder *encoder, int mode);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * encoder. This should be implemented if the encoder has some sort
> +	 * of restriction in the modes it can display. For example, a given
> +	 * encoder may be responsible to set a clock value. If the clock can
> +	 * not produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This hook is used by the probe helpers to filter the mode list in
> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> +	 * atomic helpers to validate modes supplied by userspace in
> +	 * drm_atomic_helper_check_modeset().
> +	 *
> +	 * This function is optional.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_encoder *crtc,
> +					   const struct drm_display_mode *mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
>  	 * This callback is used to validate and adjust a mode. The parameter
> @@ -482,21 +529,11 @@ struct drm_encoder_helper_funcs {
>  	 * Atomic drivers which need to inspect and adjust more state should
>  	 * instead use the @atomic_check callback.
>  	 *
> -	 * Also beware that neither core nor helpers filter modes before
> -	 * passing them to the driver: While the list of modes that is
> -	 * advertised to userspace is filtered using the connector's
> -	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
> -	 * the helpers do any filtering on modes passed in from userspace when
> -	 * setting a mode. It is therefore possible for userspace to pass in a
> -	 * mode that was previously filtered out using
> -	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
> -	 * wasn't probed from EDID or similar to begin with.  Even though this
> -	 * is an advanced feature and rarely used nowadays, some users rely on
> -	 * being able to specify modes manually so drivers must be prepared to
> -	 * deal with it. Specifically this means that all drivers need not only
> -	 * validate modes in &drm_connector.mode_valid but also in this or in
> -	 * the &drm_crtc_helper_funcs.mode_fixup callback to make sure
> -	 * invalid modes passed in from userspace are rejected.
> +	 * Also beware that userspace can request its own custom modes, neither
> +	 * core nor helpers filter modes to the list of probe modes reported by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> +	 * that modes are filtered consistently put any encoder constraints and
> +	 * limits checks into @mode_valid.
>  	 *
>  	 * RETURNS:
>  	 *
> @@ -686,6 +723,12 @@ struct drm_encoder_helper_funcs {
>  	 * state objects passed-in or assembled in the overall &drm_atomic_state
>  	 * update tracking structure.
>  	 *
> +	 * Also beware that userspace can request its own custom modes, neither
> +	 * core nor helpers filter modes to the list of probe modes reported by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> +	 * that modes are filtered consistently put any encoder constraints and
> +	 * limits checks into @mode_valid.
> +	 *
>  	 * RETURNS:
>  	 *
>  	 * 0 on success, -EINVAL if the state or the transition can't be
> @@ -795,13 +838,20 @@ struct drm_connector_helper_funcs {
>  	 * (which is usually derived from the EDID data block from the sink).
>  	 * See e.g. drm_helper_probe_single_connector_modes().
>  	 *
> +	 * This function is optional.
> +	 *
>  	 * NOTE:
>  	 *
>  	 * This only filters the mode list supplied to userspace in the
> -	 * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and
> -	 * ask the kernel to use them. It this case the atomic helpers or legacy
> -	 * CRTC helpers will not call this function. Drivers therefore must
> -	 * still fully validate any mode passed in in a modeset request.
> +	 * GETCONNECTOR IOCTL. Compared to &drm_encoder_helper_funcs.mode_valid,
> +	 * &drm_crtc_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid,
> +	 * which are also called by the atomic helpers from
> +	 * drm_atomic_helper_check_modeset(). This allows userspace to force and
> +	 * ignore sink constraint (like the pixel clock limits in the screen's
> +	 * EDID), which is useful for e.g. testing, or working around a broken
> +	 * EDID. Any source hardware constraint (which always need to be
> +	 * enforced) therefore should be checked in one of the above callbacks,
> +	 * and not this one here.

The callback has the same name but different semantic, little bit weird.
But do we really need connector::mode_valid then? I mean: are there
connectors not bound to bridge/encoder which have their own constraints?
If there are no such connectors, we can remove this callback.
If they are rare, maybe just adding loop to connector::get_modes would
be enough.

Regards
Andrzej

>  	 *
>  	 * To avoid races with concurrent connector state updates, the helper
>  	 * libraries always call this with the &drm_mode_config.connection_mutex


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 0/6] Introduce new mode validation callbacks
  2017-05-12  7:32   ` Daniel Vetter
@ 2017-05-12 13:37     ` Andrzej Hajda
  -1 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-12 13:37 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel, Carlos Palminha,
	Alexey Brodkin, Ville Syrjälä,
	Dave Airlie, Archit Taneja

On 12.05.2017 09:32, Daniel Vetter wrote:
> On Thu, May 11, 2017 at 10:05:56AM +0100, Jose Abreu wrote:
>> This series is a follow up from the discussion at [1]. We start by
>> introducing crtc->mode_valid(), encoder->mode_valid() and
>> bridge->mode_valid() callbacks which will be used in followup
>> patches and also by cleaning the documentation a little bit.
>>
>> We proceed by introducing new helpers to call this new callbacks
>> at 2/6.
>>
>> At 3/6 a helper function is introduced that calls all mode_valid()
>> from a set of bridges.
>>
>> Next, at 4/6 we modify the connector probe helper so that only modes
>> which are supported by a given bridge+encoder+crtc combination are
>> probbed.
>>
>> At 5/6 we call all the mode_valid() callbacks for a given pipeline,
>> except the connector->mode_valid one, so that the mode is validated.
>> This is done before calling mode_fixup().
>>
>> Finally, at 6/6 we use the new crtc->mode_valid() callback in arcpgu
>> and remove the atomic_check() callback.
>>
>> [1] https://patchwork.kernel.org/patch/9702233/
>>
>> Jose Abreu (6):
>>   drm: Add crtc/encoder/bridge->mode_valid() callbacks
>>   drm: Add drm_{crtc/encoder/connector}_mode_valid()
>>   drm: Introduce drm_bridge_mode_valid()
>>   drm: Use new mode_valid() helpers in connector probe helper
>>   drm: Use mode_valid() in atomic modeset
>>   drm: arc: Use crtc->mode_valid() callback
>>
>> Cc: Carlos Palminha <palminha@synopsys.com>
>> Cc: Alexey Brodkin <abrodkin@synopsys.com>
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
>> Cc: Dave Airlie <airlied@linux.ie>
>> Cc: Andrzej Hajda <a.hajda@samsung.com>
>> Cc: Archit Taneja <architt@codeaurora.org>
> Commented with an entire patch on patch 1, patches 2-5 are all
>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>
> But I think some more acks/r-bs would be really good, since this is quite
> a bit change in the helper infrastructure. But otherwise ready for merging
> imo. Can you pls also review my proposal for patch 1?
>
> Thanks, Daniel

As the patchset improves many things, I would like to point here that
there are still issues with mode probing at least in case of panels.
Panels in general does not provide discrete list of supported modes, but
they provide list of supported mode ranges (named display_timings), at
the moment this is only addressed in drm_panel_funcs::get_timings, but
drm core does not use it at all.
Currently most of the panel drivers advertises only fixed list of
arbitrary chosen modes, and if bridge/connector/encoder/crtc does not
support it pipeline does not work, even if slightly different
configuration could work. Of course there are workarounds but maybe it
would be good to replace drm_connector::modes with drm_connector::timings.
This way set of valid timings of the whole pipeline will be intersection
of sets of valid timings of every component of the pipeline - quite
straightforward and simple construct.

As this is just an idea which came to me during patchset review, it is
not backed by any code, but maybe it can be interesting for quick
brainstorm.

Regards
Andrzej


>
>>  drivers/gpu/drm/arc/arcpgu_crtc.c          |  39 ++++++----
>>  drivers/gpu/drm/drm_atomic_helper.c        |  76 +++++++++++++++++++-
>>  drivers/gpu/drm/drm_bridge.c               |  33 +++++++++
>>  drivers/gpu/drm/drm_crtc_helper_internal.h |  13 ++++
>>  drivers/gpu/drm/drm_probe_helper.c         | 103 ++++++++++++++++++++++++++-
>>  include/drm/drm_bridge.h                   |  22 ++++++
>>  include/drm/drm_modeset_helper_vtables.h   | 110 ++++++++++++++++++++++-------
>>  7 files changed, 348 insertions(+), 48 deletions(-)
>>
>> -- 
>> 1.9.1
>>
>>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 0/6] Introduce new mode validation callbacks
@ 2017-05-12 13:37     ` Andrzej Hajda
  0 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-12 13:37 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel, Carlos Palminha,
	Alexey Brodkin, Ville Syrjälä,
	Dave Airlie, Archit Taneja

On 12.05.2017 09:32, Daniel Vetter wrote:
> On Thu, May 11, 2017 at 10:05:56AM +0100, Jose Abreu wrote:
>> This series is a follow up from the discussion at [1]. We start by
>> introducing crtc->mode_valid(), encoder->mode_valid() and
>> bridge->mode_valid() callbacks which will be used in followup
>> patches and also by cleaning the documentation a little bit.
>>
>> We proceed by introducing new helpers to call this new callbacks
>> at 2/6.
>>
>> At 3/6 a helper function is introduced that calls all mode_valid()
>> from a set of bridges.
>>
>> Next, at 4/6 we modify the connector probe helper so that only modes
>> which are supported by a given bridge+encoder+crtc combination are
>> probbed.
>>
>> At 5/6 we call all the mode_valid() callbacks for a given pipeline,
>> except the connector->mode_valid one, so that the mode is validated.
>> This is done before calling mode_fixup().
>>
>> Finally, at 6/6 we use the new crtc->mode_valid() callback in arcpgu
>> and remove the atomic_check() callback.
>>
>> [1] https://patchwork.kernel.org/patch/9702233/
>>
>> Jose Abreu (6):
>>   drm: Add crtc/encoder/bridge->mode_valid() callbacks
>>   drm: Add drm_{crtc/encoder/connector}_mode_valid()
>>   drm: Introduce drm_bridge_mode_valid()
>>   drm: Use new mode_valid() helpers in connector probe helper
>>   drm: Use mode_valid() in atomic modeset
>>   drm: arc: Use crtc->mode_valid() callback
>>
>> Cc: Carlos Palminha <palminha@synopsys.com>
>> Cc: Alexey Brodkin <abrodkin@synopsys.com>
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
>> Cc: Dave Airlie <airlied@linux.ie>
>> Cc: Andrzej Hajda <a.hajda@samsung.com>
>> Cc: Archit Taneja <architt@codeaurora.org>
> Commented with an entire patch on patch 1, patches 2-5 are all
>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>
> But I think some more acks/r-bs would be really good, since this is quite
> a bit change in the helper infrastructure. But otherwise ready for merging
> imo. Can you pls also review my proposal for patch 1?
>
> Thanks, Daniel

As the patchset improves many things, I would like to point here that
there are still issues with mode probing at least in case of panels.
Panels in general does not provide discrete list of supported modes, but
they provide list of supported mode ranges (named display_timings), at
the moment this is only addressed in drm_panel_funcs::get_timings, but
drm core does not use it at all.
Currently most of the panel drivers advertises only fixed list of
arbitrary chosen modes, and if bridge/connector/encoder/crtc does not
support it pipeline does not work, even if slightly different
configuration could work. Of course there are workarounds but maybe it
would be good to replace drm_connector::modes with drm_connector::timings.
This way set of valid timings of the whole pipeline will be intersection
of sets of valid timings of every component of the pipeline - quite
straightforward and simple construct.

As this is just an idea which came to me during patchset review, it is
not backed by any code, but maybe it can be interesting for quick
brainstorm.

Regards
Andrzej


>
>>  drivers/gpu/drm/arc/arcpgu_crtc.c          |  39 ++++++----
>>  drivers/gpu/drm/drm_atomic_helper.c        |  76 +++++++++++++++++++-
>>  drivers/gpu/drm/drm_bridge.c               |  33 +++++++++
>>  drivers/gpu/drm/drm_crtc_helper_internal.h |  13 ++++
>>  drivers/gpu/drm/drm_probe_helper.c         | 103 ++++++++++++++++++++++++++-
>>  include/drm/drm_bridge.h                   |  22 ++++++
>>  include/drm/drm_modeset_helper_vtables.h   | 110 ++++++++++++++++++++++-------
>>  7 files changed, 348 insertions(+), 48 deletions(-)
>>
>> -- 
>> 1.9.1
>>
>>

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-12  7:31   ` [PATCH] " Daniel Vetter
  2017-05-12 11:29     ` Laurent Pinchart
  2017-05-12 12:37     ` Andrzej Hajda
@ 2017-05-12 15:59     ` Jose Abreu
  2017-05-15  9:11     ` [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better Daniel Vetter
  2017-05-15  9:33     ` [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks Daniel Vetter
  4 siblings, 0 replies; 46+ messages in thread
From: Jose Abreu @ 2017-05-12 15:59 UTC (permalink / raw)
  To: Daniel Vetter, DRI Development
  Cc: Jose Abreu, Alexey Brodkin, Carlos Palminha

Hi Daniel,


On 12-05-2017 08:31, Daniel Vetter wrote:
> From: Jose Abreu <Jose.Abreu@synopsys.com>
>
> This adds a new callback to crtc, encoder and bridge helper functions
> called mode_valid(). This callback shall be implemented if the
> corresponding component has some sort of restriction in the modes
> that can be displayed. A NULL callback implicates that the component
> can display all the modes.
>
> We also change the documentation so that the new and old callbacks
> are correctly documented.
>
> Only the callbacks were implemented to simplify review process,
> following patches will make use of them.
>
> Changes in v2 from Daniel:
> - Update the warning about how modes aren't filtered in atomic_check -
>   the heleprs help out a lot more now.
> - Consistenly roll out that warning, crtc/encoder's atomic_check
>   missed it.
> - Sprinkle more links all over the place, so it's easier to see where
>   this stuff is used and how the differen hooks are related.
> - Note that ->mode_valid is optional everywhere.
> - Explain why the connector's mode_valid is special and does _not_ get
>   called in atomic_check.
>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2)

Thanks! Looks fine by me.

Reviewed-by: Jose Abreu <joabreu@synopsys.com>

Best regards,
Jose Miguel Abreu

> ---
>  include/drm/drm_bridge.h                 |  31 +++++++++
>  include/drm/drm_modeset_helper_vtables.h | 116 ++++++++++++++++++++++---------
>  2 files changed, 114 insertions(+), 33 deletions(-)
>
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index fdd82fcbf168..f694de756ecf 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -59,6 +59,31 @@ struct drm_bridge_funcs {
>  	void (*detach)(struct drm_bridge *bridge);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * bridge. This should be implemented if the bridge has some sort of
> +	 * restriction in the modes it can display. For example, a given bridge
> +	 * may be responsible to set a clock value. If the clock can not
> +	 * produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This hook is used by the probe helpers to filter the mode list in
> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> +	 * atomic helpers to validate modes supplied by userspace in
> +	 * drm_atomic_helper_check_modeset().
> +	 *
> +	 * This function is optional.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc,
> +					   const struct drm_display_mode *mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
>  	 * This callback is used to validate and adjust a mode. The paramater
> @@ -82,6 +107,12 @@ struct drm_bridge_funcs {
>  	 * NOT touch any persistent state (hardware or software) or data
>  	 * structures except the passed in @state parameter.
>  	 *
> +	 * Also beware that userspace can request its own custom modes, neither
> +	 * core nor helpers filter modes to the list of probe modes reported by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> +	 * that modes are filtered consistently put any bridge constraints and
> +	 * limits checks into @mode_valid.
> +	 *
>  	 * RETURNS:
>  	 *
>  	 * True if an acceptable configuration is possible, false if the modeset
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index c01c328f6cc8..91d071ff1232 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -106,6 +106,31 @@ struct drm_crtc_helper_funcs {
>  	void (*commit)(struct drm_crtc *crtc);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * crtc. This should be implemented if the crtc has some sort of
> +	 * restriction in the modes it can display. For example, a given crtc
> +	 * may be responsible to set a clock value. If the clock can not
> +	 * produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This hook is used by the probe helpers to filter the mode list in
> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> +	 * atomic helpers to validate modes supplied by userspace in
> +	 * drm_atomic_helper_check_modeset().
> +	 *
> +	 * This function is optional.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
> +					   const struct drm_display_mode *mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
>  	 * This callback is used to validate a mode. The parameter mode is the
> @@ -132,20 +157,11 @@ struct drm_crtc_helper_funcs {
>  	 * Atomic drivers which need to inspect and adjust more state should
>  	 * instead use the @atomic_check callback.
>  	 *
> -	 * Also beware that neither core nor helpers filter modes before
> -	 * passing them to the driver: While the list of modes that is
> -	 * advertised to userspace is filtered using the
> -	 * &drm_connector.mode_valid callback, neither the core nor the helpers
> -	 * do any filtering on modes passed in from userspace when setting a
> -	 * mode. It is therefore possible for userspace to pass in a mode that
> -	 * was previously filtered out using &drm_connector.mode_valid or add a
> -	 * custom mode that wasn't probed from EDID or similar to begin with.
> -	 * Even though this is an advanced feature and rarely used nowadays,
> -	 * some users rely on being able to specify modes manually so drivers
> -	 * must be prepared to deal with it. Specifically this means that all
> -	 * drivers need not only validate modes in &drm_connector.mode_valid but
> -	 * also in this or in the &drm_encoder_helper_funcs.mode_fixup callback
> -	 * to make sure invalid modes passed in from userspace are rejected.
> +	 * Also beware that userspace can request its own custom modes, neither
> +	 * core nor helpers filter modes to the list of probe modes reported by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> +	 * that modes are filtered consistently put any CRTC constraints and
> +	 * limits checks into @mode_valid.
>  	 *
>  	 * RETURNS:
>  	 *
> @@ -341,6 +357,12 @@ struct drm_crtc_helper_funcs {
>  	 * state objects passed-in or assembled in the overall &drm_atomic_state
>  	 * update tracking structure.
>  	 *
> +	 * Also beware that userspace can request its own custom modes, neither
> +	 * core nor helpers filter modes to the list of probe modes reported by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> +	 * that modes are filtered consistently put any CRTC constraints and
> +	 * limits checks into @mode_valid.
> +	 *
>  	 * RETURNS:
>  	 *
>  	 * 0 on success, -EINVAL if the state or the transition can't be
> @@ -457,6 +479,31 @@ struct drm_encoder_helper_funcs {
>  	void (*dpms)(struct drm_encoder *encoder, int mode);
>  
>  	/**
> +	 * @mode_valid:
> +	 *
> +	 * This callback is used to check if a specific mode is valid in this
> +	 * encoder. This should be implemented if the encoder has some sort
> +	 * of restriction in the modes it can display. For example, a given
> +	 * encoder may be responsible to set a clock value. If the clock can
> +	 * not produce all the values for the available modes then this callback
> +	 * can be used to restrict the number of modes to only the ones that
> +	 * can be displayed.
> +	 *
> +	 * This hook is used by the probe helpers to filter the mode list in
> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> +	 * atomic helpers to validate modes supplied by userspace in
> +	 * drm_atomic_helper_check_modeset().
> +	 *
> +	 * This function is optional.
> +	 *
> +	 * RETURNS:
> +	 *
> +	 * drm_mode_status Enum
> +	 */
> +	enum drm_mode_status (*mode_valid)(struct drm_encoder *crtc,
> +					   const struct drm_display_mode *mode);
> +
> +	/**
>  	 * @mode_fixup:
>  	 *
>  	 * This callback is used to validate and adjust a mode. The parameter
> @@ -482,21 +529,11 @@ struct drm_encoder_helper_funcs {
>  	 * Atomic drivers which need to inspect and adjust more state should
>  	 * instead use the @atomic_check callback.
>  	 *
> -	 * Also beware that neither core nor helpers filter modes before
> -	 * passing them to the driver: While the list of modes that is
> -	 * advertised to userspace is filtered using the connector's
> -	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
> -	 * the helpers do any filtering on modes passed in from userspace when
> -	 * setting a mode. It is therefore possible for userspace to pass in a
> -	 * mode that was previously filtered out using
> -	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
> -	 * wasn't probed from EDID or similar to begin with.  Even though this
> -	 * is an advanced feature and rarely used nowadays, some users rely on
> -	 * being able to specify modes manually so drivers must be prepared to
> -	 * deal with it. Specifically this means that all drivers need not only
> -	 * validate modes in &drm_connector.mode_valid but also in this or in
> -	 * the &drm_crtc_helper_funcs.mode_fixup callback to make sure
> -	 * invalid modes passed in from userspace are rejected.
> +	 * Also beware that userspace can request its own custom modes, neither
> +	 * core nor helpers filter modes to the list of probe modes reported by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> +	 * that modes are filtered consistently put any encoder constraints and
> +	 * limits checks into @mode_valid.
>  	 *
>  	 * RETURNS:
>  	 *
> @@ -686,6 +723,12 @@ struct drm_encoder_helper_funcs {
>  	 * state objects passed-in or assembled in the overall &drm_atomic_state
>  	 * update tracking structure.
>  	 *
> +	 * Also beware that userspace can request its own custom modes, neither
> +	 * core nor helpers filter modes to the list of probe modes reported by
> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> +	 * that modes are filtered consistently put any encoder constraints and
> +	 * limits checks into @mode_valid.
> +	 *
>  	 * RETURNS:
>  	 *
>  	 * 0 on success, -EINVAL if the state or the transition can't be
> @@ -795,13 +838,20 @@ struct drm_connector_helper_funcs {
>  	 * (which is usually derived from the EDID data block from the sink).
>  	 * See e.g. drm_helper_probe_single_connector_modes().
>  	 *
> +	 * This function is optional.
> +	 *
>  	 * NOTE:
>  	 *
>  	 * This only filters the mode list supplied to userspace in the
> -	 * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and
> -	 * ask the kernel to use them. It this case the atomic helpers or legacy
> -	 * CRTC helpers will not call this function. Drivers therefore must
> -	 * still fully validate any mode passed in in a modeset request.
> +	 * GETCONNECTOR IOCTL. Compared to &drm_encoder_helper_funcs.mode_valid,
> +	 * &drm_crtc_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid,
> +	 * which are also called by the atomic helpers from
> +	 * drm_atomic_helper_check_modeset(). This allows userspace to force and
> +	 * ignore sink constraint (like the pixel clock limits in the screen's
> +	 * EDID), which is useful for e.g. testing, or working around a broken
> +	 * EDID. Any source hardware constraint (which always need to be
> +	 * enforced) therefore should be checked in one of the above callbacks,
> +	 * and not this one here.
>  	 *
>  	 * To avoid races with concurrent connector state updates, the helper
>  	 * libraries always call this with the &drm_mode_config.connection_mutex

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-12 11:29     ` Laurent Pinchart
@ 2017-05-15  6:50       ` Daniel Vetter
  0 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15  6:50 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Jose Abreu, Daniel Vetter, Alexey Brodkin, dri-devel, Jose Abreu,
	Carlos Palminha

On Fri, May 12, 2017 at 02:29:30PM +0300, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Friday 12 May 2017 09:31:00 Daniel Vetter wrote:
> > From: Jose Abreu <Jose.Abreu@synopsys.com>
> > 
> > This adds a new callback to crtc, encoder and bridge helper functions
> > called mode_valid(). This callback shall be implemented if the
> > corresponding component has some sort of restriction in the modes
> > that can be displayed. A NULL callback implicates that the component
> > can display all the modes.
> > 
> > We also change the documentation so that the new and old callbacks
> > are correctly documented.
> > 
> > Only the callbacks were implemented to simplify review process,
> > following patches will make use of them.
> > 
> > Changes in v2 from Daniel:
> > - Update the warning about how modes aren't filtered in atomic_check -
> >   the heleprs help out a lot more now.
> > - Consistenly roll out that warning, crtc/encoder's atomic_check
> >   missed it.
> > - Sprinkle more links all over the place, so it's easier to see where
> >   this stuff is used and how the differen hooks are related.
> > - Note that ->mode_valid is optional everywhere.
> > - Explain why the connector's mode_valid is special and does _not_ get
> >   called in atomic_check.
> 
> As commented on v2 (but after you sent this patch), I think we need to 
> document clearly how mode_valid and mode_fixup should interact. It's very 
> confusing for driver authors at the moment.

I tried to do that here, is it not enough? Note that mode_fixup is kinda
deprecated, in favour of atomic_check. So the equivalence is not as
clear-cut as you seem to think.
-Daniel

> 
> > Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> > Cc: Jose Abreu <joabreu@synopsys.com>
> > Cc: Carlos Palminha <palminha@synopsys.com>
> > Cc: Alexey Brodkin <abrodkin@synopsys.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Dave Airlie <airlied@linux.ie>
> > Cc: Andrzej Hajda <a.hajda@samsung.com>
> > Cc: Archit Taneja <architt@codeaurora.org>
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2)
> > ---
> >  include/drm/drm_bridge.h                 |  31 +++++++++
> >  include/drm/drm_modeset_helper_vtables.h | 116
> > ++++++++++++++++++++++--------- 2 files changed, 114 insertions(+), 33
> > deletions(-)
> > 
> > diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> > index fdd82fcbf168..f694de756ecf 100644
> > --- a/include/drm/drm_bridge.h
> > +++ b/include/drm/drm_bridge.h
> > @@ -59,6 +59,31 @@ struct drm_bridge_funcs {
> >  	void (*detach)(struct drm_bridge *bridge);
> > 
> >  	/**
> > +	 * @mode_valid:
> > +	 *
> > +	 * This callback is used to check if a specific mode is valid in this
> > +	 * bridge. This should be implemented if the bridge has some sort of
> > +	 * restriction in the modes it can display. For example, a given 
> bridge
> > +	 * may be responsible to set a clock value. If the clock can not
> > +	 * produce all the values for the available modes then this callback
> > +	 * can be used to restrict the number of modes to only the ones that
> > +	 * can be displayed.
> > +	 *
> > +	 * This hook is used by the probe helpers to filter the mode list in
> > +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> > +	 * atomic helpers to validate modes supplied by userspace in
> > +	 * drm_atomic_helper_check_modeset().
> > +	 *
> > +	 * This function is optional.
> > +	 *
> > +	 * RETURNS:
> > +	 *
> > +	 * drm_mode_status Enum
> > +	 */
> > +	enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc,
> > +					   const struct drm_display_mode 
> *mode);
> > +
> > +	/**
> >  	 * @mode_fixup:
> >  	 *
> >  	 * This callback is used to validate and adjust a mode. The paramater
> > @@ -82,6 +107,12 @@ struct drm_bridge_funcs {
> >  	 * NOT touch any persistent state (hardware or software) or data
> >  	 * structures except the passed in @state parameter.
> >  	 *
> > +	 * Also beware that userspace can request its own custom modes, 
> neither
> > +	 * core nor helpers filter modes to the list of probe modes reported 
> by
> > +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To 
> ensure
> > +	 * that modes are filtered consistently put any bridge constraints and
> > +	 * limits checks into @mode_valid.
> > +	 *
> >  	 * RETURNS:
> >  	 *
> >  	 * True if an acceptable configuration is possible, false if the 
> modeset
> > diff --git a/include/drm/drm_modeset_helper_vtables.h
> > b/include/drm/drm_modeset_helper_vtables.h index c01c328f6cc8..91d071ff1232
> > 100644
> > --- a/include/drm/drm_modeset_helper_vtables.h
> > +++ b/include/drm/drm_modeset_helper_vtables.h
> > @@ -106,6 +106,31 @@ struct drm_crtc_helper_funcs {
> >  	void (*commit)(struct drm_crtc *crtc);
> > 
> >  	/**
> > +	 * @mode_valid:
> > +	 *
> > +	 * This callback is used to check if a specific mode is valid in this
> > +	 * crtc. This should be implemented if the crtc has some sort of
> > +	 * restriction in the modes it can display. For example, a given crtc
> > +	 * may be responsible to set a clock value. If the clock can not
> > +	 * produce all the values for the available modes then this callback
> > +	 * can be used to restrict the number of modes to only the ones that
> > +	 * can be displayed.
> > +	 *
> > +	 * This hook is used by the probe helpers to filter the mode list in
> > +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> > +	 * atomic helpers to validate modes supplied by userspace in
> > +	 * drm_atomic_helper_check_modeset().
> > +	 *
> > +	 * This function is optional.
> > +	 *
> > +	 * RETURNS:
> > +	 *
> > +	 * drm_mode_status Enum
> > +	 */
> > +	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
> > +					   const struct drm_display_mode 
> *mode);
> > +
> > +	/**
> >  	 * @mode_fixup:
> >  	 *
> >  	 * This callback is used to validate a mode. The parameter mode is the
> > @@ -132,20 +157,11 @@ struct drm_crtc_helper_funcs {
> >  	 * Atomic drivers which need to inspect and adjust more state should
> >  	 * instead use the @atomic_check callback.
> >  	 *
> > -	 * Also beware that neither core nor helpers filter modes before
> > -	 * passing them to the driver: While the list of modes that is
> > -	 * advertised to userspace is filtered using the
> > -	 * &drm_connector.mode_valid callback, neither the core nor the 
> helpers
> > -	 * do any filtering on modes passed in from userspace when setting a
> > -	 * mode. It is therefore possible for userspace to pass in a mode that
> > -	 * was previously filtered out using &drm_connector.mode_valid or add 
> a
> > -	 * custom mode that wasn't probed from EDID or similar to begin with.
> > -	 * Even though this is an advanced feature and rarely used nowadays,
> > -	 * some users rely on being able to specify modes manually so drivers
> > -	 * must be prepared to deal with it. Specifically this means that all
> > -	 * drivers need not only validate modes in &drm_connector.mode_valid 
> but
> > -	 * also in this or in the &drm_encoder_helper_funcs.mode_fixup 
> callback
> > -	 * to make sure invalid modes passed in from userspace are rejected.
> > +	 * Also beware that userspace can request its own custom modes, 
> neither
> > +	 * core nor helpers filter modes to the list of probe modes reported 
> by
> > +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To 
> ensure
> > +	 * that modes are filtered consistently put any CRTC constraints and
> > +	 * limits checks into @mode_valid.
> >  	 *
> >  	 * RETURNS:
> >  	 *
> > @@ -341,6 +357,12 @@ struct drm_crtc_helper_funcs {
> >  	 * state objects passed-in or assembled in the overall 
> &drm_atomic_state
> >  	 * update tracking structure.
> >  	 *
> > +	 * Also beware that userspace can request its own custom modes, 
> neither
> > +	 * core nor helpers filter modes to the list of probe modes reported 
> by
> > +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To 
> ensure
> > +	 * that modes are filtered consistently put any CRTC constraints and
> > +	 * limits checks into @mode_valid.
> > +	 *
> >  	 * RETURNS:
> >  	 *
> >  	 * 0 on success, -EINVAL if the state or the transition can't be
> > @@ -457,6 +479,31 @@ struct drm_encoder_helper_funcs {
> >  	void (*dpms)(struct drm_encoder *encoder, int mode);
> > 
> >  	/**
> > +	 * @mode_valid:
> > +	 *
> > +	 * This callback is used to check if a specific mode is valid in this
> > +	 * encoder. This should be implemented if the encoder has some sort
> > +	 * of restriction in the modes it can display. For example, a given
> > +	 * encoder may be responsible to set a clock value. If the clock can
> > +	 * not produce all the values for the available modes then this 
> callback
> > +	 * can be used to restrict the number of modes to only the ones that
> > +	 * can be displayed.
> > +	 *
> > +	 * This hook is used by the probe helpers to filter the mode list in
> > +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> > +	 * atomic helpers to validate modes supplied by userspace in
> > +	 * drm_atomic_helper_check_modeset().
> > +	 *
> > +	 * This function is optional.
> > +	 *
> > +	 * RETURNS:
> > +	 *
> > +	 * drm_mode_status Enum
> > +	 */
> > +	enum drm_mode_status (*mode_valid)(struct drm_encoder *crtc,
> > +					   const struct drm_display_mode 
> *mode);
> > +
> > +	/**
> >  	 * @mode_fixup:
> >  	 *
> >  	 * This callback is used to validate and adjust a mode. The parameter
> > @@ -482,21 +529,11 @@ struct drm_encoder_helper_funcs {
> >  	 * Atomic drivers which need to inspect and adjust more state should
> >  	 * instead use the @atomic_check callback.
> >  	 *
> > -	 * Also beware that neither core nor helpers filter modes before
> > -	 * passing them to the driver: While the list of modes that is
> > -	 * advertised to userspace is filtered using the connector's
> > -	 * &drm_connector_helper_funcs.mode_valid callback, neither the core 
> nor
> > -	 * the helpers do any filtering on modes passed in from userspace when
> > -	 * setting a mode. It is therefore possible for userspace to pass in a
> > -	 * mode that was previously filtered out using
> > -	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
> > -	 * wasn't probed from EDID or similar to begin with.  Even though this
> > -	 * is an advanced feature and rarely used nowadays, some users rely on
> > -	 * being able to specify modes manually so drivers must be prepared to
> > -	 * deal with it. Specifically this means that all drivers need not 
> only
> > -	 * validate modes in &drm_connector.mode_valid but also in this or in
> > -	 * the &drm_crtc_helper_funcs.mode_fixup callback to make sure
> > -	 * invalid modes passed in from userspace are rejected.
> > +	 * Also beware that userspace can request its own custom modes, 
> neither
> > +	 * core nor helpers filter modes to the list of probe modes reported 
> by
> > +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To 
> ensure
> > +	 * that modes are filtered consistently put any encoder constraints 
> and
> > +	 * limits checks into @mode_valid.
> >  	 *
> >  	 * RETURNS:
> >  	 *
> > @@ -686,6 +723,12 @@ struct drm_encoder_helper_funcs {
> >  	 * state objects passed-in or assembled in the overall 
> &drm_atomic_state
> >  	 * update tracking structure.
> >  	 *
> > +	 * Also beware that userspace can request its own custom modes, 
> neither
> > +	 * core nor helpers filter modes to the list of probe modes reported 
> by
> > +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To 
> ensure
> > +	 * that modes are filtered consistently put any encoder constraints 
> and
> > +	 * limits checks into @mode_valid.
> > +	 *
> >  	 * RETURNS:
> >  	 *
> >  	 * 0 on success, -EINVAL if the state or the transition can't be
> > @@ -795,13 +838,20 @@ struct drm_connector_helper_funcs {
> >  	 * (which is usually derived from the EDID data block from the sink).
> >  	 * See e.g. drm_helper_probe_single_connector_modes().
> >  	 *
> > +	 * This function is optional.
> > +	 *
> >  	 * NOTE:
> >  	 *
> >  	 * This only filters the mode list supplied to userspace in the
> > -	 * GETCONNECOTR IOCTL. Userspace is free to create modes of its own 
> and
> > -	 * ask the kernel to use them. It this case the atomic helpers or 
> legacy
> > -	 * CRTC helpers will not call this function. Drivers therefore must
> > -	 * still fully validate any mode passed in in a modeset request.
> > +	 * GETCONNECTOR IOCTL. Compared to 
> &drm_encoder_helper_funcs.mode_valid,
> > +	 * &drm_crtc_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid,
> > +	 * which are also called by the atomic helpers from
> > +	 * drm_atomic_helper_check_modeset(). This allows userspace to force 
> and
> > +	 * ignore sink constraint (like the pixel clock limits in the screen's
> > +	 * EDID), which is useful for e.g. testing, or working around a broken
> > +	 * EDID. Any source hardware constraint (which always need to be
> > +	 * enforced) therefore should be checked in one of the above 
> callbacks,
> > +	 * and not this one here.
> >  	 *
> >  	 * To avoid races with concurrent connector state updates, the helper
> >  	 * libraries always call this with the 
> &drm_mode_config.connection_mutex
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-12 12:37     ` Andrzej Hajda
@ 2017-05-15  6:56       ` Daniel Vetter
  2017-05-15  8:10         ` Andrzej Hajda
  0 siblings, 1 reply; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15  6:56 UTC (permalink / raw)
  To: Andrzej Hajda
  Cc: Jose Abreu, Daniel Vetter, Alexey Brodkin, DRI Development,
	Jose Abreu, Carlos Palminha

On Fri, May 12, 2017 at 02:37:17PM +0200, Andrzej Hajda wrote:
> On 12.05.2017 09:31, Daniel Vetter wrote:
> > From: Jose Abreu <Jose.Abreu@synopsys.com>
> >
> > This adds a new callback to crtc, encoder and bridge helper functions
> > called mode_valid(). This callback shall be implemented if the
> > corresponding component has some sort of restriction in the modes
> > that can be displayed. A NULL callback implicates that the component
> > can display all the modes.
> >
> > We also change the documentation so that the new and old callbacks
> > are correctly documented.
> >
> > Only the callbacks were implemented to simplify review process,
> > following patches will make use of them.
> >
> > Changes in v2 from Daniel:
> > - Update the warning about how modes aren't filtered in atomic_check -
> >   the heleprs help out a lot more now.
> > - Consistenly roll out that warning, crtc/encoder's atomic_check
> >   missed it.
> > - Sprinkle more links all over the place, so it's easier to see where
> >   this stuff is used and how the differen hooks are related.
> > - Note that ->mode_valid is optional everywhere.
> > - Explain why the connector's mode_valid is special and does _not_ get
> >   called in atomic_check.
> >
> > Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> > Cc: Jose Abreu <joabreu@synopsys.com>
> > Cc: Carlos Palminha <palminha@synopsys.com>
> > Cc: Alexey Brodkin <abrodkin@synopsys.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Dave Airlie <airlied@linux.ie>
> > Cc: Andrzej Hajda <a.hajda@samsung.com>
> > Cc: Archit Taneja <architt@codeaurora.org>
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2)
> > ---
> >  include/drm/drm_bridge.h                 |  31 +++++++++
> >  include/drm/drm_modeset_helper_vtables.h | 116 ++++++++++++++++++++++---------
> >  2 files changed, 114 insertions(+), 33 deletions(-)
> >
> > diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> > index fdd82fcbf168..f694de756ecf 100644
> > --- a/include/drm/drm_bridge.h
> > +++ b/include/drm/drm_bridge.h
> > @@ -59,6 +59,31 @@ struct drm_bridge_funcs {
> >  	void (*detach)(struct drm_bridge *bridge);
> >  
> >  	/**
> > +	 * @mode_valid:
> > +	 *
> > +	 * This callback is used to check if a specific mode is valid in this
> > +	 * bridge. This should be implemented if the bridge has some sort of
> > +	 * restriction in the modes it can display. For example, a given bridge
> > +	 * may be responsible to set a clock value. If the clock can not
> > +	 * produce all the values for the available modes then this callback
> > +	 * can be used to restrict the number of modes to only the ones that
> > +	 * can be displayed.
> > +	 *
> > +	 * This hook is used by the probe helpers to filter the mode list in
> > +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> > +	 * atomic helpers to validate modes supplied by userspace in
> > +	 * drm_atomic_helper_check_modeset().
> > +	 *
> > +	 * This function is optional.
> > +	 *
> > +	 * RETURNS:
> > +	 *
> > +	 * drm_mode_status Enum
> > +	 */
> > +	enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc,
> > +					   const struct drm_display_mode *mode);
> 
> I have put my concerns here but it touches all mode_valid callbacks.
> As the callback can be called in mode probe and atomic check it could
> only inspect common set of properties for both contexts, for example
> crtc cannot check to which encoder it is connected, am I right?
> Maybe it would be good to emphasize it here, as it is emphasized in case
> of mode_fixup callbacks.

You can inspect nothing else but the mode here. Looking at anything else
is not allowed since this is the generic check which should work for any
config. Good question, so I'll augment the docs to address this.

> > +
> > +	/**
> >  	 * @mode_fixup:
> >  	 *
> >  	 * This callback is used to validate and adjust a mode. The paramater
> > @@ -82,6 +107,12 @@ struct drm_bridge_funcs {
> >  	 * NOT touch any persistent state (hardware or software) or data
> >  	 * structures except the passed in @state parameter.
> >  	 *
> > +	 * Also beware that userspace can request its own custom modes, neither
> > +	 * core nor helpers filter modes to the list of probe modes reported by
> > +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> > +	 * that modes are filtered consistently put any bridge constraints and
> > +	 * limits checks into @mode_valid.
> > +	 *
> >  	 * RETURNS:
> >  	 *
> >  	 * True if an acceptable configuration is possible, false if the modeset
> > diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> > index c01c328f6cc8..91d071ff1232 100644
> > --- a/include/drm/drm_modeset_helper_vtables.h
> > +++ b/include/drm/drm_modeset_helper_vtables.h
> > @@ -106,6 +106,31 @@ struct drm_crtc_helper_funcs {
> >  	void (*commit)(struct drm_crtc *crtc);
> >  
> >  	/**
> > +	 * @mode_valid:
> > +	 *
> > +	 * This callback is used to check if a specific mode is valid in this
> > +	 * crtc. This should be implemented if the crtc has some sort of
> > +	 * restriction in the modes it can display. For example, a given crtc
> > +	 * may be responsible to set a clock value. If the clock can not
> > +	 * produce all the values for the available modes then this callback
> > +	 * can be used to restrict the number of modes to only the ones that
> > +	 * can be displayed.
> > +	 *
> > +	 * This hook is used by the probe helpers to filter the mode list in
> > +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> > +	 * atomic helpers to validate modes supplied by userspace in
> > +	 * drm_atomic_helper_check_modeset().
> > +	 *
> > +	 * This function is optional.
> > +	 *
> > +	 * RETURNS:
> > +	 *
> > +	 * drm_mode_status Enum
> > +	 */
> > +	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
> > +					   const struct drm_display_mode *mode);
> > +
> > +	/**
> >  	 * @mode_fixup:
> >  	 *
> >  	 * This callback is used to validate a mode. The parameter mode is the
> > @@ -132,20 +157,11 @@ struct drm_crtc_helper_funcs {
> >  	 * Atomic drivers which need to inspect and adjust more state should
> >  	 * instead use the @atomic_check callback.
> >  	 *
> > -	 * Also beware that neither core nor helpers filter modes before
> > -	 * passing them to the driver: While the list of modes that is
> > -	 * advertised to userspace is filtered using the
> > -	 * &drm_connector.mode_valid callback, neither the core nor the helpers
> > -	 * do any filtering on modes passed in from userspace when setting a
> > -	 * mode. It is therefore possible for userspace to pass in a mode that
> > -	 * was previously filtered out using &drm_connector.mode_valid or add a
> > -	 * custom mode that wasn't probed from EDID or similar to begin with.
> > -	 * Even though this is an advanced feature and rarely used nowadays,
> > -	 * some users rely on being able to specify modes manually so drivers
> > -	 * must be prepared to deal with it. Specifically this means that all
> > -	 * drivers need not only validate modes in &drm_connector.mode_valid but
> > -	 * also in this or in the &drm_encoder_helper_funcs.mode_fixup callback
> > -	 * to make sure invalid modes passed in from userspace are rejected.
> > +	 * Also beware that userspace can request its own custom modes, neither
> > +	 * core nor helpers filter modes to the list of probe modes reported by
> > +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> > +	 * that modes are filtered consistently put any CRTC constraints and
> > +	 * limits checks into @mode_valid.
> 
> Why we do not make mode_fixup obsolete for atomic drivers as
> atomic_check can do the same and is more powerful, this way we could
> avoid the overlapped functionality of mode_valid and mode_fixup.

What do you mean with "make obselete"? mode_fixup is the compat callback,
atomic_check is the shiny new one, so it is already obselete.

> >  	 *
> >  	 * RETURNS:
> >  	 *
> > @@ -341,6 +357,12 @@ struct drm_crtc_helper_funcs {
> >  	 * state objects passed-in or assembled in the overall &drm_atomic_state
> >  	 * update tracking structure.
> >  	 *
> > +	 * Also beware that userspace can request its own custom modes, neither
> > +	 * core nor helpers filter modes to the list of probe modes reported by
> > +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> > +	 * that modes are filtered consistently put any CRTC constraints and
> > +	 * limits checks into @mode_valid.
> > +	 *
> >  	 * RETURNS:
> >  	 *
> >  	 * 0 on success, -EINVAL if the state or the transition can't be
> > @@ -457,6 +479,31 @@ struct drm_encoder_helper_funcs {
> >  	void (*dpms)(struct drm_encoder *encoder, int mode);
> >  
> >  	/**
> > +	 * @mode_valid:
> > +	 *
> > +	 * This callback is used to check if a specific mode is valid in this
> > +	 * encoder. This should be implemented if the encoder has some sort
> > +	 * of restriction in the modes it can display. For example, a given
> > +	 * encoder may be responsible to set a clock value. If the clock can
> > +	 * not produce all the values for the available modes then this callback
> > +	 * can be used to restrict the number of modes to only the ones that
> > +	 * can be displayed.
> > +	 *
> > +	 * This hook is used by the probe helpers to filter the mode list in
> > +	 * drm_helper_probe_single_connector_modes(), and it is used by the
> > +	 * atomic helpers to validate modes supplied by userspace in
> > +	 * drm_atomic_helper_check_modeset().
> > +	 *
> > +	 * This function is optional.
> > +	 *
> > +	 * RETURNS:
> > +	 *
> > +	 * drm_mode_status Enum
> > +	 */
> > +	enum drm_mode_status (*mode_valid)(struct drm_encoder *crtc,
> > +					   const struct drm_display_mode *mode);
> > +
> > +	/**
> >  	 * @mode_fixup:
> >  	 *
> >  	 * This callback is used to validate and adjust a mode. The parameter
> > @@ -482,21 +529,11 @@ struct drm_encoder_helper_funcs {
> >  	 * Atomic drivers which need to inspect and adjust more state should
> >  	 * instead use the @atomic_check callback.
> >  	 *
> > -	 * Also beware that neither core nor helpers filter modes before
> > -	 * passing them to the driver: While the list of modes that is
> > -	 * advertised to userspace is filtered using the connector's
> > -	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
> > -	 * the helpers do any filtering on modes passed in from userspace when
> > -	 * setting a mode. It is therefore possible for userspace to pass in a
> > -	 * mode that was previously filtered out using
> > -	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
> > -	 * wasn't probed from EDID or similar to begin with.  Even though this
> > -	 * is an advanced feature and rarely used nowadays, some users rely on
> > -	 * being able to specify modes manually so drivers must be prepared to
> > -	 * deal with it. Specifically this means that all drivers need not only
> > -	 * validate modes in &drm_connector.mode_valid but also in this or in
> > -	 * the &drm_crtc_helper_funcs.mode_fixup callback to make sure
> > -	 * invalid modes passed in from userspace are rejected.
> > +	 * Also beware that userspace can request its own custom modes, neither
> > +	 * core nor helpers filter modes to the list of probe modes reported by
> > +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> > +	 * that modes are filtered consistently put any encoder constraints and
> > +	 * limits checks into @mode_valid.
> >  	 *
> >  	 * RETURNS:
> >  	 *
> > @@ -686,6 +723,12 @@ struct drm_encoder_helper_funcs {
> >  	 * state objects passed-in or assembled in the overall &drm_atomic_state
> >  	 * update tracking structure.
> >  	 *
> > +	 * Also beware that userspace can request its own custom modes, neither
> > +	 * core nor helpers filter modes to the list of probe modes reported by
> > +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
> > +	 * that modes are filtered consistently put any encoder constraints and
> > +	 * limits checks into @mode_valid.
> > +	 *
> >  	 * RETURNS:
> >  	 *
> >  	 * 0 on success, -EINVAL if the state or the transition can't be
> > @@ -795,13 +838,20 @@ struct drm_connector_helper_funcs {
> >  	 * (which is usually derived from the EDID data block from the sink).
> >  	 * See e.g. drm_helper_probe_single_connector_modes().
> >  	 *
> > +	 * This function is optional.
> > +	 *
> >  	 * NOTE:
> >  	 *
> >  	 * This only filters the mode list supplied to userspace in the
> > -	 * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and
> > -	 * ask the kernel to use them. It this case the atomic helpers or legacy
> > -	 * CRTC helpers will not call this function. Drivers therefore must
> > -	 * still fully validate any mode passed in in a modeset request.
> > +	 * GETCONNECTOR IOCTL. Compared to &drm_encoder_helper_funcs.mode_valid,
> > +	 * &drm_crtc_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid,
> > +	 * which are also called by the atomic helpers from
> > +	 * drm_atomic_helper_check_modeset(). This allows userspace to force and
> > +	 * ignore sink constraint (like the pixel clock limits in the screen's
> > +	 * EDID), which is useful for e.g. testing, or working around a broken
> > +	 * EDID. Any source hardware constraint (which always need to be
> > +	 * enforced) therefore should be checked in one of the above callbacks,
> > +	 * and not this one here.
> 
> The callback has the same name but different semantic, little bit weird.
> But do we really need connector::mode_valid then? I mean: are there
> connectors not bound to bridge/encoder which have their own constraints?
> If there are no such connectors, we can remove this callback.

Yes. And the pixel clock limit is exactly the current real-world use-case:
There are hdmi screens which have a pixel clock limit set, but in reality
can take higher modes. There's users out there who want to use these
higher modes on these peculiar screens. But for everyone else (and for all
other screens), we do need to filter modes correctly (the example here is
dual-link vs. single-link limits, which is an interaction between sink and
source).

> If they are rare, maybe just adding loop to connector::get_modes would
> be enough.

What do you mean with "adding a loop"?
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-15  6:56       ` Daniel Vetter
@ 2017-05-15  8:10         ` Andrzej Hajda
  2017-05-15  8:14           ` Daniel Vetter
  0 siblings, 1 reply; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-15  8:10 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Jose Abreu, Daniel Vetter, Alexey Brodkin, DRI Development,
	Jose Abreu, Carlos Palminha

On 15.05.2017 08:56, Daniel Vetter wrote:
> On Fri, May 12, 2017 at 02:37:17PM +0200, Andrzej Hajda wrote:
>> On 12.05.2017 09:31, Daniel Vetter wrote:
>>> From: Jose Abreu <Jose.Abreu@synopsys.com>
>>>
>>> This adds a new callback to crtc, encoder and bridge helper functions
>>> called mode_valid(). This callback shall be implemented if the
>>> corresponding component has some sort of restriction in the modes
>>> that can be displayed. A NULL callback implicates that the component
>>> can display all the modes.
>>>
>>> We also change the documentation so that the new and old callbacks
>>> are correctly documented.
>>>
>>> Only the callbacks were implemented to simplify review process,
>>> following patches will make use of them.
>>>
>>> Changes in v2 from Daniel:
>>> - Update the warning about how modes aren't filtered in atomic_check -
>>>   the heleprs help out a lot more now.
>>> - Consistenly roll out that warning, crtc/encoder's atomic_check
>>>   missed it.
>>> - Sprinkle more links all over the place, so it's easier to see where
>>>   this stuff is used and how the differen hooks are related.
>>> - Note that ->mode_valid is optional everywhere.
>>> - Explain why the connector's mode_valid is special and does _not_ get
>>>   called in atomic_check.
>>>
>>> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
>>> Cc: Jose Abreu <joabreu@synopsys.com>
>>> Cc: Carlos Palminha <palminha@synopsys.com>
>>> Cc: Alexey Brodkin <abrodkin@synopsys.com>
>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
>>> Cc: Dave Airlie <airlied@linux.ie>
>>> Cc: Andrzej Hajda <a.hajda@samsung.com>
>>> Cc: Archit Taneja <architt@codeaurora.org>
>>> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2)
>>> ---
>>>  include/drm/drm_bridge.h                 |  31 +++++++++
>>>  include/drm/drm_modeset_helper_vtables.h | 116 ++++++++++++++++++++++---------
>>>  2 files changed, 114 insertions(+), 33 deletions(-)
>>>
>>> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
>>> index fdd82fcbf168..f694de756ecf 100644
>>> --- a/include/drm/drm_bridge.h
>>> +++ b/include/drm/drm_bridge.h
>>> @@ -59,6 +59,31 @@ struct drm_bridge_funcs {
>>>  	void (*detach)(struct drm_bridge *bridge);
>>>  
>>>  	/**
>>> +	 * @mode_valid:
>>> +	 *
>>> +	 * This callback is used to check if a specific mode is valid in this
>>> +	 * bridge. This should be implemented if the bridge has some sort of
>>> +	 * restriction in the modes it can display. For example, a given bridge
>>> +	 * may be responsible to set a clock value. If the clock can not
>>> +	 * produce all the values for the available modes then this callback
>>> +	 * can be used to restrict the number of modes to only the ones that
>>> +	 * can be displayed.
>>> +	 *
>>> +	 * This hook is used by the probe helpers to filter the mode list in
>>> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
>>> +	 * atomic helpers to validate modes supplied by userspace in
>>> +	 * drm_atomic_helper_check_modeset().
>>> +	 *
>>> +	 * This function is optional.
>>> +	 *
>>> +	 * RETURNS:
>>> +	 *
>>> +	 * drm_mode_status Enum
>>> +	 */
>>> +	enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc,
>>> +					   const struct drm_display_mode *mode);
>> I have put my concerns here but it touches all mode_valid callbacks.
>> As the callback can be called in mode probe and atomic check it could
>> only inspect common set of properties for both contexts, for example
>> crtc cannot check to which encoder it is connected, am I right?
>> Maybe it would be good to emphasize it here, as it is emphasized in case
>> of mode_fixup callbacks.
> You can inspect nothing else but the mode here. Looking at anything else
> is not allowed since this is the generic check which should work for any
> config. Good question, so I'll augment the docs to address this.
>
>>> +
>>> +	/**
>>>  	 * @mode_fixup:
>>>  	 *
>>>  	 * This callback is used to validate and adjust a mode. The paramater
>>> @@ -82,6 +107,12 @@ struct drm_bridge_funcs {
>>>  	 * NOT touch any persistent state (hardware or software) or data
>>>  	 * structures except the passed in @state parameter.
>>>  	 *
>>> +	 * Also beware that userspace can request its own custom modes, neither
>>> +	 * core nor helpers filter modes to the list of probe modes reported by
>>> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
>>> +	 * that modes are filtered consistently put any bridge constraints and
>>> +	 * limits checks into @mode_valid.
>>> +	 *
>>>  	 * RETURNS:
>>>  	 *
>>>  	 * True if an acceptable configuration is possible, false if the modeset
>>> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
>>> index c01c328f6cc8..91d071ff1232 100644
>>> --- a/include/drm/drm_modeset_helper_vtables.h
>>> +++ b/include/drm/drm_modeset_helper_vtables.h
>>> @@ -106,6 +106,31 @@ struct drm_crtc_helper_funcs {
>>>  	void (*commit)(struct drm_crtc *crtc);
>>>  
>>>  	/**
>>> +	 * @mode_valid:
>>> +	 *
>>> +	 * This callback is used to check if a specific mode is valid in this
>>> +	 * crtc. This should be implemented if the crtc has some sort of
>>> +	 * restriction in the modes it can display. For example, a given crtc
>>> +	 * may be responsible to set a clock value. If the clock can not
>>> +	 * produce all the values for the available modes then this callback
>>> +	 * can be used to restrict the number of modes to only the ones that
>>> +	 * can be displayed.
>>> +	 *
>>> +	 * This hook is used by the probe helpers to filter the mode list in
>>> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
>>> +	 * atomic helpers to validate modes supplied by userspace in
>>> +	 * drm_atomic_helper_check_modeset().
>>> +	 *
>>> +	 * This function is optional.
>>> +	 *
>>> +	 * RETURNS:
>>> +	 *
>>> +	 * drm_mode_status Enum
>>> +	 */
>>> +	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
>>> +					   const struct drm_display_mode *mode);
>>> +
>>> +	/**
>>>  	 * @mode_fixup:
>>>  	 *
>>>  	 * This callback is used to validate a mode. The parameter mode is the
>>> @@ -132,20 +157,11 @@ struct drm_crtc_helper_funcs {
>>>  	 * Atomic drivers which need to inspect and adjust more state should
>>>  	 * instead use the @atomic_check callback.
>>>  	 *
>>> -	 * Also beware that neither core nor helpers filter modes before
>>> -	 * passing them to the driver: While the list of modes that is
>>> -	 * advertised to userspace is filtered using the
>>> -	 * &drm_connector.mode_valid callback, neither the core nor the helpers
>>> -	 * do any filtering on modes passed in from userspace when setting a
>>> -	 * mode. It is therefore possible for userspace to pass in a mode that
>>> -	 * was previously filtered out using &drm_connector.mode_valid or add a
>>> -	 * custom mode that wasn't probed from EDID or similar to begin with.
>>> -	 * Even though this is an advanced feature and rarely used nowadays,
>>> -	 * some users rely on being able to specify modes manually so drivers
>>> -	 * must be prepared to deal with it. Specifically this means that all
>>> -	 * drivers need not only validate modes in &drm_connector.mode_valid but
>>> -	 * also in this or in the &drm_encoder_helper_funcs.mode_fixup callback
>>> -	 * to make sure invalid modes passed in from userspace are rejected.
>>> +	 * Also beware that userspace can request its own custom modes, neither
>>> +	 * core nor helpers filter modes to the list of probe modes reported by
>>> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
>>> +	 * that modes are filtered consistently put any CRTC constraints and
>>> +	 * limits checks into @mode_valid.
>> Why we do not make mode_fixup obsolete for atomic drivers as
>> atomic_check can do the same and is more powerful, this way we could
>> avoid the overlapped functionality of mode_valid and mode_fixup.
> What do you mean with "make obselete"? mode_fixup is the compat callback,
> atomic_check is the shiny new one, so it is already obselete.

Hmm, the docs says 'atomic drivers which need to inspect and adjust more
state should instead use the @atomic_check callback', it does not sound
like 'mode_fixup is obsolete for atomic drivers, please use atomic_check
instead' :)

>>>  	 *
>>>  	 * RETURNS:
>>>  	 *
>>> @@ -341,6 +357,12 @@ struct drm_crtc_helper_funcs {
>>>  	 * state objects passed-in or assembled in the overall &drm_atomic_state
>>>  	 * update tracking structure.
>>>  	 *
>>> +	 * Also beware that userspace can request its own custom modes, neither
>>> +	 * core nor helpers filter modes to the list of probe modes reported by
>>> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
>>> +	 * that modes are filtered consistently put any CRTC constraints and
>>> +	 * limits checks into @mode_valid.
>>> +	 *
>>>  	 * RETURNS:
>>>  	 *
>>>  	 * 0 on success, -EINVAL if the state or the transition can't be
>>> @@ -457,6 +479,31 @@ struct drm_encoder_helper_funcs {
>>>  	void (*dpms)(struct drm_encoder *encoder, int mode);
>>>  
>>>  	/**
>>> +	 * @mode_valid:
>>> +	 *
>>> +	 * This callback is used to check if a specific mode is valid in this
>>> +	 * encoder. This should be implemented if the encoder has some sort
>>> +	 * of restriction in the modes it can display. For example, a given
>>> +	 * encoder may be responsible to set a clock value. If the clock can
>>> +	 * not produce all the values for the available modes then this callback
>>> +	 * can be used to restrict the number of modes to only the ones that
>>> +	 * can be displayed.
>>> +	 *
>>> +	 * This hook is used by the probe helpers to filter the mode list in
>>> +	 * drm_helper_probe_single_connector_modes(), and it is used by the
>>> +	 * atomic helpers to validate modes supplied by userspace in
>>> +	 * drm_atomic_helper_check_modeset().
>>> +	 *
>>> +	 * This function is optional.
>>> +	 *
>>> +	 * RETURNS:
>>> +	 *
>>> +	 * drm_mode_status Enum
>>> +	 */
>>> +	enum drm_mode_status (*mode_valid)(struct drm_encoder *crtc,
>>> +					   const struct drm_display_mode *mode);
>>> +
>>> +	/**
>>>  	 * @mode_fixup:
>>>  	 *
>>>  	 * This callback is used to validate and adjust a mode. The parameter
>>> @@ -482,21 +529,11 @@ struct drm_encoder_helper_funcs {
>>>  	 * Atomic drivers which need to inspect and adjust more state should
>>>  	 * instead use the @atomic_check callback.
>>>  	 *
>>> -	 * Also beware that neither core nor helpers filter modes before
>>> -	 * passing them to the driver: While the list of modes that is
>>> -	 * advertised to userspace is filtered using the connector's
>>> -	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
>>> -	 * the helpers do any filtering on modes passed in from userspace when
>>> -	 * setting a mode. It is therefore possible for userspace to pass in a
>>> -	 * mode that was previously filtered out using
>>> -	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
>>> -	 * wasn't probed from EDID or similar to begin with.  Even though this
>>> -	 * is an advanced feature and rarely used nowadays, some users rely on
>>> -	 * being able to specify modes manually so drivers must be prepared to
>>> -	 * deal with it. Specifically this means that all drivers need not only
>>> -	 * validate modes in &drm_connector.mode_valid but also in this or in
>>> -	 * the &drm_crtc_helper_funcs.mode_fixup callback to make sure
>>> -	 * invalid modes passed in from userspace are rejected.
>>> +	 * Also beware that userspace can request its own custom modes, neither
>>> +	 * core nor helpers filter modes to the list of probe modes reported by
>>> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
>>> +	 * that modes are filtered consistently put any encoder constraints and
>>> +	 * limits checks into @mode_valid.
>>>  	 *
>>>  	 * RETURNS:
>>>  	 *
>>> @@ -686,6 +723,12 @@ struct drm_encoder_helper_funcs {
>>>  	 * state objects passed-in or assembled in the overall &drm_atomic_state
>>>  	 * update tracking structure.
>>>  	 *
>>> +	 * Also beware that userspace can request its own custom modes, neither
>>> +	 * core nor helpers filter modes to the list of probe modes reported by
>>> +	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
>>> +	 * that modes are filtered consistently put any encoder constraints and
>>> +	 * limits checks into @mode_valid.
>>> +	 *
>>>  	 * RETURNS:
>>>  	 *
>>>  	 * 0 on success, -EINVAL if the state or the transition can't be
>>> @@ -795,13 +838,20 @@ struct drm_connector_helper_funcs {
>>>  	 * (which is usually derived from the EDID data block from the sink).
>>>  	 * See e.g. drm_helper_probe_single_connector_modes().
>>>  	 *
>>> +	 * This function is optional.
>>> +	 *
>>>  	 * NOTE:
>>>  	 *
>>>  	 * This only filters the mode list supplied to userspace in the
>>> -	 * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and
>>> -	 * ask the kernel to use them. It this case the atomic helpers or legacy
>>> -	 * CRTC helpers will not call this function. Drivers therefore must
>>> -	 * still fully validate any mode passed in in a modeset request.
>>> +	 * GETCONNECTOR IOCTL. Compared to &drm_encoder_helper_funcs.mode_valid,
>>> +	 * &drm_crtc_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid,
>>> +	 * which are also called by the atomic helpers from
>>> +	 * drm_atomic_helper_check_modeset(). This allows userspace to force and
>>> +	 * ignore sink constraint (like the pixel clock limits in the screen's
>>> +	 * EDID), which is useful for e.g. testing, or working around a broken
>>> +	 * EDID. Any source hardware constraint (which always need to be
>>> +	 * enforced) therefore should be checked in one of the above callbacks,
>>> +	 * and not this one here.
>> The callback has the same name but different semantic, little bit weird.
>> But do we really need connector::mode_valid then? I mean: are there
>> connectors not bound to bridge/encoder which have their own constraints?
>> If there are no such connectors, we can remove this callback.
> Yes. And the pixel clock limit is exactly the current real-world use-case:
> There are hdmi screens which have a pixel clock limit set, but in reality
> can take higher modes. There's users out there who want to use these
> higher modes on these peculiar screens. But for everyone else (and for all
> other screens), we do need to filter modes correctly (the example here is
> dual-link vs. single-link limits, which is an interaction between sink and
> source).
>
>> If they are rare, maybe just adding loop to connector::get_modes would
>> be enough.
> What do you mean with "adding a loop"?
> -Daniel

Sorry for confusing shortcut, I have just inspected call sites of both
callbacks - drm_helper_probe_single_connector_modes, both callbacks are
called from this function, so my idea was to move loop
'list_for_each_entry(mode, &connector->modes, head){ ....,
...->mode_valid(...); ....}' from
drm_helper_probe_single_connector_modes to .get_modes callback. After
looking bit more at this function I have realized that such change is
not so obvious, and it is not really clear if the final result will be
better :).

Regards
Andrzej




_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-15  8:10         ` Andrzej Hajda
@ 2017-05-15  8:14           ` Daniel Vetter
  0 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15  8:14 UTC (permalink / raw)
  To: Andrzej Hajda
  Cc: Jose Abreu, Alexey Brodkin, DRI Development, Jose Abreu, Carlos Palminha

On Mon, May 15, 2017 at 10:10 AM, Andrzej Hajda <a.hajda@samsung.com> wrote:
> Sorry for confusing shortcut, I have just inspected call sites of both
> callbacks - drm_helper_probe_single_connector_modes, both callbacks are
> called from this function, so my idea was to move loop
> 'list_for_each_entry(mode, &connector->modes, head){ ....,
> ...->mode_valid(...); ....}' from
> drm_helper_probe_single_connector_modes to .get_modes callback. After
> looking bit more at this function I have realized that such change is
> not so obvious, and it is not really clear if the final result will be
> better :).

This would defeat the purpose of ->get_modes, which is to just grab
the modes from the sink, without filtering for source constraints,
which is done by ->mode_valid. That framework is why we have the probe
helpers, if you want to do something else you can always implement
->fill_modes (which is the uapi entry point) yourself.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 2/6] drm: Add drm_{crtc/encoder/connector}_mode_valid()
  2017-05-11  9:05 ` [PATCH v3 2/6] drm: Add drm_{crtc/encoder/connector}_mode_valid() Jose Abreu
@ 2017-05-15  8:27     ` Andrzej Hajda
  0 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-15  8:27 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel
  Cc: Carlos Palminha, Alexey Brodkin, Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Archit Taneja

On 11.05.2017 11:05, Jose Abreu wrote:
> Add a new helper to call crtc->mode_valid, connector->mode_valid
> and encoder->mode_valid callbacks.
>
> Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> ---
> Changes v2->v3:
> 	- Move helpers to drm_probe_helper.c (Daniel)
> 	- Squeeze patches that introduce the helpers into a single
> 	one (Daniel)
>
>  drivers/gpu/drm/drm_crtc_helper_internal.h | 13 ++++++++++
>  drivers/gpu/drm/drm_probe_helper.c         | 38 ++++++++++++++++++++++++++++++
>  2 files changed, 51 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_crtc_helper_internal.h b/drivers/gpu/drm/drm_crtc_helper_internal.h
> index 28295e5..97dfe20 100644
> --- a/drivers/gpu/drm/drm_crtc_helper_internal.h
> +++ b/drivers/gpu/drm/drm_crtc_helper_internal.h
> @@ -26,7 +26,11 @@
>   * implementation details and are not exported to drivers.
>   */
>  
> +#include <drm/drm_connector.h>
> +#include <drm/drm_crtc.h>
>  #include <drm/drm_dp_helper.h>
> +#include <drm/drm_encoder.h>
> +#include <drm/drm_modes.h>
>  
>  /* drm_fb_helper.c */
>  #ifdef CONFIG_DRM_FBDEV_EMULATION
> @@ -62,4 +66,13 @@ static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
>  static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
>  {
>  }
> +
> +/* drm_probe_helper.c */
> +enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
> +					 const struct drm_display_mode *mode);
> +enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder,
> +					    const struct drm_display_mode *mode);
> +enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
> +					      struct drm_display_mode *mode);
> +
>  #endif
> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> index 1b0c14a..f01abdc 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -38,6 +38,9 @@
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +
> +#include "drm_crtc_helper_internal.h"
>  
>  /**
>   * DOC: output probing helper overview
> @@ -113,6 +116,41 @@ static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
>  	return 1;
>  }
>  
> +enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
> +					 const struct drm_display_mode *mode)
> +{
> +	const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
> +
> +	if (!crtc_funcs || !crtc_funcs->mode_valid)
> +		return MODE_OK;
> +
> +	return crtc_funcs->mode_valid(crtc, mode);
> +}
> +
> +enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder,
> +					    const struct drm_display_mode *mode)
> +{
> +	const struct drm_encoder_helper_funcs *encoder_funcs =
> +		encoder->helper_private;
> +
> +	if (!encoder_funcs || !encoder_funcs->mode_valid)
> +		return MODE_OK;
> +
> +	return encoder_funcs->mode_valid(encoder, mode);
> +}
> +
> +enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
> +					      struct drm_display_mode *mode)
> +{
> +	const struct drm_connector_helper_funcs *connector_funcs =
> +		connector->helper_private;
> +
> +	if (!connector_funcs || !connector_funcs->mode_valid)
> +		return MODE_OK;
> +
> +	return connector_funcs->mode_valid(connector, mode);
> +}
> +

"Copy/Paste" as the main generic programming technique in C :)
I guess clever/scary macro wouldn't be an option.

Anyway:
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej

>  #define DRM_OUTPUT_POLL_PERIOD (10*HZ)
>  /**
>   * drm_kms_helper_poll_enable - re-enable output polling.

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 2/6] drm: Add drm_{crtc/encoder/connector}_mode_valid()
@ 2017-05-15  8:27     ` Andrzej Hajda
  0 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-15  8:27 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel
  Cc: Daniel Vetter, Alexey Brodkin, Carlos Palminha

On 11.05.2017 11:05, Jose Abreu wrote:
> Add a new helper to call crtc->mode_valid, connector->mode_valid
> and encoder->mode_valid callbacks.
>
> Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> ---
> Changes v2->v3:
> 	- Move helpers to drm_probe_helper.c (Daniel)
> 	- Squeeze patches that introduce the helpers into a single
> 	one (Daniel)
>
>  drivers/gpu/drm/drm_crtc_helper_internal.h | 13 ++++++++++
>  drivers/gpu/drm/drm_probe_helper.c         | 38 ++++++++++++++++++++++++++++++
>  2 files changed, 51 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_crtc_helper_internal.h b/drivers/gpu/drm/drm_crtc_helper_internal.h
> index 28295e5..97dfe20 100644
> --- a/drivers/gpu/drm/drm_crtc_helper_internal.h
> +++ b/drivers/gpu/drm/drm_crtc_helper_internal.h
> @@ -26,7 +26,11 @@
>   * implementation details and are not exported to drivers.
>   */
>  
> +#include <drm/drm_connector.h>
> +#include <drm/drm_crtc.h>
>  #include <drm/drm_dp_helper.h>
> +#include <drm/drm_encoder.h>
> +#include <drm/drm_modes.h>
>  
>  /* drm_fb_helper.c */
>  #ifdef CONFIG_DRM_FBDEV_EMULATION
> @@ -62,4 +66,13 @@ static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
>  static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
>  {
>  }
> +
> +/* drm_probe_helper.c */
> +enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
> +					 const struct drm_display_mode *mode);
> +enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder,
> +					    const struct drm_display_mode *mode);
> +enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
> +					      struct drm_display_mode *mode);
> +
>  #endif
> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> index 1b0c14a..f01abdc 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -38,6 +38,9 @@
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +
> +#include "drm_crtc_helper_internal.h"
>  
>  /**
>   * DOC: output probing helper overview
> @@ -113,6 +116,41 @@ static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
>  	return 1;
>  }
>  
> +enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
> +					 const struct drm_display_mode *mode)
> +{
> +	const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
> +
> +	if (!crtc_funcs || !crtc_funcs->mode_valid)
> +		return MODE_OK;
> +
> +	return crtc_funcs->mode_valid(crtc, mode);
> +}
> +
> +enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder,
> +					    const struct drm_display_mode *mode)
> +{
> +	const struct drm_encoder_helper_funcs *encoder_funcs =
> +		encoder->helper_private;
> +
> +	if (!encoder_funcs || !encoder_funcs->mode_valid)
> +		return MODE_OK;
> +
> +	return encoder_funcs->mode_valid(encoder, mode);
> +}
> +
> +enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
> +					      struct drm_display_mode *mode)
> +{
> +	const struct drm_connector_helper_funcs *connector_funcs =
> +		connector->helper_private;
> +
> +	if (!connector_funcs || !connector_funcs->mode_valid)
> +		return MODE_OK;
> +
> +	return connector_funcs->mode_valid(connector, mode);
> +}
> +

"Copy/Paste" as the main generic programming technique in C :)
I guess clever/scary macro wouldn't be an option.

Anyway:
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej

>  #define DRM_OUTPUT_POLL_PERIOD (10*HZ)
>  /**
>   * drm_kms_helper_poll_enable - re-enable output polling.


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 4/6] drm: Use new mode_valid() helpers in connector probe helper
  2017-05-11  9:06 ` [PATCH v3 4/6] drm: Use new mode_valid() helpers in connector probe helper Jose Abreu
@ 2017-05-15  8:39     ` Andrzej Hajda
  0 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-15  8:39 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel
  Cc: Carlos Palminha, Alexey Brodkin, Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Archit Taneja

On 11.05.2017 11:06, Jose Abreu wrote:
> This changes the connector probe helper function to use the new
> encoder->mode_valid(), bridge->mode_valid() and crtc->mode_valid()
> helper callbacks to validate the modes.
>
> The new callbacks are optional so the behaviour remains the same
> if they are not implemented. If they are, then the code loops
> through all the connector's encodersXbridgesXcrtcs and calls the
> callback.
>
> If at least a valid encoderXbridgeXcrtc combination is found which
> accepts the mode then the function returns MODE_OK.
>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> ---
>
> Changes v2->v3:
> 	- Call also bridge->mode_valid (Daniel)
> Changes v1->v2:
> 	- Use new helpers suggested by Ville
> 	- Change documentation (Daniel)
>
>  drivers/gpu/drm/drm_probe_helper.c | 65 ++++++++++++++++++++++++++++++++++++--
>  1 file changed, 62 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> index f01abdc..84d660e 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -83,6 +83,61 @@
>  	return MODE_OK;
>  }
>  
> +static enum drm_mode_status
> +drm_mode_validate_connector(struct drm_connector *connector,
> +			    struct drm_display_mode *mode)
> +{
> +	struct drm_device *dev = connector->dev;
> +	uint32_t *ids = connector->encoder_ids;
> +	enum drm_mode_status ret = MODE_OK;
> +	unsigned int i;
> +
> +	/* Step 1: Validate against connector */
> +	ret = drm_connector_mode_valid(connector, mode);
> +	if (ret != MODE_OK)
> +		return ret;
> +
> +	/* Step 2: Validate against encoders and crtcs */
> +	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> +		struct drm_encoder *encoder = drm_encoder_find(dev, ids[i]);
> +		struct drm_crtc *crtc;
> +
> +		if (!encoder)
> +			continue;
> +
> +		ret = drm_encoder_mode_valid(encoder, mode);
> +		if (ret != MODE_OK) {
> +			/* No point in continuing for crtc check as this encoder
> +			 * will not accept the mode anyway. If all encoders
> +			 * reject the mode then, at exit, ret will not be
> +			 * MODE_OK. */
> +			continue;
> +		}
> +
> +		ret = drm_bridge_mode_valid(encoder->bridge, mode);
> +		if (ret != MODE_OK) {
> +			/* There is also no point in continuing for crtc check
> +			 * here. */
> +			continue;
> +		}

Maybe it is a bikeshedding, but wouldn't be better to call
drm_bridge_mode_valid from drm_encoder_mode_valid, in general call all
bridge related stuff from corresponding encoder stuff?
This is more question about role of encoder->bridge, should it be
treated as encoder's extension, or as 1st class citizen in drm?

Another concern is about order of calls, it is from sink to source, to
keep it consistent bridge should be called before encoder, am I right?
Beside this:
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej

> +
> +		drm_for_each_crtc(crtc, dev) {
> +			if (!drm_encoder_crtc_ok(encoder, crtc))
> +				continue;
> +
> +			ret = drm_crtc_mode_valid(crtc, mode);
> +			if (ret == MODE_OK) {
> +				/* If we get to this point there is at least
> +				 * one combination of encoder+crtc that works
> +				 * for this mode. Lets return now. */
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	return ret;
> +}
> +
>  static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
>  {
>  	struct drm_cmdline_mode *cmdline_mode;
> @@ -322,7 +377,11 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
>   *    - drm_mode_validate_flag() checks the modes against basic connector
>   *      capabilities (interlace_allowed,doublescan_allowed,stereo_allowed)
>   *    - the optional &drm_connector_helper_funcs.mode_valid helper can perform
> - *      driver and/or hardware specific checks
> + *      driver and/or sink specific checks
> + *    - the optional &drm_crtc_helper_funcs.mode_valid,
> + *      &drm_bridge_funcs.mode_valid and &drm_encoder_helper_funcs.mode_valid
> + *      helpers can perform driver and/or source specific checks which are also
> + *      enforced by the modeset/atomic helpers
>   *
>   * 5. Any mode whose status is not OK is pruned from the connector's modes list,
>   *    accompanied by a debug message indicating the reason for the mode's
> @@ -466,8 +525,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
>  		if (mode->status == MODE_OK)
>  			mode->status = drm_mode_validate_flag(mode, mode_flags);
>  
> -		if (mode->status == MODE_OK && connector_funcs->mode_valid)
> -			mode->status = connector_funcs->mode_valid(connector,
> +		if (mode->status == MODE_OK)
> +			mode->status = drm_mode_validate_connector(connector,
>  								   mode);
>  	}
>  

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 4/6] drm: Use new mode_valid() helpers in connector probe helper
@ 2017-05-15  8:39     ` Andrzej Hajda
  0 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-15  8:39 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel
  Cc: Daniel Vetter, Alexey Brodkin, Carlos Palminha

On 11.05.2017 11:06, Jose Abreu wrote:
> This changes the connector probe helper function to use the new
> encoder->mode_valid(), bridge->mode_valid() and crtc->mode_valid()
> helper callbacks to validate the modes.
>
> The new callbacks are optional so the behaviour remains the same
> if they are not implemented. If they are, then the code loops
> through all the connector's encodersXbridgesXcrtcs and calls the
> callback.
>
> If at least a valid encoderXbridgeXcrtc combination is found which
> accepts the mode then the function returns MODE_OK.
>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> ---
>
> Changes v2->v3:
> 	- Call also bridge->mode_valid (Daniel)
> Changes v1->v2:
> 	- Use new helpers suggested by Ville
> 	- Change documentation (Daniel)
>
>  drivers/gpu/drm/drm_probe_helper.c | 65 ++++++++++++++++++++++++++++++++++++--
>  1 file changed, 62 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> index f01abdc..84d660e 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -83,6 +83,61 @@
>  	return MODE_OK;
>  }
>  
> +static enum drm_mode_status
> +drm_mode_validate_connector(struct drm_connector *connector,
> +			    struct drm_display_mode *mode)
> +{
> +	struct drm_device *dev = connector->dev;
> +	uint32_t *ids = connector->encoder_ids;
> +	enum drm_mode_status ret = MODE_OK;
> +	unsigned int i;
> +
> +	/* Step 1: Validate against connector */
> +	ret = drm_connector_mode_valid(connector, mode);
> +	if (ret != MODE_OK)
> +		return ret;
> +
> +	/* Step 2: Validate against encoders and crtcs */
> +	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> +		struct drm_encoder *encoder = drm_encoder_find(dev, ids[i]);
> +		struct drm_crtc *crtc;
> +
> +		if (!encoder)
> +			continue;
> +
> +		ret = drm_encoder_mode_valid(encoder, mode);
> +		if (ret != MODE_OK) {
> +			/* No point in continuing for crtc check as this encoder
> +			 * will not accept the mode anyway. If all encoders
> +			 * reject the mode then, at exit, ret will not be
> +			 * MODE_OK. */
> +			continue;
> +		}
> +
> +		ret = drm_bridge_mode_valid(encoder->bridge, mode);
> +		if (ret != MODE_OK) {
> +			/* There is also no point in continuing for crtc check
> +			 * here. */
> +			continue;
> +		}

Maybe it is a bikeshedding, but wouldn't be better to call
drm_bridge_mode_valid from drm_encoder_mode_valid, in general call all
bridge related stuff from corresponding encoder stuff?
This is more question about role of encoder->bridge, should it be
treated as encoder's extension, or as 1st class citizen in drm?

Another concern is about order of calls, it is from sink to source, to
keep it consistent bridge should be called before encoder, am I right?
Beside this:
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej

> +
> +		drm_for_each_crtc(crtc, dev) {
> +			if (!drm_encoder_crtc_ok(encoder, crtc))
> +				continue;
> +
> +			ret = drm_crtc_mode_valid(crtc, mode);
> +			if (ret == MODE_OK) {
> +				/* If we get to this point there is at least
> +				 * one combination of encoder+crtc that works
> +				 * for this mode. Lets return now. */
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	return ret;
> +}
> +
>  static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
>  {
>  	struct drm_cmdline_mode *cmdline_mode;
> @@ -322,7 +377,11 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
>   *    - drm_mode_validate_flag() checks the modes against basic connector
>   *      capabilities (interlace_allowed,doublescan_allowed,stereo_allowed)
>   *    - the optional &drm_connector_helper_funcs.mode_valid helper can perform
> - *      driver and/or hardware specific checks
> + *      driver and/or sink specific checks
> + *    - the optional &drm_crtc_helper_funcs.mode_valid,
> + *      &drm_bridge_funcs.mode_valid and &drm_encoder_helper_funcs.mode_valid
> + *      helpers can perform driver and/or source specific checks which are also
> + *      enforced by the modeset/atomic helpers
>   *
>   * 5. Any mode whose status is not OK is pruned from the connector's modes list,
>   *    accompanied by a debug message indicating the reason for the mode's
> @@ -466,8 +525,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
>  		if (mode->status == MODE_OK)
>  			mode->status = drm_mode_validate_flag(mode, mode_flags);
>  
> -		if (mode->status == MODE_OK && connector_funcs->mode_valid)
> -			mode->status = connector_funcs->mode_valid(connector,
> +		if (mode->status == MODE_OK)
> +			mode->status = drm_mode_validate_connector(connector,
>  								   mode);
>  	}
>  


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 5/6] drm: Use mode_valid() in atomic modeset
  2017-05-11  9:06 ` [PATCH v3 5/6] drm: Use mode_valid() in atomic modeset Jose Abreu
@ 2017-05-15  8:45   ` Andrzej Hajda
  0 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-15  8:45 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel
  Cc: Carlos Palminha, Alexey Brodkin, Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Archit Taneja

On 11.05.2017 11:06, Jose Abreu wrote:
> This patches makes use of the new mode_valid() callbacks introduced
> previously to validate the full video pipeline when modesetting.
>
> This calls the encoder->mode_valid(), bridge->mode_valid() and
> crtc->mode_valid() so that we can make sure that the mode will
> be accepted in every components.
>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>

Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback
  2017-05-11  9:06 ` [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback Jose Abreu
@ 2017-05-15  8:53     ` Daniel Vetter
  2017-05-15  8:54     ` Andrzej Hajda
  1 sibling, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15  8:53 UTC (permalink / raw)
  To: Jose Abreu
  Cc: dri-devel, linux-kernel, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Andrzej Hajda, Archit Taneja

On Thu, May 11, 2017 at 10:06:02AM +0100, Jose Abreu wrote:
> Now that we have a callback to check if crtc supports a given mode
> we can use it in arcpgu so that we restrict the number of probbed
> modes to the ones we can actually display.
> 
> This is specially useful because arcpgu crtc is responsible to set
> a clock value in the commit() stage but unfortunatelly this clock
> does not support all the needed ranges.
> 
> Also, remove the atomic_check() callback as mode_valid() callback
> will be called before.
> 
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>

Btw for justifying your patch series a bit more, would be real sweet to
roll ->mode_valid out to more drivers. I see two easy cases:

bridge/analogix-anx78xx.c: has a simple mode_fixup which really is just a
mode_valid callback

bridge/synopsys/dw-hdmi.c: simply hand-rolls what you've done here, we
could move the connector_mode valid to the bridge and done.

Care to type these 2 patches on top, just to make this a bit more useful
and a clearer case for merging?

Thanks, Daniel

> ---
>  drivers/gpu/drm/arc/arcpgu_crtc.c | 39 ++++++++++++++++++++++++---------------
>  1 file changed, 24 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
> index ad9a959..01cae0a 100644
> --- a/drivers/gpu/drm/arc/arcpgu_crtc.c
> +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
> @@ -32,6 +32,18 @@
>  	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
>  };
>  
> +static bool arc_pgu_is_mode_valid(struct arcpgu_drm_private *arcpgu,
> +				  const struct drm_display_mode *mode)
> +{
> +	long rate, clk_rate = mode->clock * 1000;
> +
> +	rate = clk_round_rate(arcpgu->clk, clk_rate);
> +	if (rate != clk_rate)
> +		return false;
> +
> +	return true;
> +}
> +
>  static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
>  {
>  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> @@ -64,6 +76,17 @@ static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
>  	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
>  };
>  
> +enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc,
> +					     const struct drm_display_mode *mode)
> +{
> +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> +
> +	if (!arc_pgu_is_mode_valid(arcpgu, mode))
> +		return MODE_NOCLOCK;
> +
> +	return MODE_OK;
> +}
> +
>  static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
>  {
>  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> @@ -129,20 +152,6 @@ static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
>  			      ~ARCPGU_CTRL_ENABLE_MASK);
>  }
>  
> -static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
> -				     struct drm_crtc_state *state)
> -{
> -	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> -	struct drm_display_mode *mode = &state->adjusted_mode;
> -	long rate, clk_rate = mode->clock * 1000;
> -
> -	rate = clk_round_rate(arcpgu->clk, clk_rate);
> -	if (rate != clk_rate)
> -		return -EINVAL;
> -
> -	return 0;
> -}
> -
>  static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>  				      struct drm_crtc_state *state)
>  {
> @@ -158,6 +167,7 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>  }
>  
>  static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
> +	.mode_valid	= arc_pgu_crtc_mode_valid,
>  	.mode_set	= drm_helper_crtc_mode_set,
>  	.mode_set_base	= drm_helper_crtc_mode_set_base,
>  	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
> @@ -165,7 +175,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>  	.disable	= arc_pgu_crtc_disable,
>  	.prepare	= arc_pgu_crtc_disable,
>  	.commit		= arc_pgu_crtc_enable,
> -	.atomic_check	= arc_pgu_crtc_atomic_check,
>  	.atomic_begin	= arc_pgu_crtc_atomic_begin,
>  };
>  
> -- 
> 1.9.1
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback
@ 2017-05-15  8:53     ` Daniel Vetter
  0 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15  8:53 UTC (permalink / raw)
  To: Jose Abreu
  Cc: Daniel Vetter, Alexey Brodkin, linux-kernel, dri-devel, Carlos Palminha

On Thu, May 11, 2017 at 10:06:02AM +0100, Jose Abreu wrote:
> Now that we have a callback to check if crtc supports a given mode
> we can use it in arcpgu so that we restrict the number of probbed
> modes to the ones we can actually display.
> 
> This is specially useful because arcpgu crtc is responsible to set
> a clock value in the commit() stage but unfortunatelly this clock
> does not support all the needed ranges.
> 
> Also, remove the atomic_check() callback as mode_valid() callback
> will be called before.
> 
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>

Btw for justifying your patch series a bit more, would be real sweet to
roll ->mode_valid out to more drivers. I see two easy cases:

bridge/analogix-anx78xx.c: has a simple mode_fixup which really is just a
mode_valid callback

bridge/synopsys/dw-hdmi.c: simply hand-rolls what you've done here, we
could move the connector_mode valid to the bridge and done.

Care to type these 2 patches on top, just to make this a bit more useful
and a clearer case for merging?

Thanks, Daniel

> ---
>  drivers/gpu/drm/arc/arcpgu_crtc.c | 39 ++++++++++++++++++++++++---------------
>  1 file changed, 24 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
> index ad9a959..01cae0a 100644
> --- a/drivers/gpu/drm/arc/arcpgu_crtc.c
> +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
> @@ -32,6 +32,18 @@
>  	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
>  };
>  
> +static bool arc_pgu_is_mode_valid(struct arcpgu_drm_private *arcpgu,
> +				  const struct drm_display_mode *mode)
> +{
> +	long rate, clk_rate = mode->clock * 1000;
> +
> +	rate = clk_round_rate(arcpgu->clk, clk_rate);
> +	if (rate != clk_rate)
> +		return false;
> +
> +	return true;
> +}
> +
>  static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
>  {
>  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> @@ -64,6 +76,17 @@ static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
>  	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
>  };
>  
> +enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc,
> +					     const struct drm_display_mode *mode)
> +{
> +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> +
> +	if (!arc_pgu_is_mode_valid(arcpgu, mode))
> +		return MODE_NOCLOCK;
> +
> +	return MODE_OK;
> +}
> +
>  static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
>  {
>  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> @@ -129,20 +152,6 @@ static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
>  			      ~ARCPGU_CTRL_ENABLE_MASK);
>  }
>  
> -static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
> -				     struct drm_crtc_state *state)
> -{
> -	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> -	struct drm_display_mode *mode = &state->adjusted_mode;
> -	long rate, clk_rate = mode->clock * 1000;
> -
> -	rate = clk_round_rate(arcpgu->clk, clk_rate);
> -	if (rate != clk_rate)
> -		return -EINVAL;
> -
> -	return 0;
> -}
> -
>  static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>  				      struct drm_crtc_state *state)
>  {
> @@ -158,6 +167,7 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>  }
>  
>  static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
> +	.mode_valid	= arc_pgu_crtc_mode_valid,
>  	.mode_set	= drm_helper_crtc_mode_set,
>  	.mode_set_base	= drm_helper_crtc_mode_set_base,
>  	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
> @@ -165,7 +175,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>  	.disable	= arc_pgu_crtc_disable,
>  	.prepare	= arc_pgu_crtc_disable,
>  	.commit		= arc_pgu_crtc_enable,
> -	.atomic_check	= arc_pgu_crtc_atomic_check,
>  	.atomic_begin	= arc_pgu_crtc_atomic_begin,
>  };
>  
> -- 
> 1.9.1
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback
  2017-05-11  9:06 ` [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback Jose Abreu
@ 2017-05-15  8:54     ` Andrzej Hajda
  2017-05-15  8:54     ` Andrzej Hajda
  1 sibling, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-15  8:54 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel
  Cc: Carlos Palminha, Alexey Brodkin, Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Archit Taneja

On 11.05.2017 11:06, Jose Abreu wrote:
> Now that we have a callback to check if crtc supports a given mode
> we can use it in arcpgu so that we restrict the number of probbed
> modes to the ones we can actually display.
>
> This is specially useful because arcpgu crtc is responsible to set
> a clock value in the commit() stage but unfortunatelly this clock
> does not support all the needed ranges.
>
> Also, remove the atomic_check() callback as mode_valid() callback
> will be called before.
>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>

Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback
@ 2017-05-15  8:54     ` Andrzej Hajda
  0 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-15  8:54 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel
  Cc: Daniel Vetter, Alexey Brodkin, Carlos Palminha

On 11.05.2017 11:06, Jose Abreu wrote:
> Now that we have a callback to check if crtc supports a given mode
> we can use it in arcpgu so that we restrict the number of probbed
> modes to the ones we can actually display.
>
> This is specially useful because arcpgu crtc is responsible to set
> a clock value in the commit() stage but unfortunatelly this clock
> does not support all the needed ranges.
>
> Also, remove the atomic_check() callback as mode_valid() callback
> will be called before.
>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>

Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better
  2017-05-12  7:31   ` [PATCH] " Daniel Vetter
                       ` (2 preceding siblings ...)
  2017-05-12 15:59     ` Jose Abreu
@ 2017-05-15  9:11     ` Daniel Vetter
  2017-05-15  9:11       ` [PATCH 2/2] drm/doc: Clarify mode_fixup vs. atomic_check a bit more Daniel Vetter
                         ` (2 more replies)
  2017-05-15  9:33     ` [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks Daniel Vetter
  4 siblings, 3 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15  9:11 UTC (permalink / raw)
  To: DRI Development
  Cc: Jose Abreu, Daniel Vetter, Laurent Pinchart, Daniel Vetter

Laurent started a massive discussion on IRC about this. Let's try to
document common usage a bit better.

v2: Cross-links+typos.

Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Jose Abreu <Jose.Abreu@synopsys.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 include/drm/drm_bridge.h                 |  2 +-
 include/drm/drm_crtc.h                   | 28 +++++++++++++++++++++++++---
 include/drm/drm_modeset_helper_vtables.h |  6 ++++--
 3 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index f694de756ecf..f3ad38d0d621 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -91,7 +91,7 @@ struct drm_bridge_funcs {
 	 * the display chain, either the final &drm_connector or the next
 	 * &drm_bridge. The parameter adjusted_mode is the input mode the bridge
 	 * requires. It can be modified by this callback and does not need to
-	 * match mode.
+	 * match mode. See also &drm_crtc_state.adjusted_mode for more details.
 	 *
 	 * This is the only hook that allows a bridge to reject a modeset. If
 	 * this function passes all other callbacks must succeed for this
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 06236b002c22..5f5d53973ca5 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -90,8 +90,6 @@ struct drm_plane_helper_funcs;
  * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
  * @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors
  * @encoder_mask: bitmask of (1 << drm_encoder_index(encoder)) of attached encoders
- * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings
- * @mode: current mode timings
  * @mode_blob: &drm_property_blob for @mode
  * @state: backpointer to global drm_atomic_state
  *
@@ -131,9 +129,33 @@ struct drm_crtc_state {
 	u32 connector_mask;
 	u32 encoder_mask;
 
-	/* adjusted_mode: for use by helpers and drivers */
+	/**
+	 * @adjusted_mode:
+	 *
+	 * Internal display timings which can be used by the driver to handle
+	 * differences between the mode requested by userspace in @mode and what
+	 * is actually programmed into the hardware. It is purely driver
+	 * implementation defined what exactly this adjusted mode means. Usually
+	 * it is used to store the hardware display timings used between the
+	 * CRTC and encoder blocks.
+	 */
 	struct drm_display_mode adjusted_mode;
 
+	/**
+	 * @mode:
+	 *
+	 * Display timings requested by userspace. The driver should try to
+	 * match the refresh rate as close as possible (but note that it's
+	 * undefined what exactly is close enough, e.g. some of the HDMI modes
+	 * only differ in less than 1% of the refresh rate). The active width
+	 * and height as observed by userspace for positioning planes must match
+	 * exactly.
+	 *
+	 * For external connectors where the sink isn't fixed (like with a
+	 * built-in panel), this mode here should match the physical mode on the
+	 * wire to the last details (i.e. including sync polarities and
+	 * everything).
+	 */
 	struct drm_display_mode mode;
 
 	/* blob property to expose current mode to atomic userspace */
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index 91d071ff1232..c72fca544a41 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -138,7 +138,8 @@ struct drm_crtc_helper_funcs {
 	 * encoders need to be fed with. Note that this is the inverse semantics
 	 * of the meaning for the &drm_encoder and &drm_bridge_funcs.mode_fixup
 	 * vfunc. If the CRTC cannot support the requested conversion from mode
-	 * to adjusted_mode it should reject the modeset.
+	 * to adjusted_mode it should reject the modeset. See also
+	 * &drm_crtc_state.adjusted_mode for more details.
 	 *
 	 * This function is used by both legacy CRTC helpers and atomic helpers.
 	 * With atomic helpers it is optional.
@@ -510,7 +511,8 @@ struct drm_encoder_helper_funcs {
 	 * mode is the display mode that should be fed to the next element in
 	 * the display chain, either the final &drm_connector or a &drm_bridge.
 	 * The parameter adjusted_mode is the input mode the encoder requires. It
-	 * can be modified by this callback and does not need to match mode.
+	 * can be modified by this callback and does not need to match mode. See
+	 * also &drm_crtc_state.adjusted_mode for more details.
 	 *
 	 * This function is used by both legacy CRTC helpers and atomic helpers.
 	 * This hook is optional.
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH 2/2] drm/doc: Clarify mode_fixup vs. atomic_check a bit more
  2017-05-15  9:11     ` [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better Daniel Vetter
@ 2017-05-15  9:11       ` Daniel Vetter
  2017-05-16  2:41         ` Jose Abreu
  2017-05-16 13:14         ` Andrzej Hajda
  2017-05-16  2:38       ` [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better Jose Abreu
  2017-05-16 13:17       ` Andrzej Hajda
  2 siblings, 2 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15  9:11 UTC (permalink / raw)
  To: DRI Development
  Cc: Jose Abreu, Daniel Vetter, Laurent Pinchart, Daniel Vetter

Brought up by both Laurent and Andrzej when reviewing the new
->mode_valid hooks. Since mode_fixup is just a simpler version of the
much more generic atomic_check we can't really unify it with
mode_valid. Most drivers should probably switch their current
mode_fixup code to either the new mode_valid or the atomic_check
hooks, but e.g. that doesn't exist yet for bridges, and for CRTCs the
situation is a bit more complicated. Hence there's no clear
equivalence between mode_fixup and mode_valid, even if it looks like
that at first glance.

Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Jose Abreu <Jose.Abreu@synopsys.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 include/drm/drm_modeset_helper_vtables.h | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index c72fca544a41..613b2a602b77 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -156,7 +156,11 @@ struct drm_crtc_helper_funcs {
 	 * allowed.
 	 *
 	 * Atomic drivers which need to inspect and adjust more state should
-	 * instead use the @atomic_check callback.
+	 * instead use the @atomic_check callback, but note that they're not
+	 * perfectly equivalent: @mode_valid is called from
+	 * drm_atomic_helper_check_modeset(), but @atomic_check is called from
+	 * drm_atomic_helper_check_planes(), because originally it was meant for
+	 * plane update checks only..
 	 *
 	 * Also beware that userspace can request its own custom modes, neither
 	 * core nor helpers filter modes to the list of probe modes reported by
@@ -529,7 +533,9 @@ struct drm_encoder_helper_funcs {
 	 * allowed.
 	 *
 	 * Atomic drivers which need to inspect and adjust more state should
-	 * instead use the @atomic_check callback.
+	 * instead use the @atomic_check callback. If @atomic_check is used,
+	 * this hook isn't called since @atomic_check allows a strict superset
+	 * of the functionality of @mode_fixup.
 	 *
 	 * Also beware that userspace can request its own custom modes, neither
 	 * core nor helpers filter modes to the list of probe modes reported by
@@ -716,6 +722,11 @@ struct drm_encoder_helper_funcs {
 	 * update the CRTC to match what the encoder needs for the requested
 	 * connector.
 	 *
+	 * Since this provides a strict superset of the functionality of
+	 * @mode_fixup (the requested and adjusted modes are both available
+	 * through the passed in &struct drm_crtc_state) @mode_fixup is not
+	 * called when @atomic_check is implemented.
+	 *
 	 * This function is used by the atomic helpers, but it is optional.
 	 *
 	 * NOTE:
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 4/6] drm: Use new mode_valid() helpers in connector probe helper
  2017-05-15  8:39     ` Andrzej Hajda
@ 2017-05-15  9:30       ` Daniel Vetter
  -1 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15  9:30 UTC (permalink / raw)
  To: Andrzej Hajda
  Cc: Jose Abreu, dri-devel, linux-kernel, Carlos Palminha,
	Alexey Brodkin, Ville Syrjälä,
	Daniel Vetter, Dave Airlie, Archit Taneja

On Mon, May 15, 2017 at 10:39:35AM +0200, Andrzej Hajda wrote:
> On 11.05.2017 11:06, Jose Abreu wrote:
> > This changes the connector probe helper function to use the new
> > encoder->mode_valid(), bridge->mode_valid() and crtc->mode_valid()
> > helper callbacks to validate the modes.
> >
> > The new callbacks are optional so the behaviour remains the same
> > if they are not implemented. If they are, then the code loops
> > through all the connector's encodersXbridgesXcrtcs and calls the
> > callback.
> >
> > If at least a valid encoderXbridgeXcrtc combination is found which
> > accepts the mode then the function returns MODE_OK.
> >
> > Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> > Cc: Carlos Palminha <palminha@synopsys.com>
> > Cc: Alexey Brodkin <abrodkin@synopsys.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Dave Airlie <airlied@linux.ie>
> > Cc: Andrzej Hajda <a.hajda@samsung.com>
> > Cc: Archit Taneja <architt@codeaurora.org>
> > ---
> >
> > Changes v2->v3:
> > 	- Call also bridge->mode_valid (Daniel)
> > Changes v1->v2:
> > 	- Use new helpers suggested by Ville
> > 	- Change documentation (Daniel)
> >
> >  drivers/gpu/drm/drm_probe_helper.c | 65 ++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 62 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> > index f01abdc..84d660e 100644
> > --- a/drivers/gpu/drm/drm_probe_helper.c
> > +++ b/drivers/gpu/drm/drm_probe_helper.c
> > @@ -83,6 +83,61 @@
> >  	return MODE_OK;
> >  }
> >  
> > +static enum drm_mode_status
> > +drm_mode_validate_connector(struct drm_connector *connector,
> > +			    struct drm_display_mode *mode)
> > +{
> > +	struct drm_device *dev = connector->dev;
> > +	uint32_t *ids = connector->encoder_ids;
> > +	enum drm_mode_status ret = MODE_OK;
> > +	unsigned int i;
> > +
> > +	/* Step 1: Validate against connector */
> > +	ret = drm_connector_mode_valid(connector, mode);
> > +	if (ret != MODE_OK)
> > +		return ret;
> > +
> > +	/* Step 2: Validate against encoders and crtcs */
> > +	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> > +		struct drm_encoder *encoder = drm_encoder_find(dev, ids[i]);
> > +		struct drm_crtc *crtc;
> > +
> > +		if (!encoder)
> > +			continue;
> > +
> > +		ret = drm_encoder_mode_valid(encoder, mode);
> > +		if (ret != MODE_OK) {
> > +			/* No point in continuing for crtc check as this encoder
> > +			 * will not accept the mode anyway. If all encoders
> > +			 * reject the mode then, at exit, ret will not be
> > +			 * MODE_OK. */
> > +			continue;
> > +		}
> > +
> > +		ret = drm_bridge_mode_valid(encoder->bridge, mode);
> > +		if (ret != MODE_OK) {
> > +			/* There is also no point in continuing for crtc check
> > +			 * here. */
> > +			continue;
> > +		}
> 
> Maybe it is a bikeshedding, but wouldn't be better to call
> drm_bridge_mode_valid from drm_encoder_mode_valid, in general call all
> bridge related stuff from corresponding encoder stuff?
> This is more question about role of encoder->bridge, should it be
> treated as encoder's extension, or as 1st class citizen in drm?
> 
> Another concern is about order of calls, it is from sink to source, to
> keep it consistent bridge should be called before encoder, am I right?

For the atomic_check stuff (where we do change the passed-in mode) this
would be correct, and calling order and layering would matter. But this
just validates the mode in turn with everything, not taking any
cross-component constraint or other configuration-dependent constraints
into account. Hence it doesn't matter in which order we call stuff.

Note that the passed-in mode is const, so you can't escape. And v3 of
patch 1 now has added wording that you're not allowed to look at anything
else dynamie either.

Does that address your concern?
-Daniel

> Beside this:
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> 
>  --
> Regards
> Andrzej
> 
> > +
> > +		drm_for_each_crtc(crtc, dev) {
> > +			if (!drm_encoder_crtc_ok(encoder, crtc))
> > +				continue;
> > +
> > +			ret = drm_crtc_mode_valid(crtc, mode);
> > +			if (ret == MODE_OK) {
> > +				/* If we get to this point there is at least
> > +				 * one combination of encoder+crtc that works
> > +				 * for this mode. Lets return now. */
> > +				return ret;
> > +			}
> > +		}
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> >  static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
> >  {
> >  	struct drm_cmdline_mode *cmdline_mode;
> > @@ -322,7 +377,11 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
> >   *    - drm_mode_validate_flag() checks the modes against basic connector
> >   *      capabilities (interlace_allowed,doublescan_allowed,stereo_allowed)
> >   *    - the optional &drm_connector_helper_funcs.mode_valid helper can perform
> > - *      driver and/or hardware specific checks
> > + *      driver and/or sink specific checks
> > + *    - the optional &drm_crtc_helper_funcs.mode_valid,
> > + *      &drm_bridge_funcs.mode_valid and &drm_encoder_helper_funcs.mode_valid
> > + *      helpers can perform driver and/or source specific checks which are also
> > + *      enforced by the modeset/atomic helpers
> >   *
> >   * 5. Any mode whose status is not OK is pruned from the connector's modes list,
> >   *    accompanied by a debug message indicating the reason for the mode's
> > @@ -466,8 +525,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
> >  		if (mode->status == MODE_OK)
> >  			mode->status = drm_mode_validate_flag(mode, mode_flags);
> >  
> > -		if (mode->status == MODE_OK && connector_funcs->mode_valid)
> > -			mode->status = connector_funcs->mode_valid(connector,
> > +		if (mode->status == MODE_OK)
> > +			mode->status = drm_mode_validate_connector(connector,
> >  								   mode);
> >  	}
> >  
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 4/6] drm: Use new mode_valid() helpers in connector probe helper
@ 2017-05-15  9:30       ` Daniel Vetter
  0 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15  9:30 UTC (permalink / raw)
  To: Andrzej Hajda
  Cc: Jose Abreu, Daniel Vetter, Alexey Brodkin, linux-kernel,
	dri-devel, Carlos Palminha

On Mon, May 15, 2017 at 10:39:35AM +0200, Andrzej Hajda wrote:
> On 11.05.2017 11:06, Jose Abreu wrote:
> > This changes the connector probe helper function to use the new
> > encoder->mode_valid(), bridge->mode_valid() and crtc->mode_valid()
> > helper callbacks to validate the modes.
> >
> > The new callbacks are optional so the behaviour remains the same
> > if they are not implemented. If they are, then the code loops
> > through all the connector's encodersXbridgesXcrtcs and calls the
> > callback.
> >
> > If at least a valid encoderXbridgeXcrtc combination is found which
> > accepts the mode then the function returns MODE_OK.
> >
> > Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> > Cc: Carlos Palminha <palminha@synopsys.com>
> > Cc: Alexey Brodkin <abrodkin@synopsys.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Dave Airlie <airlied@linux.ie>
> > Cc: Andrzej Hajda <a.hajda@samsung.com>
> > Cc: Archit Taneja <architt@codeaurora.org>
> > ---
> >
> > Changes v2->v3:
> > 	- Call also bridge->mode_valid (Daniel)
> > Changes v1->v2:
> > 	- Use new helpers suggested by Ville
> > 	- Change documentation (Daniel)
> >
> >  drivers/gpu/drm/drm_probe_helper.c | 65 ++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 62 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> > index f01abdc..84d660e 100644
> > --- a/drivers/gpu/drm/drm_probe_helper.c
> > +++ b/drivers/gpu/drm/drm_probe_helper.c
> > @@ -83,6 +83,61 @@
> >  	return MODE_OK;
> >  }
> >  
> > +static enum drm_mode_status
> > +drm_mode_validate_connector(struct drm_connector *connector,
> > +			    struct drm_display_mode *mode)
> > +{
> > +	struct drm_device *dev = connector->dev;
> > +	uint32_t *ids = connector->encoder_ids;
> > +	enum drm_mode_status ret = MODE_OK;
> > +	unsigned int i;
> > +
> > +	/* Step 1: Validate against connector */
> > +	ret = drm_connector_mode_valid(connector, mode);
> > +	if (ret != MODE_OK)
> > +		return ret;
> > +
> > +	/* Step 2: Validate against encoders and crtcs */
> > +	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> > +		struct drm_encoder *encoder = drm_encoder_find(dev, ids[i]);
> > +		struct drm_crtc *crtc;
> > +
> > +		if (!encoder)
> > +			continue;
> > +
> > +		ret = drm_encoder_mode_valid(encoder, mode);
> > +		if (ret != MODE_OK) {
> > +			/* No point in continuing for crtc check as this encoder
> > +			 * will not accept the mode anyway. If all encoders
> > +			 * reject the mode then, at exit, ret will not be
> > +			 * MODE_OK. */
> > +			continue;
> > +		}
> > +
> > +		ret = drm_bridge_mode_valid(encoder->bridge, mode);
> > +		if (ret != MODE_OK) {
> > +			/* There is also no point in continuing for crtc check
> > +			 * here. */
> > +			continue;
> > +		}
> 
> Maybe it is a bikeshedding, but wouldn't be better to call
> drm_bridge_mode_valid from drm_encoder_mode_valid, in general call all
> bridge related stuff from corresponding encoder stuff?
> This is more question about role of encoder->bridge, should it be
> treated as encoder's extension, or as 1st class citizen in drm?
> 
> Another concern is about order of calls, it is from sink to source, to
> keep it consistent bridge should be called before encoder, am I right?

For the atomic_check stuff (where we do change the passed-in mode) this
would be correct, and calling order and layering would matter. But this
just validates the mode in turn with everything, not taking any
cross-component constraint or other configuration-dependent constraints
into account. Hence it doesn't matter in which order we call stuff.

Note that the passed-in mode is const, so you can't escape. And v3 of
patch 1 now has added wording that you're not allowed to look at anything
else dynamie either.

Does that address your concern?
-Daniel

> Beside this:
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> 
>  --
> Regards
> Andrzej
> 
> > +
> > +		drm_for_each_crtc(crtc, dev) {
> > +			if (!drm_encoder_crtc_ok(encoder, crtc))
> > +				continue;
> > +
> > +			ret = drm_crtc_mode_valid(crtc, mode);
> > +			if (ret == MODE_OK) {
> > +				/* If we get to this point there is at least
> > +				 * one combination of encoder+crtc that works
> > +				 * for this mode. Lets return now. */
> > +				return ret;
> > +			}
> > +		}
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> >  static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
> >  {
> >  	struct drm_cmdline_mode *cmdline_mode;
> > @@ -322,7 +377,11 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
> >   *    - drm_mode_validate_flag() checks the modes against basic connector
> >   *      capabilities (interlace_allowed,doublescan_allowed,stereo_allowed)
> >   *    - the optional &drm_connector_helper_funcs.mode_valid helper can perform
> > - *      driver and/or hardware specific checks
> > + *      driver and/or sink specific checks
> > + *    - the optional &drm_crtc_helper_funcs.mode_valid,
> > + *      &drm_bridge_funcs.mode_valid and &drm_encoder_helper_funcs.mode_valid
> > + *      helpers can perform driver and/or source specific checks which are also
> > + *      enforced by the modeset/atomic helpers
> >   *
> >   * 5. Any mode whose status is not OK is pruned from the connector's modes list,
> >   *    accompanied by a debug message indicating the reason for the mode's
> > @@ -466,8 +525,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
> >  		if (mode->status == MODE_OK)
> >  			mode->status = drm_mode_validate_flag(mode, mode_flags);
> >  
> > -		if (mode->status == MODE_OK && connector_funcs->mode_valid)
> > -			mode->status = connector_funcs->mode_valid(connector,
> > +		if (mode->status == MODE_OK)
> > +			mode->status = drm_mode_validate_connector(connector,
> >  								   mode);
> >  	}
> >  
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-12  7:31   ` [PATCH] " Daniel Vetter
                       ` (3 preceding siblings ...)
  2017-05-15  9:11     ` [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better Daniel Vetter
@ 2017-05-15  9:33     ` Daniel Vetter
  2017-05-16 13:15       ` Andrzej Hajda
  4 siblings, 1 reply; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15  9:33 UTC (permalink / raw)
  To: DRI Development
  Cc: Jose Abreu, Daniel Vetter, Alexey Brodkin, Jose Abreu,
	Laurent Pinchart, Carlos Palminha

From: Jose Abreu <Jose.Abreu@synopsys.com>

This adds a new callback to crtc, encoder and bridge helper functions
called mode_valid(). This callback shall be implemented if the
corresponding component has some sort of restriction in the modes
that can be displayed. A NULL callback implicates that the component
can display all the modes.

We also change the documentation so that the new and old callbacks
are correctly documented.

Only the callbacks were implemented to simplify review process,
following patches will make use of them.

Changes in v2 from Daniel:
- Update the warning about how modes aren't filtered in atomic_check -
  the heleprs help out a lot more now.
- Consistenly roll out that warning, crtc/encoder's atomic_check
  missed it.
- Sprinkle more links all over the place, so it's easier to see where
  this stuff is used and how the differen hooks are related.
- Note that ->mode_valid is optional everywhere.
- Explain why the connector's mode_valid is special and does _not_ get
  called in atomic_check.

v3: Document what can and cannot be checked in mode_valid a bit better
(Andrjez). Answer: Only allowed to look at the mode, nothing else.

Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: Jose Abreu <joabreu@synopsys.com>
Cc: Carlos Palminha <palminha@synopsys.com>
Cc: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Airlie <airlied@linux.ie>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2)
---
 include/drm/drm_bridge.h                 |  40 +++++++++
 include/drm/drm_modeset_helper_vtables.h | 134 +++++++++++++++++++++++--------
 2 files changed, 141 insertions(+), 33 deletions(-)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index fdd82fcbf168..f703bafc2e30 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -59,6 +59,40 @@ struct drm_bridge_funcs {
 	void (*detach)(struct drm_bridge *bridge);
 
 	/**
+	 * @mode_valid:
+	 *
+	 * This callback is used to check if a specific mode is valid in this
+	 * bridge. This should be implemented if the bridge has some sort of
+	 * restriction in the modes it can display. For example, a given bridge
+	 * may be responsible to set a clock value. If the clock can not
+	 * produce all the values for the available modes then this callback
+	 * can be used to restrict the number of modes to only the ones that
+	 * can be displayed.
+	 *
+	 * This hook is used by the probe helpers to filter the mode list in
+	 * drm_helper_probe_single_connector_modes(), and it is used by the
+	 * atomic helpers to validate modes supplied by userspace in
+	 * drm_atomic_helper_check_modeset().
+	 *
+	 * This function is optional.
+	 *
+	 * NOTE:
+	 *
+	 * Since this function is both called from the check phase of an atomic
+	 * commit, and the mode validation in the probe paths it is not allowed
+	 * to look at anything else but the passed-in mode, and validate it
+	 * against configuration-invariant hardward constraints. Any further
+	 * limits which depend upon the configuration can only be checked in
+	 * @mode_fixup.
+	 *
+	 * RETURNS:
+	 *
+	 * drm_mode_status Enum
+	 */
+	enum drm_mode_status (*mode_valid)(struct drm_bridge *crtc,
+					   const struct drm_display_mode *mode);
+
+	/**
 	 * @mode_fixup:
 	 *
 	 * This callback is used to validate and adjust a mode. The paramater
@@ -82,6 +116,12 @@ struct drm_bridge_funcs {
 	 * NOT touch any persistent state (hardware or software) or data
 	 * structures except the passed in @state parameter.
 	 *
+	 * Also beware that userspace can request its own custom modes, neither
+	 * core nor helpers filter modes to the list of probe modes reported by
+	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
+	 * that modes are filtered consistently put any bridge constraints and
+	 * limits checks into @mode_valid.
+	 *
 	 * RETURNS:
 	 *
 	 * True if an acceptable configuration is possible, false if the modeset
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index c01c328f6cc8..739b832eb304 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -106,6 +106,40 @@ struct drm_crtc_helper_funcs {
 	void (*commit)(struct drm_crtc *crtc);
 
 	/**
+	 * @mode_valid:
+	 *
+	 * This callback is used to check if a specific mode is valid in this
+	 * crtc. This should be implemented if the crtc has some sort of
+	 * restriction in the modes it can display. For example, a given crtc
+	 * may be responsible to set a clock value. If the clock can not
+	 * produce all the values for the available modes then this callback
+	 * can be used to restrict the number of modes to only the ones that
+	 * can be displayed.
+	 *
+	 * This hook is used by the probe helpers to filter the mode list in
+	 * drm_helper_probe_single_connector_modes(), and it is used by the
+	 * atomic helpers to validate modes supplied by userspace in
+	 * drm_atomic_helper_check_modeset().
+	 *
+	 * This function is optional.
+	 *
+	 * NOTE:
+	 *
+	 * Since this function is both called from the check phase of an atomic
+	 * commit, and the mode validation in the probe paths it is not allowed
+	 * to look at anything else but the passed-in mode, and validate it
+	 * against configuration-invariant hardward constraints. Any further
+	 * limits which depend upon the configuration can only be checked in
+	 * @mode_fixup or @atomic_check.
+	 *
+	 * RETURNS:
+	 *
+	 * drm_mode_status Enum
+	 */
+	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
+					   const struct drm_display_mode *mode);
+
+	/**
 	 * @mode_fixup:
 	 *
 	 * This callback is used to validate a mode. The parameter mode is the
@@ -132,20 +166,11 @@ struct drm_crtc_helper_funcs {
 	 * Atomic drivers which need to inspect and adjust more state should
 	 * instead use the @atomic_check callback.
 	 *
-	 * Also beware that neither core nor helpers filter modes before
-	 * passing them to the driver: While the list of modes that is
-	 * advertised to userspace is filtered using the
-	 * &drm_connector.mode_valid callback, neither the core nor the helpers
-	 * do any filtering on modes passed in from userspace when setting a
-	 * mode. It is therefore possible for userspace to pass in a mode that
-	 * was previously filtered out using &drm_connector.mode_valid or add a
-	 * custom mode that wasn't probed from EDID or similar to begin with.
-	 * Even though this is an advanced feature and rarely used nowadays,
-	 * some users rely on being able to specify modes manually so drivers
-	 * must be prepared to deal with it. Specifically this means that all
-	 * drivers need not only validate modes in &drm_connector.mode_valid but
-	 * also in this or in the &drm_encoder_helper_funcs.mode_fixup callback
-	 * to make sure invalid modes passed in from userspace are rejected.
+	 * Also beware that userspace can request its own custom modes, neither
+	 * core nor helpers filter modes to the list of probe modes reported by
+	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
+	 * that modes are filtered consistently put any CRTC constraints and
+	 * limits checks into @mode_valid.
 	 *
 	 * RETURNS:
 	 *
@@ -341,6 +366,12 @@ struct drm_crtc_helper_funcs {
 	 * state objects passed-in or assembled in the overall &drm_atomic_state
 	 * update tracking structure.
 	 *
+	 * Also beware that userspace can request its own custom modes, neither
+	 * core nor helpers filter modes to the list of probe modes reported by
+	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
+	 * that modes are filtered consistently put any CRTC constraints and
+	 * limits checks into @mode_valid.
+	 *
 	 * RETURNS:
 	 *
 	 * 0 on success, -EINVAL if the state or the transition can't be
@@ -457,6 +488,40 @@ struct drm_encoder_helper_funcs {
 	void (*dpms)(struct drm_encoder *encoder, int mode);
 
 	/**
+	 * @mode_valid:
+	 *
+	 * This callback is used to check if a specific mode is valid in this
+	 * encoder. This should be implemented if the encoder has some sort
+	 * of restriction in the modes it can display. For example, a given
+	 * encoder may be responsible to set a clock value. If the clock can
+	 * not produce all the values for the available modes then this callback
+	 * can be used to restrict the number of modes to only the ones that
+	 * can be displayed.
+	 *
+	 * This hook is used by the probe helpers to filter the mode list in
+	 * drm_helper_probe_single_connector_modes(), and it is used by the
+	 * atomic helpers to validate modes supplied by userspace in
+	 * drm_atomic_helper_check_modeset().
+	 *
+	 * This function is optional.
+	 *
+	 * NOTE:
+	 *
+	 * Since this function is both called from the check phase of an atomic
+	 * commit, and the mode validation in the probe paths it is not allowed
+	 * to look at anything else but the passed-in mode, and validate it
+	 * against configuration-invariant hardward constraints. Any further
+	 * limits which depend upon the configuration can only be checked in
+	 * @mode_fixup or @atomic_check.
+	 *
+	 * RETURNS:
+	 *
+	 * drm_mode_status Enum
+	 */
+	enum drm_mode_status (*mode_valid)(struct drm_encoder *crtc,
+					   const struct drm_display_mode *mode);
+
+	/**
 	 * @mode_fixup:
 	 *
 	 * This callback is used to validate and adjust a mode. The parameter
@@ -482,21 +547,11 @@ struct drm_encoder_helper_funcs {
 	 * Atomic drivers which need to inspect and adjust more state should
 	 * instead use the @atomic_check callback.
 	 *
-	 * Also beware that neither core nor helpers filter modes before
-	 * passing them to the driver: While the list of modes that is
-	 * advertised to userspace is filtered using the connector's
-	 * &drm_connector_helper_funcs.mode_valid callback, neither the core nor
-	 * the helpers do any filtering on modes passed in from userspace when
-	 * setting a mode. It is therefore possible for userspace to pass in a
-	 * mode that was previously filtered out using
-	 * &drm_connector_helper_funcs.mode_valid or add a custom mode that
-	 * wasn't probed from EDID or similar to begin with.  Even though this
-	 * is an advanced feature and rarely used nowadays, some users rely on
-	 * being able to specify modes manually so drivers must be prepared to
-	 * deal with it. Specifically this means that all drivers need not only
-	 * validate modes in &drm_connector.mode_valid but also in this or in
-	 * the &drm_crtc_helper_funcs.mode_fixup callback to make sure
-	 * invalid modes passed in from userspace are rejected.
+	 * Also beware that userspace can request its own custom modes, neither
+	 * core nor helpers filter modes to the list of probe modes reported by
+	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
+	 * that modes are filtered consistently put any encoder constraints and
+	 * limits checks into @mode_valid.
 	 *
 	 * RETURNS:
 	 *
@@ -686,6 +741,12 @@ struct drm_encoder_helper_funcs {
 	 * state objects passed-in or assembled in the overall &drm_atomic_state
 	 * update tracking structure.
 	 *
+	 * Also beware that userspace can request its own custom modes, neither
+	 * core nor helpers filter modes to the list of probe modes reported by
+	 * the GETCONNECTOR IOCTL and stored in &drm_connector.modes. To ensure
+	 * that modes are filtered consistently put any encoder constraints and
+	 * limits checks into @mode_valid.
+	 *
 	 * RETURNS:
 	 *
 	 * 0 on success, -EINVAL if the state or the transition can't be
@@ -795,13 +856,20 @@ struct drm_connector_helper_funcs {
 	 * (which is usually derived from the EDID data block from the sink).
 	 * See e.g. drm_helper_probe_single_connector_modes().
 	 *
+	 * This function is optional.
+	 *
 	 * NOTE:
 	 *
 	 * This only filters the mode list supplied to userspace in the
-	 * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and
-	 * ask the kernel to use them. It this case the atomic helpers or legacy
-	 * CRTC helpers will not call this function. Drivers therefore must
-	 * still fully validate any mode passed in in a modeset request.
+	 * GETCONNECTOR IOCTL. Compared to &drm_encoder_helper_funcs.mode_valid,
+	 * &drm_crtc_helper_funcs.mode_valid and &drm_bridge_funcs.mode_valid,
+	 * which are also called by the atomic helpers from
+	 * drm_atomic_helper_check_modeset(). This allows userspace to force and
+	 * ignore sink constraint (like the pixel clock limits in the screen's
+	 * EDID), which is useful for e.g. testing, or working around a broken
+	 * EDID. Any source hardware constraint (which always need to be
+	 * enforced) therefore should be checked in one of the above callbacks,
+	 * and not this one here.
 	 *
 	 * To avoid races with concurrent connector state updates, the helper
 	 * libraries always call this with the &drm_mode_config.connection_mutex
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 4/6] drm: Use new mode_valid() helpers in connector probe helper
  2017-05-15  9:30       ` Daniel Vetter
@ 2017-05-15  9:51         ` Andrzej Hajda
  -1 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-15  9:51 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel, Carlos Palminha,
	Alexey Brodkin, Ville Syrjälä,
	Dave Airlie, Archit Taneja

On 15.05.2017 11:30, Daniel Vetter wrote:
> On Mon, May 15, 2017 at 10:39:35AM +0200, Andrzej Hajda wrote:
>> On 11.05.2017 11:06, Jose Abreu wrote:
>>> This changes the connector probe helper function to use the new
>>> encoder->mode_valid(), bridge->mode_valid() and crtc->mode_valid()
>>> helper callbacks to validate the modes.
>>>
>>> The new callbacks are optional so the behaviour remains the same
>>> if they are not implemented. If they are, then the code loops
>>> through all the connector's encodersXbridgesXcrtcs and calls the
>>> callback.
>>>
>>> If at least a valid encoderXbridgeXcrtc combination is found which
>>> accepts the mode then the function returns MODE_OK.
>>>
>>> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
>>> Cc: Carlos Palminha <palminha@synopsys.com>
>>> Cc: Alexey Brodkin <abrodkin@synopsys.com>
>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
>>> Cc: Dave Airlie <airlied@linux.ie>
>>> Cc: Andrzej Hajda <a.hajda@samsung.com>
>>> Cc: Archit Taneja <architt@codeaurora.org>
>>> ---
>>>
>>> Changes v2->v3:
>>> 	- Call also bridge->mode_valid (Daniel)
>>> Changes v1->v2:
>>> 	- Use new helpers suggested by Ville
>>> 	- Change documentation (Daniel)
>>>
>>>  drivers/gpu/drm/drm_probe_helper.c | 65 ++++++++++++++++++++++++++++++++++++--
>>>  1 file changed, 62 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
>>> index f01abdc..84d660e 100644
>>> --- a/drivers/gpu/drm/drm_probe_helper.c
>>> +++ b/drivers/gpu/drm/drm_probe_helper.c
>>> @@ -83,6 +83,61 @@
>>>  	return MODE_OK;
>>>  }
>>>  
>>> +static enum drm_mode_status
>>> +drm_mode_validate_connector(struct drm_connector *connector,
>>> +			    struct drm_display_mode *mode)
>>> +{
>>> +	struct drm_device *dev = connector->dev;
>>> +	uint32_t *ids = connector->encoder_ids;
>>> +	enum drm_mode_status ret = MODE_OK;
>>> +	unsigned int i;
>>> +
>>> +	/* Step 1: Validate against connector */
>>> +	ret = drm_connector_mode_valid(connector, mode);
>>> +	if (ret != MODE_OK)
>>> +		return ret;
>>> +
>>> +	/* Step 2: Validate against encoders and crtcs */
>>> +	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
>>> +		struct drm_encoder *encoder = drm_encoder_find(dev, ids[i]);
>>> +		struct drm_crtc *crtc;
>>> +
>>> +		if (!encoder)
>>> +			continue;
>>> +
>>> +		ret = drm_encoder_mode_valid(encoder, mode);
>>> +		if (ret != MODE_OK) {
>>> +			/* No point in continuing for crtc check as this encoder
>>> +			 * will not accept the mode anyway. If all encoders
>>> +			 * reject the mode then, at exit, ret will not be
>>> +			 * MODE_OK. */
>>> +			continue;
>>> +		}
>>> +
>>> +		ret = drm_bridge_mode_valid(encoder->bridge, mode);
>>> +		if (ret != MODE_OK) {
>>> +			/* There is also no point in continuing for crtc check
>>> +			 * here. */
>>> +			continue;
>>> +		}
>> Maybe it is a bikeshedding, but wouldn't be better to call
>> drm_bridge_mode_valid from drm_encoder_mode_valid, in general call all
>> bridge related stuff from corresponding encoder stuff?
>> This is more question about role of encoder->bridge, should it be
>> treated as encoder's extension, or as 1st class citizen in drm?
>>
>> Another concern is about order of calls, it is from sink to source, to
>> keep it consistent bridge should be called before encoder, am I right?
> For the atomic_check stuff (where we do change the passed-in mode) this
> would be correct, and calling order and layering would matter. But this
> just validates the mode in turn with everything, not taking any
> cross-component constraint or other configuration-dependent constraints
> into account. Hence it doesn't matter in which order we call stuff.
>
> Note that the passed-in mode is const, so you can't escape. And v3 of
> patch 1 now has added wording that you're not allowed to look at anything
> else dynamie either.
>
> Does that address your concern?

Yes, I know it practically does not matter. I have mistakenly written
"Beside this: R-b", it should be rather "Anyway: R-b" :)

Regards
Andrzej

> -Daniel
>
>> Beside this:
>> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
>>
>>  --
>> Regards
>> Andrzej
>>
>>> +
>>> +		drm_for_each_crtc(crtc, dev) {
>>> +			if (!drm_encoder_crtc_ok(encoder, crtc))
>>> +				continue;
>>> +
>>> +			ret = drm_crtc_mode_valid(crtc, mode);
>>> +			if (ret == MODE_OK) {
>>> +				/* If we get to this point there is at least
>>> +				 * one combination of encoder+crtc that works
>>> +				 * for this mode. Lets return now. */
>>> +				return ret;
>>> +			}
>>> +		}
>>> +	}
>>> +
>>> +	return ret;
>>> +}
>>> +
>>>  static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
>>>  {
>>>  	struct drm_cmdline_mode *cmdline_mode;
>>> @@ -322,7 +377,11 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
>>>   *    - drm_mode_validate_flag() checks the modes against basic connector
>>>   *      capabilities (interlace_allowed,doublescan_allowed,stereo_allowed)
>>>   *    - the optional &drm_connector_helper_funcs.mode_valid helper can perform
>>> - *      driver and/or hardware specific checks
>>> + *      driver and/or sink specific checks
>>> + *    - the optional &drm_crtc_helper_funcs.mode_valid,
>>> + *      &drm_bridge_funcs.mode_valid and &drm_encoder_helper_funcs.mode_valid
>>> + *      helpers can perform driver and/or source specific checks which are also
>>> + *      enforced by the modeset/atomic helpers
>>>   *
>>>   * 5. Any mode whose status is not OK is pruned from the connector's modes list,
>>>   *    accompanied by a debug message indicating the reason for the mode's
>>> @@ -466,8 +525,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
>>>  		if (mode->status == MODE_OK)
>>>  			mode->status = drm_mode_validate_flag(mode, mode_flags);
>>>  
>>> -		if (mode->status == MODE_OK && connector_funcs->mode_valid)
>>> -			mode->status = connector_funcs->mode_valid(connector,
>>> +		if (mode->status == MODE_OK)
>>> +			mode->status = drm_mode_validate_connector(connector,
>>>  								   mode);
>>>  	}
>>>  
>>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 4/6] drm: Use new mode_valid() helpers in connector probe helper
@ 2017-05-15  9:51         ` Andrzej Hajda
  0 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-15  9:51 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel, Carlos Palminha,
	Alexey Brodkin, Ville Syrjälä,
	Dave Airlie, Archit Taneja

On 15.05.2017 11:30, Daniel Vetter wrote:
> On Mon, May 15, 2017 at 10:39:35AM +0200, Andrzej Hajda wrote:
>> On 11.05.2017 11:06, Jose Abreu wrote:
>>> This changes the connector probe helper function to use the new
>>> encoder->mode_valid(), bridge->mode_valid() and crtc->mode_valid()
>>> helper callbacks to validate the modes.
>>>
>>> The new callbacks are optional so the behaviour remains the same
>>> if they are not implemented. If they are, then the code loops
>>> through all the connector's encodersXbridgesXcrtcs and calls the
>>> callback.
>>>
>>> If at least a valid encoderXbridgeXcrtc combination is found which
>>> accepts the mode then the function returns MODE_OK.
>>>
>>> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
>>> Cc: Carlos Palminha <palminha@synopsys.com>
>>> Cc: Alexey Brodkin <abrodkin@synopsys.com>
>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
>>> Cc: Dave Airlie <airlied@linux.ie>
>>> Cc: Andrzej Hajda <a.hajda@samsung.com>
>>> Cc: Archit Taneja <architt@codeaurora.org>
>>> ---
>>>
>>> Changes v2->v3:
>>> 	- Call also bridge->mode_valid (Daniel)
>>> Changes v1->v2:
>>> 	- Use new helpers suggested by Ville
>>> 	- Change documentation (Daniel)
>>>
>>>  drivers/gpu/drm/drm_probe_helper.c | 65 ++++++++++++++++++++++++++++++++++++--
>>>  1 file changed, 62 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
>>> index f01abdc..84d660e 100644
>>> --- a/drivers/gpu/drm/drm_probe_helper.c
>>> +++ b/drivers/gpu/drm/drm_probe_helper.c
>>> @@ -83,6 +83,61 @@
>>>  	return MODE_OK;
>>>  }
>>>  
>>> +static enum drm_mode_status
>>> +drm_mode_validate_connector(struct drm_connector *connector,
>>> +			    struct drm_display_mode *mode)
>>> +{
>>> +	struct drm_device *dev = connector->dev;
>>> +	uint32_t *ids = connector->encoder_ids;
>>> +	enum drm_mode_status ret = MODE_OK;
>>> +	unsigned int i;
>>> +
>>> +	/* Step 1: Validate against connector */
>>> +	ret = drm_connector_mode_valid(connector, mode);
>>> +	if (ret != MODE_OK)
>>> +		return ret;
>>> +
>>> +	/* Step 2: Validate against encoders and crtcs */
>>> +	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
>>> +		struct drm_encoder *encoder = drm_encoder_find(dev, ids[i]);
>>> +		struct drm_crtc *crtc;
>>> +
>>> +		if (!encoder)
>>> +			continue;
>>> +
>>> +		ret = drm_encoder_mode_valid(encoder, mode);
>>> +		if (ret != MODE_OK) {
>>> +			/* No point in continuing for crtc check as this encoder
>>> +			 * will not accept the mode anyway. If all encoders
>>> +			 * reject the mode then, at exit, ret will not be
>>> +			 * MODE_OK. */
>>> +			continue;
>>> +		}
>>> +
>>> +		ret = drm_bridge_mode_valid(encoder->bridge, mode);
>>> +		if (ret != MODE_OK) {
>>> +			/* There is also no point in continuing for crtc check
>>> +			 * here. */
>>> +			continue;
>>> +		}
>> Maybe it is a bikeshedding, but wouldn't be better to call
>> drm_bridge_mode_valid from drm_encoder_mode_valid, in general call all
>> bridge related stuff from corresponding encoder stuff?
>> This is more question about role of encoder->bridge, should it be
>> treated as encoder's extension, or as 1st class citizen in drm?
>>
>> Another concern is about order of calls, it is from sink to source, to
>> keep it consistent bridge should be called before encoder, am I right?
> For the atomic_check stuff (where we do change the passed-in mode) this
> would be correct, and calling order and layering would matter. But this
> just validates the mode in turn with everything, not taking any
> cross-component constraint or other configuration-dependent constraints
> into account. Hence it doesn't matter in which order we call stuff.
>
> Note that the passed-in mode is const, so you can't escape. And v3 of
> patch 1 now has added wording that you're not allowed to look at anything
> else dynamie either.
>
> Does that address your concern?

Yes, I know it practically does not matter. I have mistakenly written
"Beside this: R-b", it should be rather "Anyway: R-b" :)

Regards
Andrzej

> -Daniel
>
>> Beside this:
>> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
>>
>>  --
>> Regards
>> Andrzej
>>
>>> +
>>> +		drm_for_each_crtc(crtc, dev) {
>>> +			if (!drm_encoder_crtc_ok(encoder, crtc))
>>> +				continue;
>>> +
>>> +			ret = drm_crtc_mode_valid(crtc, mode);
>>> +			if (ret == MODE_OK) {
>>> +				/* If we get to this point there is at least
>>> +				 * one combination of encoder+crtc that works
>>> +				 * for this mode. Lets return now. */
>>> +				return ret;
>>> +			}
>>> +		}
>>> +	}
>>> +
>>> +	return ret;
>>> +}
>>> +
>>>  static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
>>>  {
>>>  	struct drm_cmdline_mode *cmdline_mode;
>>> @@ -322,7 +377,11 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
>>>   *    - drm_mode_validate_flag() checks the modes against basic connector
>>>   *      capabilities (interlace_allowed,doublescan_allowed,stereo_allowed)
>>>   *    - the optional &drm_connector_helper_funcs.mode_valid helper can perform
>>> - *      driver and/or hardware specific checks
>>> + *      driver and/or sink specific checks
>>> + *    - the optional &drm_crtc_helper_funcs.mode_valid,
>>> + *      &drm_bridge_funcs.mode_valid and &drm_encoder_helper_funcs.mode_valid
>>> + *      helpers can perform driver and/or source specific checks which are also
>>> + *      enforced by the modeset/atomic helpers
>>>   *
>>>   * 5. Any mode whose status is not OK is pruned from the connector's modes list,
>>>   *    accompanied by a debug message indicating the reason for the mode's
>>> @@ -466,8 +525,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
>>>  		if (mode->status == MODE_OK)
>>>  			mode->status = drm_mode_validate_flag(mode, mode_flags);
>>>  
>>> -		if (mode->status == MODE_OK && connector_funcs->mode_valid)
>>> -			mode->status = connector_funcs->mode_valid(connector,
>>> +		if (mode->status == MODE_OK)
>>> +			mode->status = drm_mode_validate_connector(connector,
>>>  								   mode);
>>>  	}
>>>  
>>

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback
  2017-05-15  8:53     ` Daniel Vetter
@ 2017-05-15 15:52       ` Daniel Vetter
  -1 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15 15:52 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel, Carlos Palminha,
	Alexey Brodkin, Ville Syrjälä,
	Dave Airlie, Andrzej Hajda, Archit Taneja

On Mon, May 15, 2017 at 10:53:25AM +0200, Daniel Vetter wrote:
> On Thu, May 11, 2017 at 10:06:02AM +0100, Jose Abreu wrote:
> > Now that we have a callback to check if crtc supports a given mode
> > we can use it in arcpgu so that we restrict the number of probbed
> > modes to the ones we can actually display.
> > 
> > This is specially useful because arcpgu crtc is responsible to set
> > a clock value in the commit() stage but unfortunatelly this clock
> > does not support all the needed ranges.
> > 
> > Also, remove the atomic_check() callback as mode_valid() callback
> > will be called before.
> > 
> > Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> > Cc: Carlos Palminha <palminha@synopsys.com>
> > Cc: Alexey Brodkin <abrodkin@synopsys.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Dave Airlie <airlied@linux.ie>
> > Cc: Andrzej Hajda <a.hajda@samsung.com>
> > Cc: Archit Taneja <architt@codeaurora.org>
> 
> Btw for justifying your patch series a bit more, would be real sweet to
> roll ->mode_valid out to more drivers. I see two easy cases:
> 
> bridge/analogix-anx78xx.c: has a simple mode_fixup which really is just a
> mode_valid callback
> 
> bridge/synopsys/dw-hdmi.c: simply hand-rolls what you've done here, we
> could move the connector_mode valid to the bridge and done.
> 
> Care to type these 2 patches on top, just to make this a bit more useful
> and a clearer case for merging?

Aside: There's a pile more drivers (encoders and crtc drivers) which would
similarly benefit and dont really look like they'd be hard to patch up:
- malidp_crtc_mode_fixup
- armada_drm_crtc_mode_fixup (armada isn't atomic, so forget this one)
- atmel_hlcdc_crtc_mode_fixup
- hdmi_mode_fixup in exynos_hdmi.c
- vc4_crtc_mode_fixup and vc4_dpi_encoder_mode_fixup (they both just check
  for interlaced modes, we could probably dump the same check in
  connector->mode_valid).

Plus the 2 bridge drivers. Everyone else does either something more
complex, or something that's not quite correct.
-Daniel

> 
> Thanks, Daniel
> 
> > ---
> >  drivers/gpu/drm/arc/arcpgu_crtc.c | 39 ++++++++++++++++++++++++---------------
> >  1 file changed, 24 insertions(+), 15 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
> > index ad9a959..01cae0a 100644
> > --- a/drivers/gpu/drm/arc/arcpgu_crtc.c
> > +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
> > @@ -32,6 +32,18 @@
> >  	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
> >  };
> >  
> > +static bool arc_pgu_is_mode_valid(struct arcpgu_drm_private *arcpgu,
> > +				  const struct drm_display_mode *mode)
> > +{
> > +	long rate, clk_rate = mode->clock * 1000;
> > +
> > +	rate = clk_round_rate(arcpgu->clk, clk_rate);
> > +	if (rate != clk_rate)
> > +		return false;
> > +
> > +	return true;
> > +}
> > +
> >  static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
> >  {
> >  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> > @@ -64,6 +76,17 @@ static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
> >  	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> >  };
> >  
> > +enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc,
> > +					     const struct drm_display_mode *mode)
> > +{
> > +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> > +
> > +	if (!arc_pgu_is_mode_valid(arcpgu, mode))
> > +		return MODE_NOCLOCK;
> > +
> > +	return MODE_OK;
> > +}
> > +
> >  static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
> >  {
> >  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> > @@ -129,20 +152,6 @@ static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
> >  			      ~ARCPGU_CTRL_ENABLE_MASK);
> >  }
> >  
> > -static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
> > -				     struct drm_crtc_state *state)
> > -{
> > -	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> > -	struct drm_display_mode *mode = &state->adjusted_mode;
> > -	long rate, clk_rate = mode->clock * 1000;
> > -
> > -	rate = clk_round_rate(arcpgu->clk, clk_rate);
> > -	if (rate != clk_rate)
> > -		return -EINVAL;
> > -
> > -	return 0;
> > -}
> > -
> >  static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
> >  				      struct drm_crtc_state *state)
> >  {
> > @@ -158,6 +167,7 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
> >  }
> >  
> >  static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
> > +	.mode_valid	= arc_pgu_crtc_mode_valid,
> >  	.mode_set	= drm_helper_crtc_mode_set,
> >  	.mode_set_base	= drm_helper_crtc_mode_set_base,
> >  	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
> > @@ -165,7 +175,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
> >  	.disable	= arc_pgu_crtc_disable,
> >  	.prepare	= arc_pgu_crtc_disable,
> >  	.commit		= arc_pgu_crtc_enable,
> > -	.atomic_check	= arc_pgu_crtc_atomic_check,
> >  	.atomic_begin	= arc_pgu_crtc_atomic_begin,
> >  };
> >  
> > -- 
> > 1.9.1
> > 
> > 
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback
@ 2017-05-15 15:52       ` Daniel Vetter
  0 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2017-05-15 15:52 UTC (permalink / raw)
  To: Jose Abreu, dri-devel, linux-kernel, Carlos Palminha,
	Alexey Brodkin, Ville Syrjälä,
	Dave Airlie, Andrzej Hajda, Archit Taneja

On Mon, May 15, 2017 at 10:53:25AM +0200, Daniel Vetter wrote:
> On Thu, May 11, 2017 at 10:06:02AM +0100, Jose Abreu wrote:
> > Now that we have a callback to check if crtc supports a given mode
> > we can use it in arcpgu so that we restrict the number of probbed
> > modes to the ones we can actually display.
> > 
> > This is specially useful because arcpgu crtc is responsible to set
> > a clock value in the commit() stage but unfortunatelly this clock
> > does not support all the needed ranges.
> > 
> > Also, remove the atomic_check() callback as mode_valid() callback
> > will be called before.
> > 
> > Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> > Cc: Carlos Palminha <palminha@synopsys.com>
> > Cc: Alexey Brodkin <abrodkin@synopsys.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Dave Airlie <airlied@linux.ie>
> > Cc: Andrzej Hajda <a.hajda@samsung.com>
> > Cc: Archit Taneja <architt@codeaurora.org>
> 
> Btw for justifying your patch series a bit more, would be real sweet to
> roll ->mode_valid out to more drivers. I see two easy cases:
> 
> bridge/analogix-anx78xx.c: has a simple mode_fixup which really is just a
> mode_valid callback
> 
> bridge/synopsys/dw-hdmi.c: simply hand-rolls what you've done here, we
> could move the connector_mode valid to the bridge and done.
> 
> Care to type these 2 patches on top, just to make this a bit more useful
> and a clearer case for merging?

Aside: There's a pile more drivers (encoders and crtc drivers) which would
similarly benefit and dont really look like they'd be hard to patch up:
- malidp_crtc_mode_fixup
- armada_drm_crtc_mode_fixup (armada isn't atomic, so forget this one)
- atmel_hlcdc_crtc_mode_fixup
- hdmi_mode_fixup in exynos_hdmi.c
- vc4_crtc_mode_fixup and vc4_dpi_encoder_mode_fixup (they both just check
  for interlaced modes, we could probably dump the same check in
  connector->mode_valid).

Plus the 2 bridge drivers. Everyone else does either something more
complex, or something that's not quite correct.
-Daniel

> 
> Thanks, Daniel
> 
> > ---
> >  drivers/gpu/drm/arc/arcpgu_crtc.c | 39 ++++++++++++++++++++++++---------------
> >  1 file changed, 24 insertions(+), 15 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
> > index ad9a959..01cae0a 100644
> > --- a/drivers/gpu/drm/arc/arcpgu_crtc.c
> > +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
> > @@ -32,6 +32,18 @@
> >  	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
> >  };
> >  
> > +static bool arc_pgu_is_mode_valid(struct arcpgu_drm_private *arcpgu,
> > +				  const struct drm_display_mode *mode)
> > +{
> > +	long rate, clk_rate = mode->clock * 1000;
> > +
> > +	rate = clk_round_rate(arcpgu->clk, clk_rate);
> > +	if (rate != clk_rate)
> > +		return false;
> > +
> > +	return true;
> > +}
> > +
> >  static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
> >  {
> >  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> > @@ -64,6 +76,17 @@ static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
> >  	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> >  };
> >  
> > +enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc,
> > +					     const struct drm_display_mode *mode)
> > +{
> > +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> > +
> > +	if (!arc_pgu_is_mode_valid(arcpgu, mode))
> > +		return MODE_NOCLOCK;
> > +
> > +	return MODE_OK;
> > +}
> > +
> >  static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
> >  {
> >  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> > @@ -129,20 +152,6 @@ static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
> >  			      ~ARCPGU_CTRL_ENABLE_MASK);
> >  }
> >  
> > -static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
> > -				     struct drm_crtc_state *state)
> > -{
> > -	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
> > -	struct drm_display_mode *mode = &state->adjusted_mode;
> > -	long rate, clk_rate = mode->clock * 1000;
> > -
> > -	rate = clk_round_rate(arcpgu->clk, clk_rate);
> > -	if (rate != clk_rate)
> > -		return -EINVAL;
> > -
> > -	return 0;
> > -}
> > -
> >  static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
> >  				      struct drm_crtc_state *state)
> >  {
> > @@ -158,6 +167,7 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
> >  }
> >  
> >  static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
> > +	.mode_valid	= arc_pgu_crtc_mode_valid,
> >  	.mode_set	= drm_helper_crtc_mode_set,
> >  	.mode_set_base	= drm_helper_crtc_mode_set_base,
> >  	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
> > @@ -165,7 +175,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
> >  	.disable	= arc_pgu_crtc_disable,
> >  	.prepare	= arc_pgu_crtc_disable,
> >  	.commit		= arc_pgu_crtc_enable,
> > -	.atomic_check	= arc_pgu_crtc_atomic_check,
> >  	.atomic_begin	= arc_pgu_crtc_atomic_begin,
> >  };
> >  
> > -- 
> > 1.9.1
> > 
> > 
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback
  2017-05-15 15:52       ` Daniel Vetter
@ 2017-05-15 23:55         ` Jose Abreu
  -1 siblings, 0 replies; 46+ messages in thread
From: Jose Abreu @ 2017-05-15 23:55 UTC (permalink / raw)
  To: dri-devel, Daniel Vetter
  Cc: Jose Abreu, linux-kernel, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Dave Airlie, Andrzej Hajda, Archit Taneja

Hi Daniel,


On 15-05-2017 16:52, Daniel Vetter wrote:
> On Mon, May 15, 2017 at 10:53:25AM +0200, Daniel Vetter wrote:
>> On Thu, May 11, 2017 at 10:06:02AM +0100, Jose Abreu wrote:
>>> Now that we have a callback to check if crtc supports a given mode
>>> we can use it in arcpgu so that we restrict the number of probbed
>>> modes to the ones we can actually display.
>>>
>>> This is specially useful because arcpgu crtc is responsible to set
>>> a clock value in the commit() stage but unfortunatelly this clock
>>> does not support all the needed ranges.
>>>
>>> Also, remove the atomic_check() callback as mode_valid() callback
>>> will be called before.
>>>
>>> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
>>> Cc: Carlos Palminha <palminha@synopsys.com>
>>> Cc: Alexey Brodkin <abrodkin@synopsys.com>
>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
>>> Cc: Dave Airlie <airlied@linux.ie>
>>> Cc: Andrzej Hajda <a.hajda@samsung.com>
>>> Cc: Archit Taneja <architt@codeaurora.org>
>> Btw for justifying your patch series a bit more, would be real sweet to
>> roll ->mode_valid out to more drivers. I see two easy cases:
>>
>> bridge/analogix-anx78xx.c: has a simple mode_fixup which really is just a
>> mode_valid callback
>>
>> bridge/synopsys/dw-hdmi.c: simply hand-rolls what you've done here, we
>> could move the connector_mode valid to the bridge and done.
>>
>> Care to type these 2 patches on top, just to make this a bit more useful
>> and a clearer case for merging?
> Aside: There's a pile more drivers (encoders and crtc drivers) which would
> similarly benefit and dont really look like they'd be hard to patch up:
> - malidp_crtc_mode_fixup
> - armada_drm_crtc_mode_fixup (armada isn't atomic, so forget this one)
> - atmel_hlcdc_crtc_mode_fixup
> - hdmi_mode_fixup in exynos_hdmi.c
> - vc4_crtc_mode_fixup and vc4_dpi_encoder_mode_fixup (they both just check
>   for interlaced modes, we could probably dump the same check in
>   connector->mode_valid).
>
> Plus the 2 bridge drivers. Everyone else does either something more
> complex, or something that's not quite correct.
> -Daniel

Sorry for being silent but I am away from office this week. I
will try to evaluate and add this in next version. In the
meantime I will review the documentation patches you sent. Thanks!

Best regards,
Jose Miguel Abreu

>
>> Thanks, Daniel
>>
>>> ---
>>>  drivers/gpu/drm/arc/arcpgu_crtc.c | 39 ++++++++++++++++++++++++---------------
>>>  1 file changed, 24 insertions(+), 15 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
>>> index ad9a959..01cae0a 100644
>>> --- a/drivers/gpu/drm/arc/arcpgu_crtc.c
>>> +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
>>> @@ -32,6 +32,18 @@
>>>  	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
>>>  };
>>>  
>>> +static bool arc_pgu_is_mode_valid(struct arcpgu_drm_private *arcpgu,
>>> +				  const struct drm_display_mode *mode)
>>> +{
>>> +	long rate, clk_rate = mode->clock * 1000;
>>> +
>>> +	rate = clk_round_rate(arcpgu->clk, clk_rate);
>>> +	if (rate != clk_rate)
>>> +		return false;
>>> +
>>> +	return true;
>>> +}
>>> +
>>>  static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
>>>  {
>>>  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
>>> @@ -64,6 +76,17 @@ static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
>>>  	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
>>>  };
>>>  
>>> +enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc,
>>> +					     const struct drm_display_mode *mode)
>>> +{
>>> +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
>>> +
>>> +	if (!arc_pgu_is_mode_valid(arcpgu, mode))
>>> +		return MODE_NOCLOCK;
>>> +
>>> +	return MODE_OK;
>>> +}
>>> +
>>>  static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
>>>  {
>>>  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
>>> @@ -129,20 +152,6 @@ static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
>>>  			      ~ARCPGU_CTRL_ENABLE_MASK);
>>>  }
>>>  
>>> -static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
>>> -				     struct drm_crtc_state *state)
>>> -{
>>> -	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
>>> -	struct drm_display_mode *mode = &state->adjusted_mode;
>>> -	long rate, clk_rate = mode->clock * 1000;
>>> -
>>> -	rate = clk_round_rate(arcpgu->clk, clk_rate);
>>> -	if (rate != clk_rate)
>>> -		return -EINVAL;
>>> -
>>> -	return 0;
>>> -}
>>> -
>>>  static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>>>  				      struct drm_crtc_state *state)
>>>  {
>>> @@ -158,6 +167,7 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>>>  }
>>>  
>>>  static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
>>> +	.mode_valid	= arc_pgu_crtc_mode_valid,
>>>  	.mode_set	= drm_helper_crtc_mode_set,
>>>  	.mode_set_base	= drm_helper_crtc_mode_set_base,
>>>  	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
>>> @@ -165,7 +175,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>>>  	.disable	= arc_pgu_crtc_disable,
>>>  	.prepare	= arc_pgu_crtc_disable,
>>>  	.commit		= arc_pgu_crtc_enable,
>>> -	.atomic_check	= arc_pgu_crtc_atomic_check,
>>>  	.atomic_begin	= arc_pgu_crtc_atomic_begin,
>>>  };
>>>  
>>> -- 
>>> 1.9.1
>>>
>>>
>> -- 
>> Daniel Vetter
>> Software Engineer, Intel Corporation
>> https://urldefense.proofpoint.com/v2/url?u=http-3A__blog.ffwll.ch&d=DwIGaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=yaVFU4TjGY0gVF8El1uKcisy6TPsyCl9uN7Wsis-qhY&m=v9tZNfdrkm8mrAlJyEpm71Te7tDReAFXijS23BkDSTo&s=Y6DG3RpFLs0nomQ09FA3hqCqq6MQ3dvG81s_2XlVytM&e= 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback
@ 2017-05-15 23:55         ` Jose Abreu
  0 siblings, 0 replies; 46+ messages in thread
From: Jose Abreu @ 2017-05-15 23:55 UTC (permalink / raw)
  To: dri-devel, Daniel Vetter
  Cc: Jose Abreu, linux-kernel, Carlos Palminha, Alexey Brodkin,
	Ville Syrjälä,
	Dave Airlie, Andrzej Hajda, Archit Taneja

Hi Daniel,


On 15-05-2017 16:52, Daniel Vetter wrote:
> On Mon, May 15, 2017 at 10:53:25AM +0200, Daniel Vetter wrote:
>> On Thu, May 11, 2017 at 10:06:02AM +0100, Jose Abreu wrote:
>>> Now that we have a callback to check if crtc supports a given mode
>>> we can use it in arcpgu so that we restrict the number of probbed
>>> modes to the ones we can actually display.
>>>
>>> This is specially useful because arcpgu crtc is responsible to set
>>> a clock value in the commit() stage but unfortunatelly this clock
>>> does not support all the needed ranges.
>>>
>>> Also, remove the atomic_check() callback as mode_valid() callback
>>> will be called before.
>>>
>>> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
>>> Cc: Carlos Palminha <palminha@synopsys.com>
>>> Cc: Alexey Brodkin <abrodkin@synopsys.com>
>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
>>> Cc: Dave Airlie <airlied@linux.ie>
>>> Cc: Andrzej Hajda <a.hajda@samsung.com>
>>> Cc: Archit Taneja <architt@codeaurora.org>
>> Btw for justifying your patch series a bit more, would be real sweet to
>> roll ->mode_valid out to more drivers. I see two easy cases:
>>
>> bridge/analogix-anx78xx.c: has a simple mode_fixup which really is just a
>> mode_valid callback
>>
>> bridge/synopsys/dw-hdmi.c: simply hand-rolls what you've done here, we
>> could move the connector_mode valid to the bridge and done.
>>
>> Care to type these 2 patches on top, just to make this a bit more useful
>> and a clearer case for merging?
> Aside: There's a pile more drivers (encoders and crtc drivers) which would
> similarly benefit and dont really look like they'd be hard to patch up:
> - malidp_crtc_mode_fixup
> - armada_drm_crtc_mode_fixup (armada isn't atomic, so forget this one)
> - atmel_hlcdc_crtc_mode_fixup
> - hdmi_mode_fixup in exynos_hdmi.c
> - vc4_crtc_mode_fixup and vc4_dpi_encoder_mode_fixup (they both just check
>   for interlaced modes, we could probably dump the same check in
>   connector->mode_valid).
>
> Plus the 2 bridge drivers. Everyone else does either something more
> complex, or something that's not quite correct.
> -Daniel

Sorry for being silent but I am away from office this week. I
will try to evaluate and add this in next version. In the
meantime I will review the documentation patches you sent. Thanks!

Best regards,
Jose Miguel Abreu

>
>> Thanks, Daniel
>>
>>> ---
>>>  drivers/gpu/drm/arc/arcpgu_crtc.c | 39 ++++++++++++++++++++++++---------------
>>>  1 file changed, 24 insertions(+), 15 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c
>>> index ad9a959..01cae0a 100644
>>> --- a/drivers/gpu/drm/arc/arcpgu_crtc.c
>>> +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c
>>> @@ -32,6 +32,18 @@
>>>  	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
>>>  };
>>>  
>>> +static bool arc_pgu_is_mode_valid(struct arcpgu_drm_private *arcpgu,
>>> +				  const struct drm_display_mode *mode)
>>> +{
>>> +	long rate, clk_rate = mode->clock * 1000;
>>> +
>>> +	rate = clk_round_rate(arcpgu->clk, clk_rate);
>>> +	if (rate != clk_rate)
>>> +		return false;
>>> +
>>> +	return true;
>>> +}
>>> +
>>>  static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
>>>  {
>>>  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
>>> @@ -64,6 +76,17 @@ static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
>>>  	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
>>>  };
>>>  
>>> +enum drm_mode_status arc_pgu_crtc_mode_valid(struct drm_crtc *crtc,
>>> +					     const struct drm_display_mode *mode)
>>> +{
>>> +	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
>>> +
>>> +	if (!arc_pgu_is_mode_valid(arcpgu, mode))
>>> +		return MODE_NOCLOCK;
>>> +
>>> +	return MODE_OK;
>>> +}
>>> +
>>>  static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
>>>  {
>>>  	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
>>> @@ -129,20 +152,6 @@ static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
>>>  			      ~ARCPGU_CTRL_ENABLE_MASK);
>>>  }
>>>  
>>> -static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
>>> -				     struct drm_crtc_state *state)
>>> -{
>>> -	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
>>> -	struct drm_display_mode *mode = &state->adjusted_mode;
>>> -	long rate, clk_rate = mode->clock * 1000;
>>> -
>>> -	rate = clk_round_rate(arcpgu->clk, clk_rate);
>>> -	if (rate != clk_rate)
>>> -		return -EINVAL;
>>> -
>>> -	return 0;
>>> -}
>>> -
>>>  static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>>>  				      struct drm_crtc_state *state)
>>>  {
>>> @@ -158,6 +167,7 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>>>  }
>>>  
>>>  static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
>>> +	.mode_valid	= arc_pgu_crtc_mode_valid,
>>>  	.mode_set	= drm_helper_crtc_mode_set,
>>>  	.mode_set_base	= drm_helper_crtc_mode_set_base,
>>>  	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
>>> @@ -165,7 +175,6 @@ static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
>>>  	.disable	= arc_pgu_crtc_disable,
>>>  	.prepare	= arc_pgu_crtc_disable,
>>>  	.commit		= arc_pgu_crtc_enable,
>>> -	.atomic_check	= arc_pgu_crtc_atomic_check,
>>>  	.atomic_begin	= arc_pgu_crtc_atomic_begin,
>>>  };
>>>  
>>> -- 
>>> 1.9.1
>>>
>>>
>> -- 
>> Daniel Vetter
>> Software Engineer, Intel Corporation
>> https://urldefense.proofpoint.com/v2/url?u=http-3A__blog.ffwll.ch&d=DwIGaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=yaVFU4TjGY0gVF8El1uKcisy6TPsyCl9uN7Wsis-qhY&m=v9tZNfdrkm8mrAlJyEpm71Te7tDReAFXijS23BkDSTo&s=Y6DG3RpFLs0nomQ09FA3hqCqq6MQ3dvG81s_2XlVytM&e= 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better
  2017-05-15  9:11     ` [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better Daniel Vetter
  2017-05-15  9:11       ` [PATCH 2/2] drm/doc: Clarify mode_fixup vs. atomic_check a bit more Daniel Vetter
@ 2017-05-16  2:38       ` Jose Abreu
  2017-05-16 13:17       ` Andrzej Hajda
  2 siblings, 0 replies; 46+ messages in thread
From: Jose Abreu @ 2017-05-16  2:38 UTC (permalink / raw)
  To: Daniel Vetter, DRI Development
  Cc: Jose Abreu, Daniel Vetter, Laurent Pinchart

Hi Daniel,


On 15-05-2017 10:11, Daniel Vetter wrote:
> Laurent started a massive discussion on IRC about this. Let's try to
> document common usage a bit better.
>
> v2: Cross-links+typos.
>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <Jose.Abreu@synopsys.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Jose Abreu <joabreu@synopsys.com>

Best regards,
Jose Miguel Abreu

> ---
>  include/drm/drm_bridge.h                 |  2 +-
>  include/drm/drm_crtc.h                   | 28 +++++++++++++++++++++++++---
>  include/drm/drm_modeset_helper_vtables.h |  6 ++++--
>  3 files changed, 30 insertions(+), 6 deletions(-)
>
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index f694de756ecf..f3ad38d0d621 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -91,7 +91,7 @@ struct drm_bridge_funcs {
>  	 * the display chain, either the final &drm_connector or the next
>  	 * &drm_bridge. The parameter adjusted_mode is the input mode the bridge
>  	 * requires. It can be modified by this callback and does not need to
> -	 * match mode.
> +	 * match mode. See also &drm_crtc_state.adjusted_mode for more details.
>  	 *
>  	 * This is the only hook that allows a bridge to reject a modeset. If
>  	 * this function passes all other callbacks must succeed for this
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 06236b002c22..5f5d53973ca5 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -90,8 +90,6 @@ struct drm_plane_helper_funcs;
>   * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
>   * @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors
>   * @encoder_mask: bitmask of (1 << drm_encoder_index(encoder)) of attached encoders
> - * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings
> - * @mode: current mode timings
>   * @mode_blob: &drm_property_blob for @mode
>   * @state: backpointer to global drm_atomic_state
>   *
> @@ -131,9 +129,33 @@ struct drm_crtc_state {
>  	u32 connector_mask;
>  	u32 encoder_mask;
>  
> -	/* adjusted_mode: for use by helpers and drivers */
> +	/**
> +	 * @adjusted_mode:
> +	 *
> +	 * Internal display timings which can be used by the driver to handle
> +	 * differences between the mode requested by userspace in @mode and what
> +	 * is actually programmed into the hardware. It is purely driver
> +	 * implementation defined what exactly this adjusted mode means. Usually
> +	 * it is used to store the hardware display timings used between the
> +	 * CRTC and encoder blocks.
> +	 */
>  	struct drm_display_mode adjusted_mode;
>  
> +	/**
> +	 * @mode:
> +	 *
> +	 * Display timings requested by userspace. The driver should try to
> +	 * match the refresh rate as close as possible (but note that it's
> +	 * undefined what exactly is close enough, e.g. some of the HDMI modes
> +	 * only differ in less than 1% of the refresh rate). The active width
> +	 * and height as observed by userspace for positioning planes must match
> +	 * exactly.
> +	 *
> +	 * For external connectors where the sink isn't fixed (like with a
> +	 * built-in panel), this mode here should match the physical mode on the
> +	 * wire to the last details (i.e. including sync polarities and
> +	 * everything).
> +	 */
>  	struct drm_display_mode mode;
>  
>  	/* blob property to expose current mode to atomic userspace */
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index 91d071ff1232..c72fca544a41 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -138,7 +138,8 @@ struct drm_crtc_helper_funcs {
>  	 * encoders need to be fed with. Note that this is the inverse semantics
>  	 * of the meaning for the &drm_encoder and &drm_bridge_funcs.mode_fixup
>  	 * vfunc. If the CRTC cannot support the requested conversion from mode
> -	 * to adjusted_mode it should reject the modeset.
> +	 * to adjusted_mode it should reject the modeset. See also
> +	 * &drm_crtc_state.adjusted_mode for more details.
>  	 *
>  	 * This function is used by both legacy CRTC helpers and atomic helpers.
>  	 * With atomic helpers it is optional.
> @@ -510,7 +511,8 @@ struct drm_encoder_helper_funcs {
>  	 * mode is the display mode that should be fed to the next element in
>  	 * the display chain, either the final &drm_connector or a &drm_bridge.
>  	 * The parameter adjusted_mode is the input mode the encoder requires. It
> -	 * can be modified by this callback and does not need to match mode.
> +	 * can be modified by this callback and does not need to match mode. See
> +	 * also &drm_crtc_state.adjusted_mode for more details.
>  	 *
>  	 * This function is used by both legacy CRTC helpers and atomic helpers.
>  	 * This hook is optional.

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH 2/2] drm/doc: Clarify mode_fixup vs. atomic_check a bit more
  2017-05-15  9:11       ` [PATCH 2/2] drm/doc: Clarify mode_fixup vs. atomic_check a bit more Daniel Vetter
@ 2017-05-16  2:41         ` Jose Abreu
  2017-05-16 13:14         ` Andrzej Hajda
  1 sibling, 0 replies; 46+ messages in thread
From: Jose Abreu @ 2017-05-16  2:41 UTC (permalink / raw)
  To: Daniel Vetter, DRI Development
  Cc: Jose Abreu, Laurent Pinchart, Daniel Vetter

Hi Daniel,


On 15-05-2017 10:11, Daniel Vetter wrote:
> Brought up by both Laurent and Andrzej when reviewing the new
> ->mode_valid hooks. Since mode_fixup is just a simpler version of the
> much more generic atomic_check we can't really unify it with
> mode_valid. Most drivers should probably switch their current
> mode_fixup code to either the new mode_valid or the atomic_check
> hooks, but e.g. that doesn't exist yet for bridges, and for CRTCs the
> situation is a bit more complicated. Hence there's no clear
> equivalence between mode_fixup and mode_valid, even if it looks like
> that at first glance.
>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Cc: Jose Abreu <Jose.Abreu@synopsys.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Jose Abreu <joabreu@synopsys.com>

Best regards,
Jose Miguel Abreu

> ---
>  include/drm/drm_modeset_helper_vtables.h | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index c72fca544a41..613b2a602b77 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -156,7 +156,11 @@ struct drm_crtc_helper_funcs {
>  	 * allowed.
>  	 *
>  	 * Atomic drivers which need to inspect and adjust more state should
> -	 * instead use the @atomic_check callback.
> +	 * instead use the @atomic_check callback, but note that they're not
> +	 * perfectly equivalent: @mode_valid is called from
> +	 * drm_atomic_helper_check_modeset(), but @atomic_check is called from
> +	 * drm_atomic_helper_check_planes(), because originally it was meant for
> +	 * plane update checks only..
>  	 *
>  	 * Also beware that userspace can request its own custom modes, neither
>  	 * core nor helpers filter modes to the list of probe modes reported by
> @@ -529,7 +533,9 @@ struct drm_encoder_helper_funcs {
>  	 * allowed.
>  	 *
>  	 * Atomic drivers which need to inspect and adjust more state should
> -	 * instead use the @atomic_check callback.
> +	 * instead use the @atomic_check callback. If @atomic_check is used,
> +	 * this hook isn't called since @atomic_check allows a strict superset
> +	 * of the functionality of @mode_fixup.
>  	 *
>  	 * Also beware that userspace can request its own custom modes, neither
>  	 * core nor helpers filter modes to the list of probe modes reported by
> @@ -716,6 +722,11 @@ struct drm_encoder_helper_funcs {
>  	 * update the CRTC to match what the encoder needs for the requested
>  	 * connector.
>  	 *
> +	 * Since this provides a strict superset of the functionality of
> +	 * @mode_fixup (the requested and adjusted modes are both available
> +	 * through the passed in &struct drm_crtc_state) @mode_fixup is not
> +	 * called when @atomic_check is implemented.
> +	 *
>  	 * This function is used by the atomic helpers, but it is optional.
>  	 *
>  	 * NOTE:

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH 2/2] drm/doc: Clarify mode_fixup vs. atomic_check a bit more
  2017-05-15  9:11       ` [PATCH 2/2] drm/doc: Clarify mode_fixup vs. atomic_check a bit more Daniel Vetter
  2017-05-16  2:41         ` Jose Abreu
@ 2017-05-16 13:14         ` Andrzej Hajda
  1 sibling, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-16 13:14 UTC (permalink / raw)
  To: Daniel Vetter, DRI Development
  Cc: Jose Abreu, Daniel Vetter, Laurent Pinchart

On 15.05.2017 11:11, Daniel Vetter wrote:
> Brought up by both Laurent and Andrzej when reviewing the new
> ->mode_valid hooks. Since mode_fixup is just a simpler version of the
> much more generic atomic_check we can't really unify it with
> mode_valid. Most drivers should probably switch their current
> mode_fixup code to either the new mode_valid or the atomic_check
> hooks, but e.g. that doesn't exist yet for bridges, and for CRTCs the
> situation is a bit more complicated. Hence there's no clear
> equivalence between mode_fixup and mode_valid, even if it looks like
> that at first glance.
>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Cc: Jose Abreu <Jose.Abreu@synopsys.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
>  include/drm/drm_modeset_helper_vtables.h | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index c72fca544a41..613b2a602b77 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -156,7 +156,11 @@ struct drm_crtc_helper_funcs {
>  	 * allowed.
>  	 *
>  	 * Atomic drivers which need to inspect and adjust more state should
> -	 * instead use the @atomic_check callback.
> +	 * instead use the @atomic_check callback, but note that they're not
> +	 * perfectly equivalent: @mode_valid is called from
> +	 * drm_atomic_helper_check_modeset(), but @atomic_check is called from
> +	 * drm_atomic_helper_check_planes(), because originally it was meant for
> +	 * plane update checks only..

Two dots.

Beside this:
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej

>  	 *
>  	 * Also beware that userspace can request its own custom modes, neither
>  	 * core nor helpers filter modes to the list of probe modes reported by
> @@ -529,7 +533,9 @@ struct drm_encoder_helper_funcs {
>  	 * allowed.
>  	 *
>  	 * Atomic drivers which need to inspect and adjust more state should
> -	 * instead use the @atomic_check callback.
> +	 * instead use the @atomic_check callback. If @atomic_check is used,
> +	 * this hook isn't called since @atomic_check allows a strict superset
> +	 * of the functionality of @mode_fixup.
>  	 *
>  	 * Also beware that userspace can request its own custom modes, neither
>  	 * core nor helpers filter modes to the list of probe modes reported by
> @@ -716,6 +722,11 @@ struct drm_encoder_helper_funcs {
>  	 * update the CRTC to match what the encoder needs for the requested
>  	 * connector.
>  	 *
> +	 * Since this provides a strict superset of the functionality of
> +	 * @mode_fixup (the requested and adjusted modes are both available
> +	 * through the passed in &struct drm_crtc_state) @mode_fixup is not
> +	 * called when @atomic_check is implemented.
> +	 *
>  	 * This function is used by the atomic helpers, but it is optional.
>  	 *
>  	 * NOTE:


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks
  2017-05-15  9:33     ` [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks Daniel Vetter
@ 2017-05-16 13:15       ` Andrzej Hajda
  0 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-16 13:15 UTC (permalink / raw)
  To: Daniel Vetter, DRI Development
  Cc: Jose Abreu, Alexey Brodkin, Jose Abreu, Laurent Pinchart,
	Carlos Palminha

On 15.05.2017 11:33, Daniel Vetter wrote:
> From: Jose Abreu <Jose.Abreu@synopsys.com>
>
> This adds a new callback to crtc, encoder and bridge helper functions
> called mode_valid(). This callback shall be implemented if the
> corresponding component has some sort of restriction in the modes
> that can be displayed. A NULL callback implicates that the component
> can display all the modes.
>
> We also change the documentation so that the new and old callbacks
> are correctly documented.
>
> Only the callbacks were implemented to simplify review process,
> following patches will make use of them.
>
> Changes in v2 from Daniel:
> - Update the warning about how modes aren't filtered in atomic_check -
>   the heleprs help out a lot more now.
> - Consistenly roll out that warning, crtc/encoder's atomic_check
>   missed it.
> - Sprinkle more links all over the place, so it's easier to see where
>   this stuff is used and how the differen hooks are related.
> - Note that ->mode_valid is optional everywhere.
> - Explain why the connector's mode_valid is special and does _not_ get
>   called in atomic_check.
>
> v3: Document what can and cannot be checked in mode_valid a bit better
> (Andrjez). Answer: Only allowed to look at the mode, nothing else.
>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> Cc: Jose Abreu <joabreu@synopsys.com>
> Cc: Carlos Palminha <palminha@synopsys.com>
> Cc: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@linux.ie>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2)
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better
  2017-05-15  9:11     ` [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better Daniel Vetter
  2017-05-15  9:11       ` [PATCH 2/2] drm/doc: Clarify mode_fixup vs. atomic_check a bit more Daniel Vetter
  2017-05-16  2:38       ` [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better Jose Abreu
@ 2017-05-16 13:17       ` Andrzej Hajda
  2 siblings, 0 replies; 46+ messages in thread
From: Andrzej Hajda @ 2017-05-16 13:17 UTC (permalink / raw)
  To: Daniel Vetter, DRI Development
  Cc: Jose Abreu, Daniel Vetter, Laurent Pinchart

On 15.05.2017 11:11, Daniel Vetter wrote:
> Laurent started a massive discussion on IRC about this. Let's try to
> document common usage a bit better.
>
> v2: Cross-links+typos.
>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <Jose.Abreu@synopsys.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 46+ messages in thread

end of thread, other threads:[~2017-05-16 13:17 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-11  9:05 [PATCH v3 0/6] Introduce new mode validation callbacks Jose Abreu
2017-05-11  9:05 ` [PATCH v3 1/6] drm: Add crtc/encoder/bridge->mode_valid() callbacks Jose Abreu
2017-05-12  7:00   ` Daniel Vetter
2017-05-12  7:00     ` Daniel Vetter
2017-05-12  7:31   ` [PATCH] " Daniel Vetter
2017-05-12 11:29     ` Laurent Pinchart
2017-05-15  6:50       ` Daniel Vetter
2017-05-12 12:37     ` Andrzej Hajda
2017-05-15  6:56       ` Daniel Vetter
2017-05-15  8:10         ` Andrzej Hajda
2017-05-15  8:14           ` Daniel Vetter
2017-05-12 15:59     ` Jose Abreu
2017-05-15  9:11     ` [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better Daniel Vetter
2017-05-15  9:11       ` [PATCH 2/2] drm/doc: Clarify mode_fixup vs. atomic_check a bit more Daniel Vetter
2017-05-16  2:41         ` Jose Abreu
2017-05-16 13:14         ` Andrzej Hajda
2017-05-16  2:38       ` [PATCH 1/2] drm/doc: Document adjusted/request modes a bit better Jose Abreu
2017-05-16 13:17       ` Andrzej Hajda
2017-05-15  9:33     ` [PATCH] drm: Add crtc/encoder/bridge->mode_valid() callbacks Daniel Vetter
2017-05-16 13:15       ` Andrzej Hajda
2017-05-11  9:05 ` [PATCH v3 2/6] drm: Add drm_{crtc/encoder/connector}_mode_valid() Jose Abreu
2017-05-15  8:27   ` Andrzej Hajda
2017-05-15  8:27     ` Andrzej Hajda
2017-05-11  9:05 ` [PATCH v3 3/6] drm: Introduce drm_bridge_mode_valid() Jose Abreu
2017-05-11  9:06 ` [PATCH v3 4/6] drm: Use new mode_valid() helpers in connector probe helper Jose Abreu
2017-05-15  8:39   ` Andrzej Hajda
2017-05-15  8:39     ` Andrzej Hajda
2017-05-15  9:30     ` Daniel Vetter
2017-05-15  9:30       ` Daniel Vetter
2017-05-15  9:51       ` Andrzej Hajda
2017-05-15  9:51         ` Andrzej Hajda
2017-05-11  9:06 ` [PATCH v3 5/6] drm: Use mode_valid() in atomic modeset Jose Abreu
2017-05-15  8:45   ` Andrzej Hajda
2017-05-11  9:06 ` [PATCH v3 6/6] drm: arc: Use crtc->mode_valid() callback Jose Abreu
2017-05-15  8:53   ` Daniel Vetter
2017-05-15  8:53     ` Daniel Vetter
2017-05-15 15:52     ` Daniel Vetter
2017-05-15 15:52       ` Daniel Vetter
2017-05-15 23:55       ` Jose Abreu
2017-05-15 23:55         ` Jose Abreu
2017-05-15  8:54   ` Andrzej Hajda
2017-05-15  8:54     ` Andrzej Hajda
2017-05-12  7:32 ` [PATCH v3 0/6] Introduce new mode validation callbacks Daniel Vetter
2017-05-12  7:32   ` Daniel Vetter
2017-05-12 13:37   ` Andrzej Hajda
2017-05-12 13:37     ` Andrzej Hajda

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.