2016-08-29 11:27:49 +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_ENCODER_H__
# define __DRM_ENCODER_H__
# include <linux/list.h>
# include <linux/ctype.h>
2016-11-28 22:03:49 +03:00
# include <drm/drm_crtc.h>
2016-11-28 21:51:09 +03:00
# include <drm/drm_mode.h>
2016-08-29 11:27:51 +03:00
# include <drm/drm_mode_object.h>
2018-09-05 16:57:05 +03:00
# include <drm/drm_util.h>
2016-08-29 11:27:49 +03:00
2016-11-28 21:51:09 +03:00
struct drm_encoder ;
2016-08-29 11:27:49 +03:00
/**
* struct drm_encoder_funcs - encoder controls
*
* Encoders sit between CRTCs and connectors .
*/
struct drm_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
2017-01-25 09:26:55 +03:00
* @ late_register . It is called from drm_dev_unregister ( ) ,
2016-08-29 11:27:49 +03:00
* 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 - 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
2020-12-10 18:38:27 +03:00
* @ funcs : control functions , can be NULL for simple managed encoders
2016-08-29 11:27:49 +03:00
* @ 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 .
*/
struct drm_encoder {
struct drm_device * dev ;
struct list_head head ;
struct drm_mode_object base ;
char * name ;
2016-08-29 11:27:50 +03:00
/**
* @ 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 .
*/
2016-08-29 11:27:49 +03:00
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 ;
2016-08-29 11:27:50 +03:00
/**
* @ 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
2019-09-14 01:27:02 +03:00
* before calling drm_dev_register ( ) .
2016-08-29 11:27:50 +03:00
*
2020-02-11 19:22:07 +03:00
* You will get a WARN if you get this wrong in the driver .
2016-08-29 11:27:50 +03:00
*
* Note that since CRTC objects can ' t be hotplugged the assigned indices
* are stable and hence known before registering all objects .
*/
2016-08-29 11:27:49 +03:00
uint32_t possible_crtcs ;
2016-08-29 11:27:50 +03:00
/**
* @ 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
2019-09-14 01:27:01 +03:00
* drm_dev_register ( ) . Drivers should set the bit representing the
2016-08-29 11:27:50 +03:00
* 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 .
*
2020-02-11 19:22:02 +03:00
* 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 .
2016-08-29 11:27:50 +03:00
*
2020-02-11 19:22:06 +03:00
* You will get a WARN if you get this wrong in the driver .
*
2016-08-29 11:27:50 +03:00
* Note that since encoder objects can ' t be hotplugged the assigned indices
* are stable and hence known before registering all objects .
*/
2016-08-29 11:27:49 +03:00
uint32_t possible_clones ;
2017-11-08 23:30:07 +03:00
/**
* @ crtc : Currently bound CRTC , only really meaningful for non - atomic
* drivers . Atomic drivers should instead check
* & drm_connector_state . crtc .
*/
2016-08-29 11:27:49 +03:00
struct drm_crtc * crtc ;
2019-12-03 17:15:08 +03:00
/**
2020-02-26 14:24:24 +03:00
* @ bridge_chain : Bridges attached to this encoder . Drivers shall not
* access this field directly .
2019-12-03 17:15:08 +03:00
*/
struct list_head bridge_chain ;
2016-08-29 11:27:49 +03:00
const struct drm_encoder_funcs * funcs ;
const struct drm_encoder_helper_funcs * helper_private ;
} ;
# define obj_to_encoder(x) container_of(x, struct drm_encoder, base)
__printf ( 5 , 6 )
int drm_encoder_init ( struct drm_device * dev ,
struct drm_encoder * encoder ,
const struct drm_encoder_funcs * funcs ,
int encoder_type , const char * name , . . . ) ;
2020-12-10 18:38:28 +03:00
__printf ( 6 , 7 )
void * __drmm_encoder_alloc ( struct drm_device * dev ,
size_t size , size_t offset ,
const struct drm_encoder_funcs * funcs ,
int encoder_type ,
const char * name , . . . ) ;
/**
* drmm_encoder_alloc - Allocate and initialize an encoder
* @ dev : drm device
* @ type : the type of the struct which contains struct & drm_encoder
* @ member : the name of the & drm_encoder within @ type
* @ funcs : callbacks for this encoder ( optional )
* @ encoder_type : user visible type of the encoder
* @ name : printf style format string for the encoder name , or NULL for default name
*
* Allocates and initializes an encoder . Encoder should be subclassed as part of
* driver encoder objects . Cleanup is automatically handled through registering
* drm_encoder_cleanup ( ) with drmm_add_action ( ) .
*
* The @ drm_encoder_funcs . destroy hook must be NULL .
*
* Returns :
* Pointer to new encoder , or ERR_PTR on failure .
*/
# define drmm_encoder_alloc(dev, type, member, funcs, encoder_type, name, ...) \
( ( type * ) __drmm_encoder_alloc ( dev , sizeof ( type ) , \
offsetof ( type , member ) , funcs , \
encoder_type , name , # # __VA_ARGS__ ) )
2021-03-27 14:57:41 +03:00
/**
* drmm_plain_encoder_alloc - Allocate and initialize an encoder
* @ dev : drm device
* @ funcs : callbacks for this encoder ( optional )
* @ encoder_type : user visible type of the encoder
* @ name : printf style format string for the encoder name , or NULL for default name
*
* This is a simplified version of drmm_encoder_alloc ( ) , which only allocates
* and returns a struct drm_encoder instance , with no subclassing .
*
* Returns :
* Pointer to the new drm_encoder struct , or ERR_PTR on failure .
*/
# define drmm_plain_encoder_alloc(dev, funcs, encoder_type, name, ...) \
( ( struct drm_encoder * ) \
__drmm_encoder_alloc ( dev , sizeof ( struct drm_encoder ) , \
0 , funcs , encoder_type , name , # # __VA_ARGS__ ) )
2016-08-29 11:27:49 +03:00
/**
* drm_encoder_index - find the index of a registered encoder
* @ encoder : encoder to find index for
*
* Given a registered encoder , return the index of that encoder within a DRM
* device ' s list of encoders .
*/
2018-06-26 22:47:09 +03:00
static inline unsigned int drm_encoder_index ( const struct drm_encoder * encoder )
2016-08-29 11:27:49 +03:00
{
return encoder - > index ;
}
2018-06-26 22:47:09 +03:00
/**
2019-09-14 01:27:03 +03:00
* drm_encoder_mask - find the mask of a registered encoder
2018-06-26 22:47:09 +03:00
* @ encoder : encoder to find mask for
*
* Given a registered encoder , return the mask bit of that encoder for an
* encoder ' s possible_clones field .
*/
static inline u32 drm_encoder_mask ( const struct drm_encoder * encoder )
{
return 1 < < drm_encoder_index ( encoder ) ;
}
2016-08-29 11:27:49 +03:00
/**
* drm_encoder_crtc_ok - can a given crtc drive a given encoder ?
* @ encoder : encoder to test
* @ crtc : crtc to test
*
2016-08-29 11:27:50 +03:00
* Returns false if @ encoder can ' t be driven by @ crtc , true otherwise .
2016-08-29 11:27:49 +03:00
*/
static inline bool drm_encoder_crtc_ok ( struct drm_encoder * encoder ,
struct drm_crtc * crtc )
{
return ! ! ( encoder - > possible_crtcs & drm_crtc_mask ( crtc ) ) ;
}
2016-08-29 11:27:50 +03:00
/**
* drm_encoder_find - find a & drm_encoder
* @ dev : DRM device
2017-11-09 02:35:04 +03:00
* @ file_priv : drm file to check for lease against .
2016-08-29 11:27:50 +03:00
* @ id : encoder id
*
* Returns the encoder with @ id , NULL if it doesn ' t exist . Simple wrapper around
* drm_mode_object_find ( ) .
*/
2016-08-29 11:27:49 +03:00
static inline struct drm_encoder * drm_encoder_find ( struct drm_device * dev ,
2017-03-15 09:25:07 +03:00
struct drm_file * file_priv ,
2016-08-29 11:27:50 +03:00
uint32_t id )
2016-08-29 11:27:49 +03:00
{
struct drm_mode_object * mo ;
2016-08-29 11:27:50 +03:00
2017-03-15 09:25:07 +03:00
mo = drm_mode_object_find ( dev , file_priv , id , DRM_MODE_OBJECT_ENCODER ) ;
2016-08-29 11:27:50 +03:00
2016-08-29 11:27:49 +03:00
return mo ? obj_to_encoder ( mo ) : NULL ;
}
void drm_encoder_cleanup ( struct drm_encoder * encoder ) ;
2016-08-31 19:09:04 +03:00
/**
* drm_for_each_encoder_mask - iterate over encoders specified by bitmask
* @ encoder : the loop cursor
* @ dev : the DRM device
* @ encoder_mask : bitmask of encoder indices
*
* Iterate over all encoders specified by bitmask .
*/
# define drm_for_each_encoder_mask(encoder, dev, encoder_mask) \
list_for_each_entry ( ( encoder ) , & ( dev ) - > mode_config . encoder_list , head ) \
2018-06-26 22:47:09 +03:00
for_each_if ( ( encoder_mask ) & drm_encoder_mask ( encoder ) )
2016-08-31 19:09:04 +03:00
/**
* drm_for_each_encoder - iterate over all encoders
* @ encoder : the loop cursor
* @ dev : the DRM device
*
* Iterate over all encoders of @ dev .
*/
# define drm_for_each_encoder(encoder, dev) \
list_for_each_entry ( encoder , & ( dev ) - > mode_config . encoder_list , head )
2016-08-29 11:27:49 +03:00
# endif