To use it, a driver must provide bottom functions for all of the three KMS
entities.
</para>
- <sect2>
- <title>Legacy CRTC Helper Operations</title>
- <itemizedlist>
- <listitem id="drm-helper-crtc-mode-fixup">
- <synopsis>bool (*mode_fixup)(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);</synopsis>
- <para>
- Let CRTCs adjust the requested mode or reject it completely. This
- operation returns true if the mode is accepted (possibly after being
- adjusted) or false if it is rejected.
- </para>
- <para>
- The <methodname>mode_fixup</methodname> operation should reject the
- mode if it can't reasonably use it. The definition of "reasonable"
- is currently fuzzy in this context. One possible behaviour would be
- to set the adjusted mode to the panel timings when a fixed-mode
- panel is used with hardware capable of scaling. Another behaviour
- would be to accept any input mode and adjust it to the closest mode
- supported by the hardware (FIXME: This needs to be clarified).
- </para>
- </listitem>
- <listitem>
- <synopsis>int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb)</synopsis>
- <para>
- Move the CRTC on the current frame buffer (stored in
- <literal>crtc->fb</literal>) to position (x,y). Any of the frame
- buffer, x position or y position may have been modified.
- </para>
- <para>
- This helper operation is optional. If not provided, the
- <function>drm_crtc_helper_set_config</function> function will fall
- back to the <methodname>mode_set</methodname> helper operation.
- </para>
- <note><para>
- FIXME: Why are x and y passed as arguments, as they can be accessed
- through <literal>crtc->x</literal> and
- <literal>crtc->y</literal>?
- </para></note>
- </listitem>
- <listitem>
- <synopsis>void (*prepare)(struct drm_crtc *crtc);</synopsis>
- <para>
- Prepare the CRTC for mode setting. This operation is called after
- validating the requested mode. Drivers use it to perform
- device-specific operations required before setting the new mode.
- </para>
- </listitem>
- <listitem>
- <synopsis>int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode, int x, int y,
- struct drm_framebuffer *old_fb);</synopsis>
- <para>
- Set a new mode, position and frame buffer. Depending on the device
- requirements, the mode can be stored internally by the driver and
- applied in the <methodname>commit</methodname> operation, or
- programmed to the hardware immediately.
- </para>
- <para>
- The <methodname>mode_set</methodname> operation returns 0 on success
- or a negative error code if an error occurs.
- </para>
- </listitem>
- <listitem>
- <synopsis>void (*commit)(struct drm_crtc *crtc);</synopsis>
- <para>
- Commit a mode. This operation is called after setting the new mode.
- Upon return the device must use the new mode and be fully
- operational.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2>
- <title>Encoder Helper Operations</title>
- <itemizedlist>
- <listitem>
- <synopsis>bool (*mode_fixup)(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);</synopsis>
- <para>
- Let encoders adjust the requested mode or reject it completely. This
- operation returns true if the mode is accepted (possibly after being
- adjusted) or false if it is rejected. See the
- <link linkend="drm-helper-crtc-mode-fixup">mode_fixup CRTC helper
- operation</link> for an explanation of the allowed adjustments.
- </para>
- </listitem>
- <listitem>
- <synopsis>void (*prepare)(struct drm_encoder *encoder);</synopsis>
- <para>
- Prepare the encoder for mode setting. This operation is called after
- validating the requested mode. Drivers use it to perform
- device-specific operations required before setting the new mode.
- </para>
- </listitem>
- <listitem>
- <synopsis>void (*mode_set)(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);</synopsis>
- <para>
- Set a new mode. Depending on the device requirements, the mode can
- be stored internally by the driver and applied in the
- <methodname>commit</methodname> operation, or programmed to the
- hardware immediately.
- </para>
- </listitem>
- <listitem>
- <synopsis>void (*commit)(struct drm_encoder *encoder);</synopsis>
- <para>
- Commit a mode. This operation is called after setting the new mode.
- Upon return the device must use the new mode and be fully
- operational.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2>
- <title>Connector Helper Operations</title>
- <itemizedlist>
- <listitem>
- <synopsis>struct drm_encoder *(*best_encoder)(struct drm_connector *connector);</synopsis>
- <para>
- Return a pointer to the best encoder for the connecter. Device that
- map connectors to encoders 1:1 simply return the pointer to the
- associated encoder. This operation is mandatory.
- </para>
- </listitem>
- <listitem>
- <synopsis>int (*get_modes)(struct drm_connector *connector);</synopsis>
- <para>
- Fill the connector's <structfield>probed_modes</structfield> list
- by parsing EDID data with <function>drm_add_edid_modes</function>,
- adding standard VESA DMT modes with <function>drm_add_modes_noedid</function>,
- or calling <function>drm_mode_probed_add</function> directly for every
- supported mode and return the number of modes it has detected. This
- operation is mandatory.
- </para>
- <para>
- Note that the caller function will automatically add standard VESA
- DMT modes up to 1024x768 if the <methodname>get_modes</methodname>
- helper operation returns no mode and if the connector status is
- connector_status_connected. There is no need to call
- <function>drm_add_edid_modes</function> manually in that case.
- </para>
- <para>
- The <structfield>vrefresh</structfield> value is computed by
- <function>drm_helper_probe_single_connector_modes</function>.
- </para>
- <para>
- When parsing EDID data, <function>drm_add_edid_modes</function> fills the
- connector <structfield>display_info</structfield>
- <structfield>width_mm</structfield> and
- <structfield>height_mm</structfield> fields. When creating modes
- manually the <methodname>get_modes</methodname> helper operation must
- set the <structfield>display_info</structfield>
- <structfield>width_mm</structfield> and
- <structfield>height_mm</structfield> fields if they haven't been set
- already (for instance at initialization time when a fixed-size panel is
- attached to the connector). The mode <structfield>width_mm</structfield>
- and <structfield>height_mm</structfield> fields are only used internally
- during EDID parsing and should not be set when creating modes manually.
- </para>
- </listitem>
- <listitem>
- <synopsis>int (*mode_valid)(struct drm_connector *connector,
- struct drm_display_mode *mode);</synopsis>
- <para>
- Verify whether a mode is valid for the connector. Return MODE_OK for
- supported modes and one of the enum drm_mode_status values (MODE_*)
- for unsupported modes. This operation is optional.
- </para>
- <para>
- As the mode rejection reason is currently not used beside for
- immediately removing the unsupported mode, an implementation can
- return MODE_BAD regardless of the exact reason why the mode is not
- valid.
- </para>
- <note><para>
- Note that the <methodname>mode_valid</methodname> helper operation is
- only called for modes detected by the device, and
- <emphasis>not</emphasis> for modes set by the user through the CRTC
- <methodname>set_config</methodname> operation.
- </para></note>
- </listitem>
- </itemizedlist>
- </sect2>
<sect2>
<title>Atomic Modeset Helper Functions Reference</title>
<sect3>
* 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
+ * ->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 ->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 ->mode_valid() but also in ->mode_fixup() to
+ * make sure invalid modes passed in from userspace are rejected.
+ *
* RETURNS:
*
* True if an acceptable configuration is possible, false if the modeset
* This callback is used by the legacy CRTC helpers to set a new
* framebuffer and scanout position. It is optional and used as an
* optimized fast-path instead of a full mode set operation with all the
- * resulting flickering. Since it can't update other planes it's
+ * resulting flickering. If it is not present
+ * drm_crtc_helper_set_config() will fall back to a full modeset, using
+ * the ->mode_set() callback. Since it can't update other planes it's
* incompatible with atomic modeset support.
*
* This callback is only used by the CRTC helpers and deprecated.
* 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
+ * ->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 ->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 ->mode_valid() but also in ->mode_fixup() to
+ * make sure invalid modes passed in from userspace are rejected.
+ *
* RETURNS:
*
* True if an acceptable configuration is possible, false if the modeset
* In this function drivers then parse the modes in the EDID and add
* them by calling drm_add_edid_modes(). But connectors that driver a
* fixed panel can also manually add specific modes using
- * drm_mode_probed_add(). Finally drivers that support audio probably
- * want to update the ELD data, too, using drm_edid_to_eld().
+ * drm_mode_probed_add(). Drivers which manually add modes should also
+ * make sure that the @display_info, @width_mm and @height_mm fields of the
+ * struct #drm_connector are filled in.
+ *
+ * Virtual drivers that just want some standard VESA mode with a given
+ * resolution can call drm_add_modes_noedid(), and mark the preferred
+ * one using drm_set_preferred_mode().
+ *
+ * Finally drivers that support audio probably want to update the ELD
+ * data, too, using drm_edid_to_eld().
*
* This function is only called after the ->detect() hook has indicated
* that a sink is connected and when the EDID isn't overridden through