2016-08-31 19:09:05 +03:00
/*
* Copyright ( c ) 2016 Intel Corporation
*
* Permission to use , copy , modify , distribute , and sell this software and its
* documentation for any purpose is hereby granted without fee , provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation , and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific ,
* written prior permission . The copyright holders make no representations
* about the suitability of this software for any purpose . It is provided " as
* is " without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE ,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS , IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL , INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE ,
* DATA OR PROFITS , WHETHER IN AN ACTION OF CONTRACT , NEGLIGENCE OR OTHER
* TORTIOUS ACTION , ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE .
*/
# ifndef __DRM_BRIDGE_H__
# define __DRM_BRIDGE_H__
# include <linux/list.h>
# include <linux/ctype.h>
# include <drm/drm_mode_object.h>
# include <drm/drm_modes.h>
struct drm_bridge ;
2018-01-12 10:48:52 +03:00
struct drm_bridge_timings ;
2017-06-02 23:25:14 +03:00
struct drm_panel ;
2016-08-31 19:09:05 +03:00
/**
* struct drm_bridge_funcs - drm_bridge control functions
*/
struct drm_bridge_funcs {
/**
* @ attach :
*
* This callback is invoked whenever our bridge is being attached to a
* & drm_encoder .
*
* The attach callback is optional .
*
* RETURNS :
*
* Zero on success , error code on failure .
*/
int ( * attach ) ( struct drm_bridge * bridge ) ;
/**
* @ 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 ) ;
2017-05-15 12:33:47 +03:00
/**
* @ mode_valid :
*
* This callback is used to check if a specific mode is valid in this
* bridge . This should be implemented if the bridge has some sort of
* restriction in the modes it can display . For example , a given bridge
* may be responsible to set a clock value . If the clock can not
* produce all the values for the available modes then this callback
* can be used to restrict the number of modes to only the ones that
* can be displayed .
*
* This hook is used by the probe helpers to filter the mode list in
* drm_helper_probe_single_connector_modes ( ) , and it is used by the
* atomic helpers to validate modes supplied by userspace in
* drm_atomic_helper_check_modeset ( ) .
*
* This function is optional .
*
* NOTE :
*
* Since this function is both called from the check phase of an atomic
* commit , and the mode validation in the probe paths it is not allowed
* to look at anything else but the passed - in mode , and validate it
* against configuration - invariant hardward constraints . Any further
* limits which depend upon the configuration can only be checked in
* @ mode_fixup .
*
* RETURNS :
*
* drm_mode_status Enum
*/
enum drm_mode_status ( * mode_valid ) ( struct drm_bridge * crtc ,
const struct drm_display_mode * mode ) ;
2016-08-31 19:09:05 +03:00
/**
* @ mode_fixup :
*
* This callback is used to validate and adjust a mode . The paramater
* 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
2017-05-15 12:11:35 +03:00
* match mode . See also & drm_crtc_state . adjusted_mode for more details .
2016-08-31 19:09:05 +03:00
*
* 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 .
*
* 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 .
*
2017-05-15 12:33:47 +03:00
* 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 .
*
2016-08-31 19:09:05 +03:00
* 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
2017-01-02 11:17:26 +03:00
* 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 .
2016-08-31 19:09:05 +03:00
*
* 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 .
*/
void ( * disable ) ( struct drm_bridge * bridge ) ;
/**
* @ post_disable :
*
2017-01-02 11:17:26 +03:00
* 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 .
2016-08-31 19:09:05 +03:00
*
* 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 .
*/
void ( * post_disable ) ( struct drm_bridge * bridge ) ;
/**
* @ mode_set :
*
* This callback should set the given mode on the bridge . It is called
2017-01-02 11:17:26 +03:00
* 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 .
2016-08-31 19:09:05 +03:00
*/
void ( * mode_set ) ( struct drm_bridge * bridge ,
struct drm_display_mode * mode ,
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
2017-01-02 11:17:26 +03:00
* 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 .
2016-08-31 19:09:05 +03:00
*
* 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 .
*/
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
2017-01-02 11:17:26 +03:00
* 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 .
2016-08-31 19:09:05 +03:00
*
* 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 .
*/
void ( * enable ) ( struct drm_bridge * bridge ) ;
} ;
2018-01-12 10:48:52 +03:00
/**
* struct drm_bridge_timings - timing information for the bridge
*/
struct drm_bridge_timings {
/**
* @ sampling_edge :
*
* Tells whether the bridge samples the digital input signal
* from the display engine on the positive or negative edge of the
* clock , this should reuse the DRM_BUS_FLAG_PIXDATA_ [ POS | NEG ] EDGE
* bitwise flags from the DRM connector ( bit 2 and 3 valid ) .
*/
u32 sampling_edge ;
/**
* @ setup_time_ps :
*
* Defines the time in picoseconds the input data lines must be
* stable before the clock edge .
*/
u32 setup_time_ps ;
/**
* @ hold_time_ps :
*
* Defines the time in picoseconds taken for the bridge to sample the
* input signal after the clock edge .
*/
u32 hold_time_ps ;
} ;
2016-08-31 19:09:05 +03:00
/**
* struct drm_bridge - central DRM bridge control structure
* @ dev : DRM device this bridge belongs to
* @ encoder : encoder to which this bridge is connected
* @ next : the next bridge in the encoder chain
* @ of_node : device node pointer to the bridge
* @ list : to keep track of all added bridges
2018-01-12 10:48:52 +03:00
* @ timings : the timing specification for the bridge , if any ( may
* be NULL )
2016-08-31 19:09:05 +03:00
* @ funcs : control functions
* @ driver_private : pointer to the bridge driver ' s internal context
*/
struct drm_bridge {
struct drm_device * dev ;
struct drm_encoder * encoder ;
struct drm_bridge * next ;
# ifdef CONFIG_OF
struct device_node * of_node ;
# endif
struct list_head list ;
2018-01-12 10:48:52 +03:00
const struct drm_bridge_timings * timings ;
2016-08-31 19:09:05 +03:00
const struct drm_bridge_funcs * funcs ;
void * driver_private ;
} ;
2017-07-03 11:42:17 +03:00
void drm_bridge_add ( struct drm_bridge * bridge ) ;
2016-08-31 19:09:05 +03:00
void drm_bridge_remove ( struct drm_bridge * bridge ) ;
struct drm_bridge * of_drm_find_bridge ( struct device_node * np ) ;
2016-11-28 18:59:08 +03:00
int drm_bridge_attach ( struct drm_encoder * encoder , struct drm_bridge * bridge ,
struct drm_bridge * previous ) ;
2016-08-31 19:09:05 +03:00
bool drm_bridge_mode_fixup ( struct drm_bridge * bridge ,
const struct drm_display_mode * mode ,
struct drm_display_mode * adjusted_mode ) ;
2017-05-25 17:19:14 +03:00
enum drm_mode_status drm_bridge_mode_valid ( struct drm_bridge * bridge ,
const struct drm_display_mode * mode ) ;
2016-08-31 19:09:05 +03:00
void drm_bridge_disable ( struct drm_bridge * bridge ) ;
void drm_bridge_post_disable ( struct drm_bridge * bridge ) ;
void drm_bridge_mode_set ( struct drm_bridge * bridge ,
struct drm_display_mode * mode ,
struct drm_display_mode * adjusted_mode ) ;
void drm_bridge_pre_enable ( struct drm_bridge * bridge ) ;
void drm_bridge_enable ( struct drm_bridge * bridge ) ;
2017-06-02 23:25:14 +03:00
# ifdef CONFIG_DRM_PANEL_BRIDGE
struct drm_bridge * drm_panel_bridge_add ( struct drm_panel * panel ,
u32 connector_type ) ;
void drm_panel_bridge_remove ( struct drm_bridge * bridge ) ;
2017-07-19 00:05:06 +03:00
struct drm_bridge * devm_drm_panel_bridge_add ( struct device * dev ,
struct drm_panel * panel ,
u32 connector_type ) ;
2017-06-02 23:25:14 +03:00
# endif
2016-08-31 19:09:05 +03:00
# endif