/** * struct drm_encoder - central DRM encoder structure * @dev: parent DRM device * @head: list management * @base: base KMS object * @name: human readable name, can be overwritten by the driver * @funcs: control functions, can be NULL for simple managed encoders * @helper_private: mid-layer private data * * CRTCs drive pixels to encoders, which convert them into signals * appropriate for a given connector or set of connectors. */ structdrm_encoder { structdrm_device *dev; structlist_headhead;
structdrm_mode_objectbase; char *name; /** * @encoder_type: * * One of the DRM_MODE_ENCODER_<foo> types in drm_mode.h. The following * encoder types are defined thus far: * * - DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A. * * - DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort. * * - DRM_MODE_ENCODER_LVDS for display panels, or in general any panel * with a proprietary parallel connector. * * - DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video, * Component, SCART). * * - DRM_MODE_ENCODER_VIRTUAL for virtual machine displays * * - DRM_MODE_ENCODER_DSI for panels connected using the DSI serial bus. * * - DRM_MODE_ENCODER_DPI for panels connected using the DPI parallel * bus. * * - DRM_MODE_ENCODER_DPMST for special fake encoders used to allow * mutliple DP MST streams to share one physical encoder. */ int encoder_type;
/** * @index: Position inside the mode_config.list, can be used as an array * index. It is invariant over the lifetime of the encoder. */ unsigned index; /** * @possible_crtcs: Bitmask of potential CRTC bindings, using * drm_crtc_index() as the index into the bitfield. The driver must set * the bits for all &drm_crtc objects this encoder can be connected to * before calling drm_dev_register(). * * You will get a WARN if you get this wrong in the driver. * * Note that since CRTC objects can't be hotplugged the assigned indices * are stable and hence known before registering all objects. */ uint32_t possible_crtcs;
/** * @possible_clones: Bitmask of potential sibling encoders for cloning, * using drm_encoder_index() as the index into the bitfield. The driver * must set the bits for all &drm_encoder objects which can clone a * &drm_crtc together with this encoder before calling * drm_dev_register(). Drivers should set the bit representing the * encoder itself, too. Cloning bits should be set such that when two * encoders can be used in a cloned configuration, they both should have * each another bits set. * * As an exception to the above rule if the driver doesn't implement * any cloning it can leave @possible_clones set to 0. The core will * automagically fix this up by setting the bit for the encoder itself. * * You will get a WARN if you get this wrong in the driver. * * Note that since encoder objects can't be hotplugged the assigned indices * are stable and hence known before registering all objects. */ uint32_t possible_clones;
/** * @crtc: Currently bound CRTC, only really meaningful for non-atomic * drivers. Atomic drivers should instead check * &drm_connector_state.crtc. */ structdrm_crtc *crtc;
/** * @bridge_chain: Bridges attached to this encoder. Drivers shall not * access this field directly. */ structlist_headbridge_chain;
/** * struct drm_encoder_funcs - encoder controls * * Encoders sit between CRTCs and connectors. */ structdrm_encoder_funcs { /** * @reset: * * Reset encoder hardware and software state to off. This function isn't * called by the core directly, only through drm_mode_config_reset(). * It's not a helper hook only for historical reasons. */ void (*reset)(struct drm_encoder *encoder);
/** * @destroy: * * Clean up encoder resources. This is only called at driver unload time * through drm_mode_config_cleanup() since an encoder cannot be * hotplugged in DRM. */ void (*destroy)(struct drm_encoder *encoder);
/** * @late_register: * * This optional hook can be used to register additional userspace * interfaces attached to the encoder like debugfs interfaces. * It is called late in the driver load sequence from drm_dev_register(). * Everything added from this callback should be unregistered in * the early_unregister callback. * * Returns: * * 0 on success, or a negative error code on failure. */ int (*late_register)(struct drm_encoder *encoder);
/** * @early_unregister: * * This optional hook should be used to unregister the additional * userspace interfaces attached to the encoder from * @late_register. It is called from drm_dev_unregister(), * early in the driver unload sequence to disable userspace access * before data structures are torndown. */ void (*early_unregister)(struct drm_encoder *encoder); };
/** * struct drm_encoder_helper_funcs - helper operations for encoders * * These hooks are used by the legacy CRTC helpers, the transitional plane * helpers and the new atomic modesetting helpers. */ structdrm_encoder_helper_funcs { /** * @dpms: * * Callback to control power levels on the encoder. If the mode passed in * is unsupported, the provider must use the next lowest power level. * This is used by the legacy encoder helpers to implement DPMS * functionality in drm_helper_connector_dpms(). * * This callback is also used to disable an encoder by calling it with * DRM_MODE_DPMS_OFF if the @disable hook isn't used. * * This callback is used by the legacy CRTC helpers. Atomic helpers * also support using this hook for enabling and disabling an encoder to * facilitate transitions to atomic, but it is deprecated. Instead * @enable and @disable should be used. */ 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 */ enumdrm_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. * 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. 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. * * NOTE: * * This function is called in the check phase of atomic modesets, which * can be aborted for any reason (including on userspace's request to * just check whether a configuration would be possible). Atomic drivers * MUST NOT touch any persistent state (hardware or software) or data * structures except the passed in adjusted_mode parameter. * * This is in contrast to the legacy CRTC helpers where this was * allowed. * * Atomic drivers which need to inspect and adjust more state should * 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 * 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: * * True if an acceptable configuration is possible, false if the modeset * operation should be rejected. */ bool (*mode_fixup)(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode);
/** * @prepare: * * This callback should prepare the encoder for a subsequent modeset, * which in practice means the driver should disable the encoder if it * is running. Most drivers ended up implementing this by calling their * @dpms hook with DRM_MODE_DPMS_OFF. * * This callback is used by the legacy CRTC helpers. Atomic helpers * also support using this hook for disabling an encoder to facilitate * transitions to atomic, but it is deprecated. Instead @disable should * be used. */ void (*prepare)(struct drm_encoder *encoder); /** * @commit: * * This callback should commit the new mode on the encoder after a modeset, * which in practice means the driver should enable the encoder. Most * drivers ended up implementing this by calling their @dpms hook with * DRM_MODE_DPMS_ON. * * This callback is used by the legacy CRTC helpers. Atomic helpers * also support using this hook for enabling an encoder to facilitate * transitions to atomic, but it is deprecated. Instead @enable should * be used. */ void (*commit)(struct drm_encoder *encoder);
/** * @mode_set: * * This callback is used to update the display mode of an encoder. * * Note that the display pipe is completely off when this function is * called. Drivers which need hardware to be running before they program * the new display mode (because they implement runtime PM) should not * use this hook, because the helper library calls it only once and not * every time the display pipeline is suspend using either DPMS or the * new "ACTIVE" property. Such drivers should instead move all their * encoder setup into the @enable callback. * * This callback is used both by the legacy CRTC helpers and the atomic * modeset helpers. It is optional in the atomic helpers. * * NOTE: * * If the driver uses the atomic modeset helpers and needs to inspect * the connector state or connector display info during mode setting, * @atomic_mode_set can be used instead. */ void (*mode_set)(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode);
/** * @atomic_mode_set: * * This callback is used to update the display mode of an encoder. * * Note that the display pipe is completely off when this function is * called. Drivers which need hardware to be running before they program * the new display mode (because they implement runtime PM) should not * use this hook, because the helper library calls it only once and not * every time the display pipeline is suspended using either DPMS or the * new "ACTIVE" property. Such drivers should instead move all their * encoder setup into the @enable callback. * * This callback is used by the atomic modeset helpers in place of the * @mode_set callback, if set by the driver. It is optional and should * be used instead of @mode_set if the driver needs to inspect the * connector state or display info, since there is no direct way to * go from the encoder to the current connector. */ void (*atomic_mode_set)(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state); /** * @detect: * * This callback can be used by drivers who want to do detection on the * encoder object instead of in connector functions. * * It is not used by any helper and therefore has purely driver-specific * semantics. New drivers shouldn't use this and instead just implement * their own private callbacks. * * FIXME: * * This should just be converted into a pile of driver vfuncs. * Currently radeon, amdgpu and nouveau are using it. */ enumdrm_connector_status(*detect)(struct drm_encoder *encoder, struct drm_connector *connector);
/** * @atomic_disable: * * This callback should be used to disable the encoder. With the atomic * drivers it is called before this encoder's CRTC has been shut off * using their own &drm_crtc_helper_funcs.atomic_disable hook. If that * sequence is too simple drivers can just add their own driver private * encoder hooks and call them from CRTC's callback by looping over all * encoders connected to it using for_each_encoder_on_crtc(). * * This callback is a variant of @disable that provides the atomic state * to the driver. If @atomic_disable is implemented, @disable is not * called by the helpers. * * This hook is only used by atomic helpers. Atomic drivers don't need * to implement it if there's no need to disable anything at the encoder * level. To ensure that runtime PM handling (using either DPMS or the * new "ACTIVE" property) works @atomic_disable must be the inverse of * @atomic_enable. */ void (*atomic_disable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
/** * @atomic_enable: * * This callback should be used to enable the encoder. It is called * after this encoder's CRTC has been enabled using their own * &drm_crtc_helper_funcs.atomic_enable hook. If that sequence is * too simple drivers can just add their own driver private encoder * hooks and call them from CRTC's callback by looping over all encoders * connected to it using for_each_encoder_on_crtc(). * * This callback is a variant of @enable that provides the atomic state * to the driver. If @atomic_enable is implemented, @enable is not * called by the helpers. * * This hook is only used by atomic helpers, it is the opposite of * @atomic_disable. Atomic drivers don't need to implement it if there's * no need to enable anything at the encoder level. To ensure that * runtime PM handling works @atomic_enable must be the inverse of * @atomic_disable. */ void (*atomic_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state); /** * @disable: * * This callback should be used to disable the encoder. With the atomic * drivers it is called before this encoder's CRTC has been shut off * using their own &drm_crtc_helper_funcs.disable hook. If that * sequence is too simple drivers can just add their own driver private * encoder hooks and call them from CRTC's callback by looping over all * encoders connected to it using for_each_encoder_on_crtc(). * * This hook is used both by legacy CRTC helpers and atomic helpers. * Atomic drivers don't need to implement it if there's no need to * disable anything at the encoder level. To ensure that runtime PM * handling (using either DPMS or the new "ACTIVE" property) works * @disable must be the inverse of @enable for atomic drivers. * * For atomic drivers also consider @atomic_disable and save yourself * from having to read the NOTE below! * * NOTE: * * With legacy CRTC helpers there's a big semantic difference between * @disable and other hooks (like @prepare or @dpms) used to shut down a * encoder: @disable is only called when also logically disabling the * display pipeline and needs to release any resources acquired in * @mode_set (like shared PLLs, or again release pinned framebuffers). * * Therefore @disable must be the inverse of @mode_set plus @commit for * drivers still using legacy CRTC helpers, which is different from the * rules under atomic. */ void (*disable)(struct drm_encoder *encoder);
/** * @enable: * * This callback should be used to enable the encoder. With the atomic * drivers it is called after this encoder's CRTC has been enabled using * their own &drm_crtc_helper_funcs.enable hook. If that sequence is * too simple drivers can just add their own driver private encoder * hooks and call them from CRTC's callback by looping over all encoders * connected to it using for_each_encoder_on_crtc(). * * This hook is only used by atomic helpers, it is the opposite of * @disable. Atomic drivers don't need to implement it if there's no * need to enable anything at the encoder level. To ensure that * runtime PM handling (using either DPMS or the new "ACTIVE" property) * works @enable must be the inverse of @disable for atomic drivers. */ void (*enable)(struct drm_encoder *encoder);
/** * @atomic_check: * * This callback is used to validate encoder state for atomic drivers. * Since the encoder is the object connecting the CRTC and connector it * gets passed both states, to be able to validate interactions and * 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: * * This function is called in the check phase of an atomic update. The * driver is not allowed to change anything outside of the free-standing * 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 * supported, -ENOMEM on memory allocation failure and -EDEADLK if an * attempt to obtain another state object ran into a &drm_modeset_lock * deadlock. */ int (*atomic_check)(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state); };
/** * struct drm_bridge - central DRM bridge control structure */ structdrm_bridge { /** @base: inherit from &drm_private_object */ structdrm_private_objbase; /** @dev: DRM device this bridge belongs to */ structdrm_device *dev; /** @encoder: encoder to which this bridge is connected */ structdrm_encoder *encoder; /** @chain_node: used to form a bridge chain */ structlist_headchain_node; #ifdef CONFIG_OF /** @of_node: device node pointer to the bridge */ structdevice_node *of_node; #endif /** @list: to keep track of all added bridges */ structlist_headlist; /** * @timings: * * the timing specification for the bridge, if any (may be NULL) */ conststructdrm_bridge_timings *timings; /** @funcs: control functions */ conststructdrm_bridge_funcs *funcs; /** @driver_private: pointer to the bridge driver's internal context */ void *driver_private; /** @ops: bitmask of operations supported by the bridge */ enum drm_bridge_ops ops; /** * @type: Type of the connection at the bridge output * (DRM_MODE_CONNECTOR_*). For bridges at the end of this chain this * identifies the type of connected display. */ int type; /** * @interlace_allowed: Indicate that the bridge can handle interlaced * modes. */ bool interlace_allowed; /** * @pre_enable_prev_first: The bridge requires that the prev * bridge @pre_enable function is called before its @pre_enable, * and conversely for post_disable. This is most frequently a * requirement for DSI devices which need the host to be initialised * before the peripheral. */ bool pre_enable_prev_first; /** * @ddc: Associated I2C adapter for DDC access, if any. */ structi2c_adapter *ddc; /** private: */ /** * @hpd_mutex: Protects the @hpd_cb and @hpd_data fields. */ structmutexhpd_mutex; /** * @hpd_cb: Hot plug detection callback, registered with * drm_bridge_hpd_enable(). */ void (*hpd_cb)(void *data, enum drm_connector_status status); /** * @hpd_data: Private data passed to the Hot plug detection callback * @hpd_cb. */ void *hpd_data; };
/** * struct drm_bridge_funcs - drm_bridge control functions */ structdrm_bridge_funcs { /** * @attach: * * This callback is invoked whenever our bridge is being attached to a * &drm_encoder. The flags argument tunes the behaviour of the attach * operation (see DRM_BRIDGE_ATTACH_*). * * The @attach callback is optional. * * RETURNS: * * Zero on success, error code on failure. */ int (*attach)(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags);
/** * @detach: * * This callback is invoked whenever our bridge is being detached from a * &drm_encoder. * * The @detach callback is optional. */ 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(). * * The @mode_valid callback 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 */ enumdrm_mode_status(*mode_valid)(struct drm_bridge *bridge, const struct drm_display_info *info, 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 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. 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 * configuration. * * The mode_fixup callback is optional. &drm_bridge_funcs.mode_fixup() * is not called when &drm_bridge_funcs.atomic_check() is implemented, * so only one of them should be provided. * * NOTE: * * This function is called in the check phase of atomic modesets, which * can be aborted for any reason (including on userspace's request to * just check whether a configuration would be possible). Drivers MUST * 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 * operation should be rejected. */ bool (*mode_fixup)(struct drm_bridge *bridge, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); /** * @disable: * * This callback should disable the bridge. It is called right before * the preceding element in the display pipe is disabled. If the * preceding element is a bridge this means it's called before that * bridge's @disable vfunc. If the preceding element is a &drm_encoder * it's called right before the &drm_encoder_helper_funcs.disable, * &drm_encoder_helper_funcs.prepare or &drm_encoder_helper_funcs.dpms * hook. * * The bridge can assume that the display pipe (i.e. clocks and timing * signals) feeding it is still running when this callback is called. * * The @disable callback is optional. * * NOTE: * * This is deprecated, do not use! * New drivers shall use &drm_bridge_funcs.atomic_disable. */ void (*disable)(struct drm_bridge *bridge);
/** * @post_disable: * * This callback should disable the bridge. It is called right after the * preceding element in the display pipe is disabled. If the preceding * element is a bridge this means it's called after that bridge's * @post_disable function. If the preceding element is a &drm_encoder * it's called right after the encoder's * &drm_encoder_helper_funcs.disable, &drm_encoder_helper_funcs.prepare * or &drm_encoder_helper_funcs.dpms hook. * * The bridge must assume that the display pipe (i.e. clocks and timing * singals) feeding it is no longer running when this callback is * called. * * The @post_disable callback is optional. * * NOTE: * * This is deprecated, do not use! * New drivers shall use &drm_bridge_funcs.atomic_post_disable. */ void (*post_disable)(struct drm_bridge *bridge);
/** * @mode_set: * * This callback should set the given mode on the bridge. It is called * after the @mode_set callback for the preceding element in the display * pipeline has been called already. If the bridge is the first element * then this would be &drm_encoder_helper_funcs.mode_set. The display * pipe (i.e. clocks and timing signals) is off when this function is * called. * * The adjusted_mode parameter is the mode output by the CRTC for the * first bridge in the chain. It can be different from the mode * parameter that contains the desired mode for the connector at the end * of the bridges chain, for instance when the first bridge in the chain * performs scaling. The adjusted mode is mostly useful for the first * bridge in the chain and is likely irrelevant for the other bridges. * * For atomic drivers the adjusted_mode is the mode stored in * &drm_crtc_state.adjusted_mode. * * NOTE: * * This is deprecated, do not use! * New drivers shall set their mode in the * &drm_bridge_funcs.atomic_enable operation. */ void (*mode_set)(struct drm_bridge *bridge, const struct drm_display_mode *mode, const struct drm_display_mode *adjusted_mode); /** * @pre_enable: * * This callback should enable the bridge. It is called right before * the preceding element in the display pipe is enabled. If the * preceding element is a bridge this means it's called before that * bridge's @pre_enable function. If the preceding element is a * &drm_encoder it's called right before the encoder's * &drm_encoder_helper_funcs.enable, &drm_encoder_helper_funcs.commit or * &drm_encoder_helper_funcs.dpms hook. * * The display pipe (i.e. clocks and timing signals) feeding this bridge * will not yet be running when this callback is called. The bridge must * not enable the display link feeding the next bridge in the chain (if * there is one) when this callback is called. * * The @pre_enable callback is optional. * * NOTE: * * This is deprecated, do not use! * New drivers shall use &drm_bridge_funcs.atomic_pre_enable. */ void (*pre_enable)(struct drm_bridge *bridge);
/** * @enable: * * This callback should enable the bridge. It is called right after * the preceding element in the display pipe is enabled. If the * preceding element is a bridge this means it's called after that * bridge's @enable function. If the preceding element is a * &drm_encoder it's called right after the encoder's * &drm_encoder_helper_funcs.enable, &drm_encoder_helper_funcs.commit or * &drm_encoder_helper_funcs.dpms hook. * * The bridge can assume that the display pipe (i.e. clocks and timing * signals) feeding it is running when this callback is called. This * callback must enable the display link feeding the next bridge in the * chain if there is one. * * The @enable callback is optional. * * NOTE: * * This is deprecated, do not use! * New drivers shall use &drm_bridge_funcs.atomic_enable. */ void (*enable)(struct drm_bridge *bridge);
/** * @atomic_pre_enable: * * This callback should enable the bridge. It is called right before * the preceding element in the display pipe is enabled. If the * preceding element is a bridge this means it's called before that * bridge's @atomic_pre_enable or @pre_enable function. If the preceding * element is a &drm_encoder it's called right before the encoder's * &drm_encoder_helper_funcs.atomic_enable hook. * * The display pipe (i.e. clocks and timing signals) feeding this bridge * will not yet be running when this callback is called. The bridge must * not enable the display link feeding the next bridge in the chain (if * there is one) when this callback is called. * * The @atomic_pre_enable callback is optional. */ void (*atomic_pre_enable)(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state);
/** * @atomic_enable: * * This callback should enable the bridge. It is called right after * the preceding element in the display pipe is enabled. If the * preceding element is a bridge this means it's called after that * bridge's @atomic_enable or @enable function. If the preceding element * is a &drm_encoder it's called right after the encoder's * &drm_encoder_helper_funcs.atomic_enable hook. * * The bridge can assume that the display pipe (i.e. clocks and timing * signals) feeding it is running when this callback is called. This * callback must enable the display link feeding the next bridge in the * chain if there is one. * * The @atomic_enable callback is optional. */ void (*atomic_enable)(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state); /** * @atomic_disable: * * This callback should disable the bridge. It is called right before * the preceding element in the display pipe is disabled. If the * preceding element is a bridge this means it's called before that * bridge's @atomic_disable or @disable vfunc. If the preceding element * is a &drm_encoder it's called right before the * &drm_encoder_helper_funcs.atomic_disable hook. * * The bridge can assume that the display pipe (i.e. clocks and timing * signals) feeding it is still running when this callback is called. * * The @atomic_disable callback is optional. */ void (*atomic_disable)(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state);
/** * @atomic_post_disable: * * This callback should disable the bridge. It is called right after the * preceding element in the display pipe is disabled. If the preceding * element is a bridge this means it's called after that bridge's * @atomic_post_disable or @post_disable function. If the preceding * element is a &drm_encoder it's called right after the encoder's * &drm_encoder_helper_funcs.atomic_disable hook. * * The bridge must assume that the display pipe (i.e. clocks and timing * signals) feeding it is no longer running when this callback is * called. * * The @atomic_post_disable callback is optional. */ void (*atomic_post_disable)(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state);
/** * @atomic_duplicate_state: * * Duplicate the current bridge state object (which is guaranteed to be * non-NULL). * * The atomic_duplicate_state hook is mandatory if the bridge * implements any of the atomic hooks, and should be left unassigned * otherwise. For bridges that don't subclass &drm_bridge_state, the * drm_atomic_helper_bridge_duplicate_state() helper function shall be * used to implement this hook. * * RETURNS: * A valid drm_bridge_state object or NULL if the allocation fails. */ structdrm_bridge_state *(*atomic_duplicate_state)(structdrm_bridge *bridge);
/** * @atomic_destroy_state: * * Destroy a bridge state object previously allocated by * &drm_bridge_funcs.atomic_duplicate_state(). * * The atomic_destroy_state hook is mandatory if the bridge implements * any of the atomic hooks, and should be left unassigned otherwise. * For bridges that don't subclass &drm_bridge_state, the * drm_atomic_helper_bridge_destroy_state() helper function shall be * used to implement this hook. */ void (*atomic_destroy_state)(struct drm_bridge *bridge, struct drm_bridge_state *state);
/** * @atomic_get_output_bus_fmts: * * Return the supported bus formats on the output end of a bridge. * The returned array must be allocated with kmalloc() and will be * freed by the caller. If the allocation fails, NULL should be * returned. num_output_fmts must be set to the returned array size. * Formats listed in the returned array should be listed in decreasing * preference order (the core will try all formats until it finds one * that works). * * This method is only called on the last element of the bridge chain * as part of the bus format negotiation process that happens in * &drm_atomic_bridge_chain_select_bus_fmts(). * This method is optional. When not implemented, the core will * fall back to &drm_connector.display_info.bus_formats[0] if * &drm_connector.display_info.num_bus_formats > 0, * or to MEDIA_BUS_FMT_FIXED otherwise. */ u32 *(*atomic_get_output_bus_fmts)(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state, unsignedint *num_output_fmts);
/** * @atomic_get_input_bus_fmts: * * Return the supported bus formats on the input end of a bridge for * a specific output bus format. * * The returned array must be allocated with kmalloc() and will be * freed by the caller. If the allocation fails, NULL should be * returned. num_input_fmts must be set to the returned array size. * Formats listed in the returned array should be listed in decreasing * preference order (the core will try all formats until it finds one * that works). When the format is not supported NULL should be * returned and num_input_fmts should be set to 0. * * This method is called on all elements of the bridge chain as part of * the bus format negotiation process that happens in * drm_atomic_bridge_chain_select_bus_fmts(). * This method is optional. When not implemented, the core will bypass * bus format negotiation on this element of the bridge without * failing, and the previous element in the chain will be passed * MEDIA_BUS_FMT_FIXED as its output bus format. * * Bridge drivers that need to support being linked to bridges that are * not supporting bus format negotiation should handle the * output_fmt == MEDIA_BUS_FMT_FIXED case appropriately, by selecting a * sensible default value or extracting this information from somewhere * else (FW property, &drm_display_mode, &drm_display_info, ...) * * Note: Even if input format selection on the first bridge has no * impact on the negotiation process (bus format negotiation stops once * we reach the first element of the chain), drivers are expected to * return accurate input formats as the input format may be used to * configure the CRTC output appropriately. */ u32 *(*atomic_get_input_bus_fmts)(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state, u32 output_fmt, unsignedint *num_input_fmts);
/** * @atomic_check: * * This method is responsible for checking bridge state correctness. * It can also check the state of the surrounding components in chain * to make sure the whole pipeline can work properly. * * &drm_bridge_funcs.atomic_check() hooks are called in reverse * order (from the last to the first bridge). * * This method is optional. &drm_bridge_funcs.mode_fixup() is not * called when &drm_bridge_funcs.atomic_check() is implemented, so only * one of them should be provided. * * If drivers need to tweak &drm_bridge_state.input_bus_cfg.flags or * &drm_bridge_state.output_bus_cfg.flags it should happen in * this function. By default the &drm_bridge_state.output_bus_cfg.flags * field is set to the next bridge * &drm_bridge_state.input_bus_cfg.flags value or * &drm_connector.display_info.bus_flags if the bridge is the last * element in the chain. * * RETURNS: * zero if the check passed, a negative error code otherwise. */ int (*atomic_check)(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state);
/** * @atomic_reset: * * Reset the bridge to a predefined state (or retrieve its current * state) and return a &drm_bridge_state object matching this state. * This function is called at attach time. * * The atomic_reset hook is mandatory if the bridge implements any of * the atomic hooks, and should be left unassigned otherwise. For * bridges that don't subclass &drm_bridge_state, the * drm_atomic_helper_bridge_reset() helper function shall be used to * implement this hook. * * Note that the atomic_reset() semantics is not exactly matching the * reset() semantics found on other components (connector, plane, ...). * * 1. The reset operation happens when the bridge is attached, not when * drm_mode_config_reset() is called * 2. It's meant to be used exclusively on bridges that have been * converted to the ATOMIC API * * RETURNS: * A valid drm_bridge_state object in case of success, an ERR_PTR() * giving the reason of the failure otherwise. */ structdrm_bridge_state *(*atomic_reset)(structdrm_bridge *bridge);
/** * @detect: * * Check if anything is attached to the bridge output. * * This callback is optional, if not implemented the bridge will be * considered as always having a component attached to its output. * Bridges that implement this callback shall set the * DRM_BRIDGE_OP_DETECT flag in their &drm_bridge->ops. * * RETURNS: * * drm_connector_status indicating the bridge output status. */ enumdrm_connector_status(*detect)(struct drm_bridge *bridge);
/** * @get_modes: * * Fill all modes currently valid for the sink into the &drm_connector * with drm_mode_probed_add(). * * The @get_modes callback is mostly intended to support non-probeable * displays such as many fixed panels. Bridges that support reading * EDID shall leave @get_modes unimplemented and implement the * &drm_bridge_funcs->get_edid callback instead. * * This callback is optional. Bridges that implement it shall set the * DRM_BRIDGE_OP_MODES flag in their &drm_bridge->ops. * * The connector parameter shall be used for the sole purpose of * filling modes, and shall not be stored internally by bridge drivers * for future usage. * * RETURNS: * * The number of modes added by calling drm_mode_probed_add(). */ int (*get_modes)(struct drm_bridge *bridge, struct drm_connector *connector);
/** * @get_edid: * * Read and parse the EDID data of the connected display. * * The @get_edid callback is the preferred way of reporting mode * information for a display connected to the bridge output. Bridges * that support reading EDID shall implement this callback and leave * the @get_modes callback unimplemented. * * The caller of this operation shall first verify the output * connection status and refrain from reading EDID from a disconnected * output. * * This callback is optional. Bridges that implement it shall set the * DRM_BRIDGE_OP_EDID flag in their &drm_bridge->ops. * * The connector parameter shall be used for the sole purpose of EDID * retrieval and parsing, and shall not be stored internally by bridge * drivers for future usage. * * RETURNS: * * An edid structure newly allocated with kmalloc() (or similar) on * success, or NULL otherwise. The caller is responsible for freeing * the returned edid structure with kfree(). */ structedid *(*get_edid)(structdrm_bridge *bridge, structdrm_connector *connector);
/** * @hpd_notify: * * Notify the bridge of hot plug detection. * * This callback is optional, it may be implemented by bridges that * need to be notified of display connection or disconnection for * internal reasons. One use case is to reset the internal state of CEC * controllers for HDMI bridges. */ void (*hpd_notify)(struct drm_bridge *bridge, enum drm_connector_status status);
/** * @hpd_enable: * * Enable hot plug detection. From now on the bridge shall call * drm_bridge_hpd_notify() each time a change is detected in the output * connection status, until hot plug detection gets disabled with * @hpd_disable. * * This callback is optional and shall only be implemented by bridges * that support hot-plug notification without polling. Bridges that * implement it shall also implement the @hpd_disable callback and set * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops. */ void (*hpd_enable)(struct drm_bridge *bridge);
/** * @hpd_disable: * * Disable hot plug detection. Once this function returns the bridge * shall not call drm_bridge_hpd_notify() when a change in the output * connection status occurs. * * This callback is optional and shall only be implemented by bridges * that support hot-plug notification without polling. Bridges that * implement it shall also implement the @hpd_enable callback and set * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops. */ void (*hpd_disable)(struct drm_bridge *bridge);
/** * struct drm_connector - central DRM connector control structure * * Each connector may be connected to one or more CRTCs, or may be clonable by * another connector if they can share a CRTC. Each connector also has a specific * position in the broader display (referred to as a 'screen' though it could * span multiple monitors). */ structdrm_connector { /** @dev: parent DRM device */ structdrm_device *dev; /** @kdev: kernel device for sysfs attributes */ structdevice *kdev; /** @attr: sysfs attributes */ structdevice_attribute *attr; /** * @fwnode: associated fwnode supplied by platform firmware * * Drivers can set this to associate a fwnode with a connector, drivers * are expected to get a reference on the fwnode when setting this. * drm_connector_cleanup() will call fwnode_handle_put() on this. */ structfwnode_handle *fwnode;
/** * @head: * * List of all connectors on a @dev, linked from * &drm_mode_config.connector_list. Protected by * &drm_mode_config.connector_list_lock, but please only use * &drm_connector_list_iter to walk this list. */ structlist_headhead;
/** * @global_connector_list_entry: * * Connector entry in the global connector-list, used by * drm_connector_find_by_fwnode(). */ structlist_headglobal_connector_list_entry;
/** @base: base KMS object */ structdrm_mode_objectbase;
/** @name: human readable name, can be overwritten by the driver */ char *name;
/** * @mutex: Lock for general connector state, but currently only protects * @registered. Most of the connector state is still protected by * &drm_mode_config.mutex. */ structmutexmutex;
/** * @index: Compacted connector index, which matches the position inside * the mode_config.list for drivers not supporting hot-add/removing. Can * be used as an array index. It is invariant over the lifetime of the * connector. */ unsigned index;
/** * @connector_type: * one of the DRM_MODE_CONNECTOR_<foo> types from drm_mode.h */ int connector_type; /** @connector_type_id: index into connector type enum */ int connector_type_id; /** * @interlace_allowed: * Can this connector handle interlaced modes? Only used by * drm_helper_probe_single_connector_modes() for mode filtering. */ bool interlace_allowed; /** * @doublescan_allowed: * Can this connector handle doublescan? Only used by * drm_helper_probe_single_connector_modes() for mode filtering. */ bool doublescan_allowed; /** * @stereo_allowed: * Can this connector handle stereo modes? Only used by * drm_helper_probe_single_connector_modes() for mode filtering. */ bool stereo_allowed;
/** * @ycbcr_420_allowed : This bool indicates if this connector is * capable of handling YCBCR 420 output. While parsing the EDID * blocks it's very helpful to know if the source is capable of * handling YCBCR 420 outputs. */ bool ycbcr_420_allowed;
/** * @registration_state: Is this connector initializing, exposed * (registered) with userspace, or unregistered? * * Protected by @mutex. */ enum drm_connector_registration_state registration_state;
/** * @modes: * Modes available on this connector (from fill_modes() + user). * Protected by &drm_mode_config.mutex. */ structlist_headmodes;
/** * @status: * One of the drm_connector_status enums (connected, not, or unknown). * Protected by &drm_mode_config.mutex. */ enum drm_connector_status status;
/** * @probed_modes: * These are modes added by probing with DDC or the BIOS, before * filtering is applied. Used by the probe helpers. Protected by * &drm_mode_config.mutex. */ structlist_headprobed_modes;
/** * @display_info: Display information is filled from EDID information * when a display is detected. For non hot-pluggable displays such as * flat panels in embedded systems, the driver should initialize the * &drm_display_info.width_mm and &drm_display_info.height_mm fields * with the physical size of the display. * * Protected by &drm_mode_config.mutex. */ structdrm_display_infodisplay_info;
/** @funcs: connector control functions */ conststructdrm_connector_funcs *funcs;
/** * @edid_blob_ptr: DRM property containing EDID if present. Protected by * &drm_mode_config.mutex. This should be updated only by calling * drm_connector_update_edid_property(). */ structdrm_property_blob *edid_blob_ptr;
/** @properties: property tracking for this connector */ structdrm_object_propertiesproperties;
/** * @scaling_mode_property: Optional atomic property to control the * upscaling. See drm_connector_attach_content_protection_property(). */ structdrm_property *scaling_mode_property;
/** * @vrr_capable_property: Optional property to help userspace * query hardware support for variable refresh rate on a connector. * connector. Drivers can add the property to a connector by * calling drm_connector_attach_vrr_capable_property(). * * This should be updated only by calling * drm_connector_set_vrr_capable_property(). */ structdrm_property *vrr_capable_property;
/** * @colorspace_property: Connector property to set the suitable * colorspace supported by the sink. */ structdrm_property *colorspace_property;
/** * @path_blob_ptr: * * DRM blob property data for the DP MST path property. This should only * be updated by calling drm_connector_set_path_property(). */ structdrm_property_blob *path_blob_ptr;
/** * @max_bpc_property: Default connector property for the max bpc to be * driven out of the connector. */ structdrm_property *max_bpc_property;
/** @privacy_screen: drm_privacy_screen for this connector, or NULL. */ structdrm_privacy_screen *privacy_screen;
/** * @privacy_screen_sw_state_property: Optional atomic property for the * connector to control the integrated privacy screen. */ structdrm_property *privacy_screen_sw_state_property;
/** * @privacy_screen_hw_state_property: Optional atomic property for the * connector to report the actual integrated privacy screen state. */ structdrm_property *privacy_screen_hw_state_property;
/** * @polled: * * Connector polling mode, a combination of * * DRM_CONNECTOR_POLL_HPD * The connector generates hotplug events and doesn't need to be * periodically polled. The CONNECT and DISCONNECT flags must not * be set together with the HPD flag. * * DRM_CONNECTOR_POLL_CONNECT * Periodically poll the connector for connection. * * DRM_CONNECTOR_POLL_DISCONNECT * Periodically poll the connector for disconnection, without * causing flickering even when the connector is in use. DACs should * rarely do this without a lot of testing. * * Set to 0 for connectors that don't support connection status * discovery. */ uint8_t polled;
/** * @dpms: Current dpms state. For legacy drivers the * &drm_connector_funcs.dpms callback must update this. For atomic * drivers, this is handled by the core atomic code, and drivers must * only take &drm_crtc_state.active into account. */ int dpms;
/** @helper_private: mid-layer private data */ conststructdrm_connector_helper_funcs *helper_private;
/** @cmdline_mode: mode line parsed from the kernel cmdline for this connector */ structdrm_cmdline_modecmdline_mode; /** @force: a DRM_FORCE_<foo> state for forced mode sets */ enum drm_connector_force force;
/** * @edid_override: Override EDID set via debugfs. * * Do not modify or access outside of the drm_edid_override_* family of * functions. */ conststructdrm_edid *edid_override;
/** * @edid_override_mutex: Protect access to edid_override. */ structmutexedid_override_mutex;
/** @epoch_counter: used to detect any other changes in connector, besides status */ u64 epoch_counter;
/** * @possible_encoders: Bit mask of encoders that can drive this * connector, drm_encoder_index() determines the index into the bitfield * and the bits are set with drm_connector_attach_encoder(). */ u32 possible_encoders;
/** * @encoder: Currently bound encoder driving this connector, if any. * Only really meaningful for non-atomic drivers. Atomic drivers should * instead look at &drm_connector_state.best_encoder, and in case they * need the CRTC driving this output, &drm_connector_state.crtc. */ structdrm_encoder *encoder;
#define MAX_ELD_BYTES 128 /** @eld: EDID-like data, if present */ uint8_t eld[MAX_ELD_BYTES]; /** @latency_present: AV delay info from ELD, if found */ bool latency_present[2]; /** * @video_latency: Video latency info from ELD, if found. * [0]: progressive, [1]: interlaced */ int video_latency[2]; /** * @audio_latency: audio latency info from ELD, if found * [0]: progressive, [1]: interlaced */ int audio_latency[2];
/** * @ddc: associated ddc adapter. * A connector usually has its associated ddc adapter. If a driver uses * this field, then an appropriate symbolic link is created in connector * sysfs directory to make it easy for the user to tell which i2c * adapter is for a particular display. * * The field should be set by calling drm_connector_init_with_ddc(). */ structi2c_adapter *ddc;
/** * @null_edid_counter: track sinks that give us all zeros for the EDID. * Needed to workaround some HW bugs where we get all 0s */ int null_edid_counter;
/** @bad_edid_counter: track sinks that give us an EDID with invalid checksum */ unsigned bad_edid_counter;
/** * @edid_corrupt: Indicates whether the last read EDID was corrupt. Used * in Displayport compliance testing - Displayport Link CTS Core 1.2 * rev1.1 4.2.2.6 */ bool edid_corrupt; /** * @real_edid_checksum: real edid checksum for corrupted edid block. * Required in Displayport 1.4 compliance testing * rev1.1 4.2.2.6 */ u8 real_edid_checksum;
/** @debugfs_entry: debugfs directory for this connector */ structdentry *debugfs_entry;
/** * @state: * * Current atomic state for this connector. * * This is protected by &drm_mode_config.connection_mutex. Note that * nonblocking atomic commits access the current connector state without * taking locks. Either by going through the &struct drm_atomic_state * pointers, see for_each_oldnew_connector_in_state(), * for_each_old_connector_in_state() and * for_each_new_connector_in_state(). Or through careful ordering of * atomic commit operations as implemented in the atomic helpers, see * &struct drm_crtc_commit. */ structdrm_connector_state *state;
/* DisplayID bits. FIXME: Extract into a substruct? */
/** * @tile_blob_ptr: * * DRM blob property data for the tile property (used mostly by DP MST). * This is meant for screens which are driven through separate display * pipelines represented by &drm_crtc, which might not be running with * genlocked clocks. For tiled panels which are genlocked, like * dual-link LVDS or dual-link DSI, the driver should try to not expose * the tiling and virtualize both &drm_crtc and &drm_plane if needed. * * This should only be updated by calling * drm_connector_set_tile_property(). */ structdrm_property_blob *tile_blob_ptr;
/** @has_tile: is this connector connected to a tiled monitor */ bool has_tile; /** @tile_group: tile group for the connected monitor */ structdrm_tile_group *tile_group; /** @tile_is_single_monitor: whether the tile is one monitor housing */ bool tile_is_single_monitor;
/** @num_h_tile: number of horizontal tiles in the tile group */ /** @num_v_tile: number of vertical tiles in the tile group */ uint8_t num_h_tile, num_v_tile; /** @tile_h_loc: horizontal location of this tile */ /** @tile_v_loc: vertical location of this tile */ uint8_t tile_h_loc, tile_v_loc; /** @tile_h_size: horizontal size of this tile. */ /** @tile_v_size: vertical size of this tile. */ uint16_t tile_h_size, tile_v_size;
/** * @free_node: * * List used only by &drm_connector_list_iter to be able to clean up a * connector from any context, in conjunction with * &drm_mode_config.connector_free_work. */ structllist_nodefree_node;
/** @hdr_sink_metadata: HDR Metadata Information read from sink */ structhdr_sink_metadatahdr_sink_metadata; };
/** * struct drm_display_info - runtime data about the connected sink * * Describes a given display (e.g. CRT or flat panel) and its limitations. For * fixed display sinks like built-in panels there's not much difference between * this and &struct drm_connector. But for sinks with a real cable this * structure is meant to describe all the things at the other end of the cable. * * For sinks which provide an EDID this can be filled out by calling * drm_add_edid_modes(). */ structdrm_display_info { /** * @width_mm: Physical width in mm. */ unsignedint width_mm;
/** * @height_mm: Physical height in mm. */ unsignedint height_mm;
/** * @bpc: Maximum bits per color channel. Used by HDMI and DP outputs. */ unsignedint bpc;
/** * @subpixel_order: Subpixel order of LCD panels. */ enum subpixel_order subpixel_order;
/** * @panel_orientation: Read only connector property for built-in panels, * indicating the orientation of the panel vs the device's casing. * drm_connector_init() sets this to DRM_MODE_PANEL_ORIENTATION_UNKNOWN. * When not UNKNOWN this gets used by the drm_fb_helpers to rotate the * fb to compensate and gets exported as prop to userspace. */ int panel_orientation;
/** * @color_formats: HDMI Color formats, selects between RGB and YCrCb * modes. Used DRM_COLOR_FORMAT\_ defines, which are _not_ the same ones * as used to describe the pixel format in framebuffers, and also don't * match the formats in @bus_formats which are shared with v4l. */ u32 color_formats;
/** * @bus_formats: Pixel data format on the wire, somewhat redundant with * @color_formats. Array of size @num_bus_formats encoded using * MEDIA_BUS_FMT\_ defines shared with v4l and media drivers. */ const u32 *bus_formats;
/** * @bus_formats: Pixel data format on the wire, somewhat redundant with * @color_formats. Array of size @num_bus_formats encoded using * MEDIA_BUS_FMT\_ defines shared with v4l and media drivers. */ const u32 *bus_formats; /** * @num_bus_formats: Size of @bus_formats array. */ unsignedint num_bus_formats;
/** * @bus_flags: Additional information (like pixel signal polarity) for * the pixel data on the bus, using &enum drm_bus_flags values * DRM_BUS_FLAGS\_. */ u32 bus_flags;
/** * @max_tmds_clock: Maximum TMDS clock rate supported by the * sink in kHz. 0 means undefined. */ int max_tmds_clock;
/** * @dvi_dual: Dual-link DVI sink? */ bool dvi_dual;
/** * @is_hdmi: True if the sink is an HDMI device. * * This field shall be used instead of calling * drm_detect_hdmi_monitor() when possible. */ bool is_hdmi;
/** * @has_hdmi_infoframe: Does the sink support the HDMI infoframe? */ bool has_hdmi_infoframe;
/** * @rgb_quant_range_selectable: Does the sink support selecting * the RGB quantization range? */ bool rgb_quant_range_selectable;
/** * @edid_hdmi_rgb444_dc_modes: Mask of supported hdmi deep color modes * in RGB 4:4:4. Even more stuff redundant with @bus_formats. */ u8 edid_hdmi_rgb444_dc_modes;
/** * @edid_hdmi_ycbcr444_dc_modes: Mask of supported hdmi deep color * modes in YCbCr 4:4:4. Even more stuff redundant with @bus_formats. */ u8 edid_hdmi_ycbcr444_dc_modes;
/** * @cea_rev: CEA revision of the HDMI sink. */ u8 cea_rev;
/** * @hdmi: advance features of a HDMI sink. */ structdrm_hdmi_infohdmi;
/** * @non_desktop: Non desktop display (HMD). */ bool non_desktop;
/** * @monitor_range: Frequency range supported by monitor range descriptor */ structdrm_monitor_range_infomonitor_range;
/** * @luminance_range: Luminance range supported by panel */ structdrm_luminance_range_infoluminance_range;
/** * @mso_stream_count: eDP Multi-SST Operation (MSO) stream count from * the DisplayID VESA vendor block. 0 for conventional Single-Stream * Transport (SST), or 2 or 4 MSO streams. */ u8 mso_stream_count;
/** * struct drm_hdmi_info - runtime information about the connected HDMI sink * * Describes if a given display supports advanced HDMI 2.0 features. * This information is available in CEA-861-F extension blocks (like HF-VSDB). */ structdrm_hdmi_info { /** @scdc: sink's scdc support and capabilities */ structdrm_scdcscdc;
/** * @y420_vdb_modes: bitmap of modes which can support ycbcr420 * output only (not normal RGB/YCBCR444/422 outputs). The max VIC * defined by the CEA-861-G spec is 219, so the size is 256 bits to map * up to 256 VICs. */ unsignedlong y420_vdb_modes[BITS_TO_LONGS(256)];
/** * @y420_cmdb_modes: bitmap of modes which can support ycbcr420 * output also, along with normal HDMI outputs. The max VIC defined by * the CEA-861-G spec is 219, so the size is 256 bits to map up to 256 * VICs. */ unsignedlong y420_cmdb_modes[BITS_TO_LONGS(256)];
/** @y420_dc_modes: bitmap of deep color support index */ u8 y420_dc_modes;
/** @max_frl_rate_per_lane: support fixed rate link */ u8 max_frl_rate_per_lane;
/** @max_lanes: supported by sink */ u8 max_lanes;
/** @dsc_cap: DSC capabilities of the sink */ structdrm_hdmi_dsc_capdsc_cap; };
/** * struct drm_connector_funcs - control connectors on a given device * * Each CRTC may have one or more connectors attached to it. The functions * below allow the core DRM code to control connectors, enumerate available modes, * etc. */ structdrm_connector_funcs { /** * @dpms: * * Legacy entry point to set the per-connector DPMS state. Legacy DPMS * is exposed as a standard property on the connector, but diverted to * this callback in the drm core. Note that atomic drivers don't * implement the 4 level DPMS support on the connector any more, but * instead only have an on/off "ACTIVE" property on the CRTC object. * * This hook is not used by atomic drivers, remapping of the legacy DPMS * property is entirely handled in the DRM core. * * RETURNS: * * 0 on success or a negative error code on failure. */ int (*dpms)(struct drm_connector *connector, int mode);
/** * @reset: * * Reset connector hardware and software state to off. This function isn't * called by the core directly, only through drm_mode_config_reset(). * It's not a helper hook only for historical reasons. * * Atomic drivers can use drm_atomic_helper_connector_reset() to reset * atomic state using this hook. */ void (*reset)(struct drm_connector *connector);
/** * @detect: * * Check to see if anything is attached to the connector. The parameter * force is set to false whilst polling, true when checking the * connector due to a user request. force can be used by the driver to * avoid expensive, destructive operations during automated probing. * * This callback is optional, if not implemented the connector will be * considered as always being attached. * * FIXME: * * Note that this hook is only called by the probe helper. It's not in * the helper library vtable purely for historical reasons. The only DRM * core entry point to probe connector state is @fill_modes. * * Note that the helper library will already hold * &drm_mode_config.connection_mutex. Drivers which need to grab additional * locks to avoid races with concurrent modeset changes need to use * &drm_connector_helper_funcs.detect_ctx instead. * * Also note that this callback can be called no matter the * state the connector is in. Drivers that need the underlying * device to be powered to perform the detection will first need * to make sure it's been properly enabled. * * RETURNS: * * drm_connector_status indicating the connector's status. */ enumdrm_connector_status(*detect)(struct drm_connector *connector, bool force);
/** * @force: * * This function is called to update internal encoder state when the * connector is forced to a certain state by userspace, either through * the sysfs interfaces or on the kernel cmdline. In that case the * @detect callback isn't called. * * FIXME: * * Note that this hook is only called by the probe helper. It's not in * the helper library vtable purely for historical reasons. The only DRM * core entry point to probe connector state is @fill_modes. */ void (*force)(struct drm_connector *connector);
/** * @fill_modes: * * Entry point for output detection and basic mode validation. The * driver should reprobe the output if needed (e.g. when hotplug * handling is unreliable), add all detected modes to &drm_connector.modes * and filter out any the device can't support in any configuration. It * also needs to filter out any modes wider or higher than the * parameters max_width and max_height indicate. * * The drivers must also prune any modes no longer valid from * &drm_connector.modes. Furthermore it must update * &drm_connector.status and &drm_connector.edid. If no EDID has been * received for this output connector->edid must be NULL. * * Drivers using the probe helpers should use * drm_helper_probe_single_connector_modes() to implement this * function. * * RETURNS: * * The number of modes detected and filled into &drm_connector.modes. */ int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
/** * @set_property: * * This is the legacy entry point to update a property attached to the * connector. * * This callback is optional if the driver does not support any legacy * driver-private properties. For atomic drivers it is not used because * property handling is done entirely in the DRM core. * * RETURNS: * * 0 on success or a negative error code on failure. */ int (*set_property)(struct drm_connector *connector, struct drm_property *property, uint64_t val);
/** * @late_register: * * This optional hook can be used to register additional userspace * interfaces attached to the connector, light backlight control, i2c, * DP aux or similar interfaces. It is called late in the driver load * sequence from drm_connector_register() when registering all the * core drm connector interfaces. Everything added from this callback * should be unregistered in the early_unregister callback. * should be unregistered in the early_unregister callback. * * This is called while holding &drm_connector.mutex. * * Returns: * * 0 on success, or a negative error code on failure. */ int (*late_register)(struct drm_connector *connector);
/** * @early_unregister: * * This optional hook should be used to unregister the additional * userspace interfaces attached to the connector from * late_register(). It is called from drm_connector_unregister(), * early in the driver unload sequence to disable userspace access * before data structures are torndown. * * This is called while holding &drm_connector.mutex. */ void (*early_unregister)(struct drm_connector *connector);
/** * @destroy: * * Clean up connector resources. This is called at driver unload time * through drm_mode_config_cleanup(). It can also be called at runtime * when a connector is being hot-unplugged for drivers that support * connector hotplugging (e.g. DisplayPort MST). */ void (*destroy)(struct drm_connector *connector);
/** * @atomic_duplicate_state: * * Duplicate the current atomic state for this connector and return it. * The core and helpers guarantee that any atomic state duplicated with * this hook and still owned by the caller (i.e. not transferred to the * driver by calling &drm_mode_config_funcs.atomic_commit) will be * cleaned up by calling the @atomic_destroy_state hook in this * structure. * * This callback is mandatory for atomic drivers. * * Atomic drivers which don't subclass &struct drm_connector_state should use * drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the * state structure to extend it with driver-private state should use * __drm_atomic_helper_connector_duplicate_state() to make sure shared state is * duplicated in a consistent fashion across drivers. * * It is an error to call this hook before &drm_connector.state has been * initialized correctly. * * NOTE: * * If the duplicate state references refcounted resources this hook must * acquire a reference for each of them. The driver must release these * references again in @atomic_destroy_state. * * RETURNS: * * Duplicated atomic state or NULL when the allocation failed. */ structdrm_connector_state *(*atomic_duplicate_state)(structdrm_connector *connector);
/** * @atomic_destroy_state: * * Destroy a state duplicated with @atomic_duplicate_state and release * or unreference all resources it references * * This callback is mandatory for atomic drivers. */ void (*atomic_destroy_state)(struct drm_connector *connector, struct drm_connector_state *state);
/** * @atomic_set_property: * * Decode a driver-private property value and store the decoded value * into the passed-in state structure. Since the atomic core decodes all * standardized properties (even for extensions beyond the core set of * properties which might not be implemented by all drivers) this * requires drivers to subclass the state structure. * * Such driver-private properties should really only be implemented for * truly hardware/vendor specific state. Instead it is preferred to * standardize atomic extension and decode the properties used to expose * such an extension in the core. * * Do not call this function directly, use * drm_atomic_connector_set_property() instead. * * This callback is optional if the driver does not support any * driver-private atomic properties. * * NOTE: * * This function is called in the state assembly phase of atomic * modesets, which can be aborted for any reason (including on * userspace's request to just check whether a configuration would be * possible). Drivers MUST NOT touch any persistent state (hardware or * software) or data structures except the passed in @state parameter. * * Also since userspace controls in which order properties are set this * function must not do any input validation (since the state update is * incomplete and hence likely inconsistent). Instead any such input * validation must be done in the various atomic_check callbacks. * * RETURNS: * * 0 if the property has been found, -EINVAL if the property isn't * implemented by the driver (which shouldn't ever happen, the core only * asks for properties attached to this connector). No other validation * is allowed by the driver. The core already checks that the property * value is within the range (integer, valid enum value, ...) the driver * set when registering the property. */ int (*atomic_set_property)(struct drm_connector *connector, struct drm_connector_state *state, struct drm_property *property, uint64_t val);
/** * @atomic_get_property: * * Reads out the decoded driver-private property. This is used to * implement the GETCONNECTOR IOCTL. * * Do not call this function directly, use * drm_atomic_connector_get_property() instead. * * This callback is optional if the driver does not support any * driver-private atomic properties. * * RETURNS: * * 0 on success, -EINVAL if the property isn't implemented by the * driver (which shouldn't ever happen, the core only asks for * properties attached to this connector). */ int (*atomic_get_property)(struct drm_connector *connector, const struct drm_connector_state *state, struct drm_property *property, uint64_t *val);
/** * @atomic_print_state: * * If driver subclasses &struct drm_connector_state, it should implement * this optional hook for printing additional driver specific state. * * Do not call this directly, use drm_atomic_connector_print_state() * instead. */ void (*atomic_print_state)(struct drm_printer *p, const struct drm_connector_state *state);
/** * @oob_hotplug_event: * * This will get called when a hotplug-event for a drm-connector * has been received from a source outside the display driver / device. */ void (*oob_hotplug_event)(struct drm_connector *connector);
/** * struct drm_connector_helper_funcs - helper operations for connectors * * These functions are used by the atomic and legacy modeset helpers and by the * probe helpers. */ structdrm_connector_helper_funcs { /** * @get_modes: * * This function should fill in all modes currently valid for the sink * into the &drm_connector.probed_modes list. It should also update the * EDID property by calling drm_connector_update_edid_property(). * * The usual way to implement this is to cache the EDID retrieved in the * probe callback somewhere in the driver-private connector structure. * In this function drivers then parse the modes in the EDID and add * them by calling drm_add_edid_modes(). But connectors that drive a * fixed panel can also manually add specific modes using * drm_mode_probed_add(). Drivers which manually add modes should also * make sure that the &drm_connector.display_info, * &drm_connector.width_mm and &drm_connector.height_mm fields are * filled in. * * Note that the caller function will automatically add standard VESA * DMT modes up to 1024x768 if the .get_modes() helper operation returns * no mode and if the connector status is connector_status_connected or * connector_status_unknown. There is no need to call * drm_add_modes_noedid() manually in that case. * * 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(). * * This function is only called after the @detect hook has indicated * that a sink is connected and when the EDID isn't overridden through * sysfs or the kernel commandline. * * This callback is used by the probe helpers in e.g. * drm_helper_probe_single_connector_modes(). * * To avoid races with concurrent connector state updates, the helper * libraries always call this with the &drm_mode_config.connection_mutex * held. Because of this it's safe to inspect &drm_connector->state. * * RETURNS: * * The number of modes added by calling drm_mode_probed_add(). */ int (*get_modes)(struct drm_connector *connector);
/** * @detect_ctx: * * Check to see if anything is attached to the connector. The parameter * force is set to false whilst polling, true when checking the * connector due to a user request. force can be used by the driver to * avoid expensive, destructive operations during automated probing. * * This callback is optional, if not implemented the connector will be * considered as always being attached. * * This is the atomic version of &drm_connector_funcs.detect. * * To avoid races against concurrent connector state updates, the * helper libraries always call this with ctx set to a valid context, * and &drm_mode_config.connection_mutex will always be locked with * the ctx parameter set to this ctx. This allows taking additional * locks as required. * * * RETURNS: * * &drm_connector_status indicating the connector's status, * or the error code returned by drm_modeset_lock(), -EDEADLK. */ int (*detect_ctx)(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, bool force);
/** * @mode_valid: * * Callback to validate a mode for a connector, irrespective of the * specific display configuration. * * This callback is used by the probe helpers to filter the mode list * (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 * 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 * held. Because of this it's safe to inspect &drm_connector->state. * * RETURNS: * * Either &drm_mode_status.MODE_OK or one of the failure reasons in &enum * drm_mode_status. */ enumdrm_mode_status(*mode_valid)(struct drm_connector *connector, struct drm_display_mode *mode);
/** * @mode_valid_ctx: * * Callback to validate a mode for a connector, irrespective of the * specific display configuration. * * This callback is used by the probe helpers to filter the mode list * (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, and is the atomic version of * &drm_connector_helper_funcs.mode_valid. * * To allow for accessing the atomic state of modesetting objects, the * helper libraries always call this with ctx set to a valid context, * and &drm_mode_config.connection_mutex will always be locked with * the ctx parameter set to @ctx. This allows for taking additional * locks as required. * * Even though additional locks may be acquired, this callback is * still expected not to take any constraints into account which would * be influenced by the currently set display state - such constraints * should be handled in the driver's atomic check. For example, if a * connector shares display bandwidth with other connectors then it * would be ok to validate the minimum bandwidth requirement of a mode * against the maximum possible bandwidth of the connector. But it * wouldn't be ok to take the current bandwidth usage of other * connectors into account, as this would change depending on the * display state. * * Returns: * 0 if &drm_connector_helper_funcs.mode_valid_ctx succeeded and wrote * the &enum drm_mode_status value to @status, or a negative error * code otherwise. * */ int (*mode_valid_ctx)(struct drm_connector *connector, struct drm_display_mode *mode, struct drm_modeset_acquire_ctx *ctx, enum drm_mode_status *status);
/** * @best_encoder: * * This function should select the best encoder for the given connector. * * This function is used by both the atomic helpers (in the * drm_atomic_helper_check_modeset() function) and in the legacy CRTC * helpers. * * NOTE: * * In atomic drivers this function is called in the check phase of an * atomic update. The driver is not allowed to change or inspect * anything outside of arguments passed-in. Atomic drivers which need to * inspect dynamic configuration state should instead use * @atomic_best_encoder. * * You can leave this function to NULL if the connector is only * attached to a single encoder. In this case, the core will call * drm_connector_get_single_encoder() for you. * * RETURNS: * * Encoder that should be used for the given connector and connector * state, or NULL if no suitable encoder exists. Note that the helpers * will ensure that encoders aren't used twice, drivers should not check * for this. */ structdrm_encoder *(*best_encoder)(structdrm_connector *connector); /** * @atomic_best_encoder: * * This is the atomic version of @best_encoder for atomic drivers which * need to select the best encoder depending upon the desired * configuration and can't select it statically. * * This function is used by drm_atomic_helper_check_modeset(). * If it is not implemented, the core will fallback to @best_encoder * (or drm_connector_get_single_encoder() if @best_encoder is NULL). * * NOTE: * * This function is called in the check phase of an atomic update. The * driver is not allowed to change anything outside of the * &drm_atomic_state update tracking structure passed in. * * RETURNS: * * Encoder that should be used for the given connector and connector * state, or NULL if no suitable encoder exists. Note that the helpers * will ensure that encoders aren't used twice, drivers should not check * for this. */ structdrm_encoder *(*atomic_best_encoder)(structdrm_connector *connector, structdrm_atomic_state *state);
/** * @atomic_check: * * This hook is used to validate connector state. This function is * called from &drm_atomic_helper_check_modeset, and is called when * a connector property is set, or a modeset on the crtc is forced. * * Because &drm_atomic_helper_check_modeset may be called multiple times, * this function should handle being called multiple times as well. * * This function is also allowed to inspect any other object's state and * can add more state objects to the atomic commit if needed. Care must * be taken though to ensure that state check and compute functions for * these added states are all called, and derived state in other objects * all updated. Again the recommendation is to just call check helpers * until a maximal configuration is reached. * * NOTE: * * This function is called in the check phase of an atomic update. The * driver is not allowed to change anything outside of the free-standing * state objects passed-in or assembled in the overall &drm_atomic_state * update tracking structure. * * RETURNS: * * 0 on success, -EINVAL if the state or the transition can't be * supported, -ENOMEM on memory allocation failure and -EDEADLK if an * attempt to obtain another state object ran into a &drm_modeset_lock * deadlock. */ int (*atomic_check)(struct drm_connector *connector, struct drm_atomic_state *state); /** * @atomic_commit: * * This hook is to be used by drivers implementing writeback connectors * that need a point when to commit the writeback job to the hardware. * The writeback_job to commit is available in the new connector state, * in &drm_connector_state.writeback_job. * * This hook is optional. * * This callback is used by the atomic modeset helpers. */ void (*atomic_commit)(struct drm_connector *connector, struct drm_atomic_state *state);
/** * @prepare_writeback_job: * * As writeback jobs contain a framebuffer, drivers may need to * prepare and clean them up the same way they can prepare and * clean up framebuffers for planes. This optional connector operation * is used to support the preparation of writeback jobs. The job * prepare operation is called from drm_atomic_helper_prepare_planes() * for struct &drm_writeback_connector connectors only. * * This operation is optional. * * This callback is used by the atomic modeset helpers. */ int (*prepare_writeback_job)(struct drm_writeback_connector *connector, struct drm_writeback_job *job); /** * @cleanup_writeback_job: * * This optional connector operation is used to support the * cleanup of writeback jobs. The job cleanup operation is called * from the existing drm_writeback_cleanup_job() function, invoked * both when destroying the job as part of an aborted commit, or when * the job completes. * * This operation is optional. * * This callback is used by the atomic modeset helpers. */ void (*cleanup_writeback_job)(struct drm_writeback_connector *connector, struct drm_writeback_job *job);
/** * @enable_hpd: * * Enable hot-plug detection for the connector. * * This operation is optional. * * This callback is used by the drm_kms_helper_poll_enable() helpers. */ void (*enable_hpd)(struct drm_connector *connector);
/** * @disable_hpd: * * Disable hot-plug detection for the connector. * * This operation is optional. * * This callback is used by the drm_kms_helper_poll_disable() helpers. */ void (*disable_hpd)(struct drm_connector *connector); };
/** * drm_encoder_init - Init a preallocated encoder * @dev: drm device * @encoder: the encoder to init * @funcs: callbacks for this encoder * @encoder_type: user visible type of the encoder * @name: printf style format string for the encoder name, or NULL for default name * * Initializes a preallocated encoder. Encoder should be subclassed as part of * driver encoder objects. At driver unload time the driver's * &drm_encoder_funcs.destroy hook should call drm_encoder_cleanup() and kfree() * the encoder structure. The encoder structure should not be allocated with * devm_kzalloc(). * * Note: consider using drmm_encoder_alloc() or drmm_encoder_init() * instead of drm_encoder_init() to let the DRM managed resource * infrastructure take care of cleanup and deallocation. * * Returns: * Zero on success, error code on failure. */ intdrm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder, const struct drm_encoder_funcs *funcs, int encoder_type, constchar *name, ...) { va_list ap; int ret;
/** * drm_connector_init - Init a preallocated connector * @dev: DRM device * @connector: the connector to init * @funcs: callbacks for this connector * @connector_type: user visible type of the connector * * Initialises a preallocated connector. Connectors should be * subclassed as part of driver connector objects. * * At driver unload time the driver's &drm_connector_funcs.destroy hook * should call drm_connector_cleanup() and free the connector structure. * The connector structure should not be allocated with devm_kzalloc(). * * Note: consider using drmm_connector_init() instead of * drm_connector_init() to let the DRM managed resource infrastructure * take care of cleanup and deallocation. * * Returns: * Zero on success, error code on failure. */ intdrm_connector_init(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, int connector_type) { if (drm_WARN_ON(dev, !(funcs && funcs->destroy))) return -EINVAL;
/* connector index is used with 32bit bitmasks */ ret = ida_alloc_max(&config->connector_ida, 31, GFP_KERNEL); if (ret < 0) { DRM_DEBUG_KMS("Failed to allocate %s connector index: %d\n", drm_connector_enum_list[connector_type].name, ret); goto out_put; } connector->index = ret; ret = 0;
connector->connector_type = connector_type; connector->connector_type_id = ida_alloc_min(connector_ida, 1, GFP_KERNEL); if (connector->connector_type_id < 0) { ret = connector->connector_type_id; goto out_put_id; } connector->name = kasprintf(GFP_KERNEL, "%s-%d", drm_connector_enum_list[connector_type].name, connector->connector_type_id); if (!connector->name) { ret = -ENOMEM; goto out_put_type_id; }
/* provide ddc symlink in sysfs */ connector->ddc = ddc;
/* We should add connectors at the end to avoid upsetting the connector * index too much. */ spin_lock_irq(&config->connector_list_lock); list_add_tail(&connector->head, &config->connector_list); config->num_connector++; spin_unlock_irq(&config->connector_list_lock);
if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL && connector_type != DRM_MODE_CONNECTOR_WRITEBACK) drm_connector_attach_edid_property(connector);