2018-04-22 17:33:20 -04:00
// SPDX-License-Identifier: GPL-2.0+
2013-06-04 11:22:30 -03:00
/*
* vsp1_entity . c - - R - Car VSP1 Base Entity
*
2014-02-06 14:42:31 -03:00
* Copyright ( C ) 2013 - 2014 Renesas Electronics Corporation
2013-06-04 11:22:30 -03:00
*
* Contact : Laurent Pinchart ( laurent . pinchart @ ideasonboard . com )
*/
# include <linux/device.h>
# include <linux/gfp.h>
# include <media/media-entity.h>
2013-07-10 12:03:30 -03:00
# include <media/v4l2-ctrls.h>
2013-06-04 11:22:30 -03:00
# include <media/v4l2-subdev.h>
# include "vsp1.h"
2015-11-01 10:46:25 -02:00
# include "vsp1_dl.h"
2013-06-04 11:22:30 -03:00
# include "vsp1_entity.h"
2016-09-07 09:09:53 -03:00
# include "vsp1_pipe.h"
# include "vsp1_rwpf.h"
2015-11-01 10:46:25 -02:00
2016-09-07 09:09:53 -03:00
void vsp1_entity_route_setup ( struct vsp1_entity * entity ,
struct vsp1_pipeline * pipe ,
2018-05-18 16:42:02 -04:00
struct vsp1_dl_body * dlb )
2015-08-02 18:58:31 -03:00
{
2016-09-07 09:09:53 -03:00
struct vsp1_entity * source ;
2017-05-25 00:16:57 +03:00
u32 route ;
2015-08-02 18:58:31 -03:00
2016-02-24 20:40:22 -03:00
if ( entity - > type = = VSP1_ENTITY_HGO ) {
u32 smppt ;
/*
* The HGO is a special case , its routing is configured on the
* sink pad .
*/
2017-06-25 20:15:22 +03:00
source = entity - > sources [ 0 ] ;
2016-02-24 20:40:22 -03:00
smppt = ( pipe - > output - > entity . index < < VI6_DPR_SMPPT_TGW_SHIFT )
| ( source - > route - > output < < VI6_DPR_SMPPT_PT_SHIFT ) ;
2018-05-18 16:42:02 -04:00
vsp1_dl_body_write ( dlb , VI6_DPR_HGO_SMPPT , smppt ) ;
2016-02-24 20:40:22 -03:00
return ;
2016-09-06 11:38:56 -03:00
} else if ( entity - > type = = VSP1_ENTITY_HGT ) {
u32 smppt ;
/*
* The HGT is a special case , its routing is configured on the
* sink pad .
*/
2017-06-25 20:15:22 +03:00
source = entity - > sources [ 0 ] ;
2016-09-06 11:38:56 -03:00
smppt = ( pipe - > output - > entity . index < < VI6_DPR_SMPPT_TGW_SHIFT )
| ( source - > route - > output < < VI6_DPR_SMPPT_PT_SHIFT ) ;
2018-05-18 16:42:02 -04:00
vsp1_dl_body_write ( dlb , VI6_DPR_HGT_SMPPT , smppt ) ;
2016-09-06 11:38:56 -03:00
return ;
2016-02-24 20:40:22 -03:00
}
2016-09-07 09:09:53 -03:00
source = entity ;
2015-08-02 18:58:31 -03:00
if ( source - > route - > reg = = 0 )
return ;
2017-05-25 00:16:57 +03:00
route = source - > sink - > route - > inputs [ source - > sink_pad ] ;
/*
* The ILV and BRS share the same data path route . The extra BRSSEL bit
* selects between the ILV and BRS .
*/
if ( source - > type = = VSP1_ENTITY_BRS )
route | = VI6_DPR_ROUTE_BRSSEL ;
2018-05-18 16:42:02 -04:00
vsp1_dl_body_write ( dlb , source - > route - > reg , route ) ;
2015-08-02 18:58:31 -03:00
}
2018-05-18 16:42:01 -04:00
void vsp1_entity_configure_stream ( struct vsp1_entity * entity ,
struct vsp1_pipeline * pipe ,
2019-03-11 20:13:43 +02:00
struct vsp1_dl_list * dl ,
2018-05-18 16:42:02 -04:00
struct vsp1_dl_body * dlb )
2018-05-18 16:42:01 -04:00
{
if ( entity - > ops - > configure_stream )
2019-03-11 20:13:43 +02:00
entity - > ops - > configure_stream ( entity , pipe , dl , dlb ) ;
2018-05-18 16:42:01 -04:00
}
void vsp1_entity_configure_frame ( struct vsp1_entity * entity ,
struct vsp1_pipeline * pipe ,
2018-05-18 16:42:02 -04:00
struct vsp1_dl_list * dl ,
struct vsp1_dl_body * dlb )
2018-05-18 16:42:01 -04:00
{
if ( entity - > ops - > configure_frame )
2018-05-18 16:42:02 -04:00
entity - > ops - > configure_frame ( entity , pipe , dl , dlb ) ;
2018-05-18 16:42:01 -04:00
}
void vsp1_entity_configure_partition ( struct vsp1_entity * entity ,
struct vsp1_pipeline * pipe ,
2018-05-18 16:42:02 -04:00
struct vsp1_dl_list * dl ,
struct vsp1_dl_body * dlb )
2018-05-18 16:42:01 -04:00
{
if ( entity - > ops - > configure_partition )
2018-05-18 16:42:02 -04:00
entity - > ops - > configure_partition ( entity , pipe , dl , dlb ) ;
2018-05-18 16:42:01 -04:00
}
2013-06-04 11:22:30 -03:00
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Operations
*/
2015-11-15 19:14:22 -02:00
/**
* vsp1_entity_get_pad_config - Get the pad configuration for an entity
* @ entity : the entity
* @ cfg : the TRY pad configuration
* @ which : configuration selector ( ACTIVE or TRY )
*
2016-06-26 08:09:31 -03:00
* When called with which set to V4L2_SUBDEV_FORMAT_ACTIVE the caller must hold
* the entity lock to access the returned configuration .
*
2015-11-15 19:14:22 -02:00
* Return the pad configuration requested by the which argument . The TRY
* configuration is passed explicitly to the function through the cfg argument
* and simply returned when requested . The ACTIVE configuration comes from the
* entity structure .
*/
struct v4l2_subdev_pad_config *
vsp1_entity_get_pad_config ( struct vsp1_entity * entity ,
2015-03-04 01:47:54 -08:00
struct v4l2_subdev_pad_config * cfg ,
2015-11-15 19:14:22 -02:00
enum v4l2_subdev_format_whence which )
2013-06-04 11:22:30 -03:00
{
switch ( which ) {
case V4L2_SUBDEV_FORMAT_ACTIVE :
2015-11-15 19:14:22 -02:00
return entity - > config ;
case V4L2_SUBDEV_FORMAT_TRY :
2013-06-04 11:22:30 -03:00
default :
2015-11-15 19:14:22 -02:00
return cfg ;
2013-06-04 11:22:30 -03:00
}
}
2015-11-15 19:14:22 -02:00
/**
* vsp1_entity_get_pad_format - Get a pad format from storage for an entity
* @ entity : the entity
* @ cfg : the configuration storage
* @ pad : the pad number
*
* Return the format stored in the given configuration for an entity ' s pad . The
* configuration can be an ACTIVE or TRY configuration .
*/
struct v4l2_mbus_framefmt *
vsp1_entity_get_pad_format ( struct vsp1_entity * entity ,
struct v4l2_subdev_pad_config * cfg ,
unsigned int pad )
{
return v4l2_subdev_get_try_format ( & entity - > subdev , cfg , pad ) ;
}
2016-03-03 20:17:49 -03:00
/**
* vsp1_entity_get_pad_selection - Get a pad selection from storage for entity
* @ entity : the entity
* @ cfg : the configuration storage
* @ pad : the pad number
* @ target : the selection target
*
* Return the selection rectangle stored in the given configuration for an
* entity ' s pad . The configuration can be an ACTIVE or TRY configuration . The
* selection target can be COMPOSE or CROP .
*/
2015-11-15 19:14:22 -02:00
struct v4l2_rect *
2016-03-03 20:17:49 -03:00
vsp1_entity_get_pad_selection ( struct vsp1_entity * entity ,
struct v4l2_subdev_pad_config * cfg ,
unsigned int pad , unsigned int target )
2015-11-15 19:14:22 -02:00
{
2016-03-03 20:17:49 -03:00
switch ( target ) {
case V4L2_SEL_TGT_COMPOSE :
return v4l2_subdev_get_try_compose ( & entity - > subdev , cfg , pad ) ;
case V4L2_SEL_TGT_CROP :
return v4l2_subdev_get_try_crop ( & entity - > subdev , cfg , pad ) ;
default :
return NULL ;
}
2015-11-15 19:14:22 -02:00
}
2013-06-04 11:22:30 -03:00
/*
2015-11-15 20:09:08 -02:00
* vsp1_entity_init_cfg - Initialize formats on all pads
2013-06-04 11:22:30 -03:00
* @ subdev : V4L2 subdevice
2015-03-04 01:47:54 -08:00
* @ cfg : V4L2 subdev pad configuration
2013-06-04 11:22:30 -03:00
*
2015-11-15 20:09:08 -02:00
* Initialize all pad formats with default values in the given pad config . This
* function can be used as a handler for the subdev pad : : init_cfg operation .
2013-06-04 11:22:30 -03:00
*/
2015-11-15 20:09:08 -02:00
int vsp1_entity_init_cfg ( struct v4l2_subdev * subdev ,
struct v4l2_subdev_pad_config * cfg )
2013-06-04 11:22:30 -03:00
{
struct v4l2_subdev_format format ;
unsigned int pad ;
for ( pad = 0 ; pad < subdev - > entity . num_pads - 1 ; + + pad ) {
memset ( & format , 0 , sizeof ( format ) ) ;
format . pad = pad ;
2015-03-04 01:47:54 -08:00
format . which = cfg ? V4L2_SUBDEV_FORMAT_TRY
2013-06-04 11:22:30 -03:00
: V4L2_SUBDEV_FORMAT_ACTIVE ;
2015-03-04 01:47:54 -08:00
v4l2_subdev_call ( subdev , pad , set_fmt , cfg , & format ) ;
2013-06-04 11:22:30 -03:00
}
return 0 ;
}
2016-02-24 21:10:13 -03:00
/*
* vsp1_subdev_get_pad_format - Subdev pad get_fmt handler
* @ subdev : V4L2 subdevice
* @ cfg : V4L2 subdev pad configuration
* @ fmt : V4L2 subdev format
*
* This function implements the subdev get_fmt pad operation . It can be used as
* a direct drop - in for the operation handler .
*/
int vsp1_subdev_get_pad_format ( struct v4l2_subdev * subdev ,
struct v4l2_subdev_pad_config * cfg ,
struct v4l2_subdev_format * fmt )
{
struct vsp1_entity * entity = to_vsp1_entity ( subdev ) ;
struct v4l2_subdev_pad_config * config ;
config = vsp1_entity_get_pad_config ( entity , cfg , fmt - > which ) ;
if ( ! config )
return - EINVAL ;
2016-06-26 08:09:31 -03:00
mutex_lock ( & entity - > lock ) ;
2016-02-24 21:10:13 -03:00
fmt - > format = * vsp1_entity_get_pad_format ( entity , config , fmt - > pad ) ;
2016-06-26 08:09:31 -03:00
mutex_unlock ( & entity - > lock ) ;
2016-02-24 21:10:13 -03:00
return 0 ;
}
2016-02-24 20:25:42 -03:00
/*
* vsp1_subdev_enum_mbus_code - Subdev pad enum_mbus_code handler
* @ subdev : V4L2 subdevice
* @ cfg : V4L2 subdev pad configuration
* @ code : Media bus code enumeration
* @ codes : Array of supported media bus codes
* @ ncodes : Number of supported media bus codes
*
* This function implements the subdev enum_mbus_code pad operation for entities
* that do not support format conversion . It enumerates the given supported
* media bus codes on the sink pad and reports a source pad format identical to
* the sink pad .
*/
int vsp1_subdev_enum_mbus_code ( struct v4l2_subdev * subdev ,
struct v4l2_subdev_pad_config * cfg ,
struct v4l2_subdev_mbus_code_enum * code ,
const unsigned int * codes , unsigned int ncodes )
{
struct vsp1_entity * entity = to_vsp1_entity ( subdev ) ;
if ( code - > pad = = 0 ) {
if ( code - > index > = ncodes )
return - EINVAL ;
code - > code = codes [ code - > index ] ;
} else {
struct v4l2_subdev_pad_config * config ;
struct v4l2_mbus_framefmt * format ;
2017-02-26 10:29:50 -03:00
/*
* The entity can ' t perform format conversion , the sink format
2016-02-24 20:25:42 -03:00
* is always identical to the source format .
*/
if ( code - > index )
return - EINVAL ;
config = vsp1_entity_get_pad_config ( entity , cfg , code - > which ) ;
if ( ! config )
return - EINVAL ;
2016-06-26 08:09:31 -03:00
mutex_lock ( & entity - > lock ) ;
2016-02-24 20:25:42 -03:00
format = vsp1_entity_get_pad_format ( entity , config , 0 ) ;
code - > code = format - > code ;
2016-06-26 08:09:31 -03:00
mutex_unlock ( & entity - > lock ) ;
2016-02-24 20:25:42 -03:00
}
return 0 ;
}
2016-02-24 20:25:42 -03:00
/*
* vsp1_subdev_enum_frame_size - Subdev pad enum_frame_size handler
* @ subdev : V4L2 subdevice
* @ cfg : V4L2 subdev pad configuration
* @ fse : Frame size enumeration
* @ min_width : Minimum image width
* @ min_height : Minimum image height
* @ max_width : Maximum image width
* @ max_height : Maximum image height
*
* This function implements the subdev enum_frame_size pad operation for
* entities that do not support scaling or cropping . It reports the given
* minimum and maximum frame width and height on the sink pad , and a fixed
* source pad size identical to the sink pad .
*/
int vsp1_subdev_enum_frame_size ( struct v4l2_subdev * subdev ,
struct v4l2_subdev_pad_config * cfg ,
struct v4l2_subdev_frame_size_enum * fse ,
unsigned int min_width , unsigned int min_height ,
unsigned int max_width , unsigned int max_height )
{
struct vsp1_entity * entity = to_vsp1_entity ( subdev ) ;
struct v4l2_subdev_pad_config * config ;
struct v4l2_mbus_framefmt * format ;
2016-06-26 08:09:31 -03:00
int ret = 0 ;
2016-02-24 20:25:42 -03:00
config = vsp1_entity_get_pad_config ( entity , cfg , fse - > which ) ;
if ( ! config )
return - EINVAL ;
format = vsp1_entity_get_pad_format ( entity , config , fse - > pad ) ;
2016-06-26 08:09:31 -03:00
mutex_lock ( & entity - > lock ) ;
if ( fse - > index | | fse - > code ! = format - > code ) {
ret = - EINVAL ;
goto done ;
}
2016-02-24 20:25:42 -03:00
if ( fse - > pad = = 0 ) {
fse - > min_width = min_width ;
fse - > max_width = max_width ;
fse - > min_height = min_height ;
fse - > max_height = max_height ;
} else {
2017-02-26 10:29:50 -03:00
/*
* The size on the source pad are fixed and always identical to
2016-02-24 20:25:42 -03:00
* the size on the sink pad .
*/
fse - > min_width = format - > width ;
fse - > max_width = format - > width ;
fse - > min_height = format - > height ;
fse - > max_height = format - > height ;
}
2016-06-26 08:09:31 -03:00
done :
mutex_unlock ( & entity - > lock ) ;
return ret ;
2016-02-24 20:25:42 -03:00
}
2017-11-27 14:59:45 -05:00
/*
* vsp1_subdev_set_pad_format - Subdev pad set_fmt handler
* @ subdev : V4L2 subdevice
* @ cfg : V4L2 subdev pad configuration
* @ fmt : V4L2 subdev format
* @ codes : Array of supported media bus codes
* @ ncodes : Number of supported media bus codes
* @ min_width : Minimum image width
* @ min_height : Minimum image height
* @ max_width : Maximum image width
* @ max_height : Maximum image height
*
* This function implements the subdev set_fmt pad operation for entities that
* do not support scaling or cropping . It defaults to the first supplied media
* bus code if the requested code isn ' t supported , clamps the size to the
* supplied minimum and maximum , and propagates the sink pad format to the
* source pad .
*/
int vsp1_subdev_set_pad_format ( struct v4l2_subdev * subdev ,
struct v4l2_subdev_pad_config * cfg ,
struct v4l2_subdev_format * fmt ,
const unsigned int * codes , unsigned int ncodes ,
unsigned int min_width , unsigned int min_height ,
unsigned int max_width , unsigned int max_height )
{
struct vsp1_entity * entity = to_vsp1_entity ( subdev ) ;
struct v4l2_subdev_pad_config * config ;
struct v4l2_mbus_framefmt * format ;
2017-11-27 19:27:32 -05:00
struct v4l2_rect * selection ;
2017-11-27 14:59:45 -05:00
unsigned int i ;
int ret = 0 ;
mutex_lock ( & entity - > lock ) ;
config = vsp1_entity_get_pad_config ( entity , cfg , fmt - > which ) ;
if ( ! config ) {
ret = - EINVAL ;
goto done ;
}
format = vsp1_entity_get_pad_format ( entity , config , fmt - > pad ) ;
if ( fmt - > pad = = entity - > source_pad ) {
/* The output format can't be modified. */
fmt - > format = * format ;
goto done ;
}
/*
* Default to the first media bus code if the requested format is not
* supported .
*/
for ( i = 0 ; i < ncodes ; + + i ) {
if ( fmt - > format . code = = codes [ i ] )
break ;
}
format - > code = i < ncodes ? codes [ i ] : codes [ 0 ] ;
format - > width = clamp_t ( unsigned int , fmt - > format . width ,
min_width , max_width ) ;
format - > height = clamp_t ( unsigned int , fmt - > format . height ,
min_height , max_height ) ;
format - > field = V4L2_FIELD_NONE ;
format - > colorspace = V4L2_COLORSPACE_SRGB ;
fmt - > format = * format ;
/* Propagate the format to the source pad. */
format = vsp1_entity_get_pad_format ( entity , config , entity - > source_pad ) ;
* format = fmt - > format ;
2018-08-31 10:40:44 -04:00
/* Reset the crop and compose rectangles. */
2017-11-27 19:27:32 -05:00
selection = vsp1_entity_get_pad_selection ( entity , config , fmt - > pad ,
V4L2_SEL_TGT_CROP ) ;
selection - > left = 0 ;
selection - > top = 0 ;
selection - > width = format - > width ;
selection - > height = format - > height ;
selection = vsp1_entity_get_pad_selection ( entity , config , fmt - > pad ,
V4L2_SEL_TGT_COMPOSE ) ;
selection - > left = 0 ;
selection - > top = 0 ;
selection - > width = format - > width ;
selection - > height = format - > height ;
2017-11-27 14:59:45 -05:00
done :
mutex_unlock ( & entity - > lock ) ;
return ret ;
}
2013-06-04 11:22:30 -03:00
/* -----------------------------------------------------------------------------
* Media Operations
*/
2017-06-25 20:15:22 +03:00
static inline struct vsp1_entity *
media_entity_to_vsp1_entity ( struct media_entity * entity )
{
return container_of ( entity , struct vsp1_entity , subdev . entity ) ;
}
2016-09-07 09:09:53 -03:00
static int vsp1_entity_link_setup_source ( const struct media_pad * source_pad ,
const struct media_pad * sink_pad ,
u32 flags )
2013-06-04 11:22:30 -03:00
{
struct vsp1_entity * source ;
2016-09-07 09:09:53 -03:00
source = media_entity_to_vsp1_entity ( source_pad - > entity ) ;
2013-06-04 11:22:30 -03:00
if ( ! source - > route )
return 0 ;
if ( flags & MEDIA_LNK_FL_ENABLED ) {
2016-09-07 09:09:53 -03:00
struct vsp1_entity * sink
= media_entity_to_vsp1_entity ( sink_pad - > entity ) ;
/*
* Fan - out is limited to one for the normal data path plus
* optional HGO and HGT . We ignore the HGO and HGT here .
*/
if ( sink - > type ! = VSP1_ENTITY_HGO & &
sink - > type ! = VSP1_ENTITY_HGT ) {
if ( source - > sink )
return - EBUSY ;
2017-06-25 20:15:22 +03:00
source - > sink = sink ;
2016-09-07 09:09:53 -03:00
source - > sink_pad = sink_pad - > index ;
}
2013-06-04 11:22:30 -03:00
} else {
source - > sink = NULL ;
2013-07-10 18:37:27 -03:00
source - > sink_pad = 0 ;
2013-06-04 11:22:30 -03:00
}
return 0 ;
}
2016-09-07 09:09:53 -03:00
static int vsp1_entity_link_setup_sink ( const struct media_pad * source_pad ,
const struct media_pad * sink_pad ,
u32 flags )
{
struct vsp1_entity * sink ;
2017-06-25 20:15:22 +03:00
struct vsp1_entity * source ;
2016-09-07 09:09:53 -03:00
sink = media_entity_to_vsp1_entity ( sink_pad - > entity ) ;
2017-06-25 20:15:22 +03:00
source = media_entity_to_vsp1_entity ( source_pad - > entity ) ;
2016-09-07 09:09:53 -03:00
if ( flags & MEDIA_LNK_FL_ENABLED ) {
/* Fan-in is limited to one. */
if ( sink - > sources [ sink_pad - > index ] )
return - EBUSY ;
2017-06-25 20:15:22 +03:00
sink - > sources [ sink_pad - > index ] = source ;
2016-09-07 09:09:53 -03:00
} else {
sink - > sources [ sink_pad - > index ] = NULL ;
}
return 0 ;
}
int vsp1_entity_link_setup ( struct media_entity * entity ,
const struct media_pad * local ,
const struct media_pad * remote , u32 flags )
{
if ( local - > flags & MEDIA_PAD_FL_SOURCE )
return vsp1_entity_link_setup_source ( local , remote , flags ) ;
else
return vsp1_entity_link_setup_sink ( remote , local , flags ) ;
}
/**
* vsp1_entity_remote_pad - Find the pad at the remote end of a link
* @ pad : Pad at the local end of the link
*
* Search for a remote pad connected to the given pad by iterating over all
* links originating or terminating at that pad until an enabled link is found .
*
* Our link setup implementation guarantees that the output fan - out will not be
* higher than one for the data pipelines , except for the links to the HGO and
* HGT that can be enabled in addition to a regular data link . When traversing
* outgoing links this function ignores HGO and HGT entities and should thus be
* used in place of the generic media_entity_remote_pad ( ) function to traverse
* data pipelines .
*
* Return a pointer to the pad at the remote end of the first found enabled
* link , or NULL if no enabled link has been found .
*/
struct media_pad * vsp1_entity_remote_pad ( struct media_pad * pad )
{
struct media_link * link ;
list_for_each_entry ( link , & pad - > entity - > links , list ) {
struct vsp1_entity * entity ;
if ( ! ( link - > flags & MEDIA_LNK_FL_ENABLED ) )
continue ;
/* If we're the sink the source will never be an HGO or HGT. */
if ( link - > sink = = pad )
return link - > source ;
if ( link - > source ! = pad )
continue ;
/* If the sink isn't a subdevice it can't be an HGO or HGT. */
if ( ! is_media_entity_v4l2_subdev ( link - > sink - > entity ) )
return link - > sink ;
entity = media_entity_to_vsp1_entity ( link - > sink - > entity ) ;
if ( entity - > type ! = VSP1_ENTITY_HGO & &
entity - > type ! = VSP1_ENTITY_HGT )
return link - > sink ;
}
return NULL ;
}
2013-06-04 11:22:30 -03:00
/* -----------------------------------------------------------------------------
* Initialization
*/
2016-02-24 19:10:04 -03:00
# define VSP1_ENTITY_ROUTE(ent) \
{ VSP1_ENTITY_ # # ent , 0 , VI6_DPR_ # # ent # # _ROUTE , \
{ VI6_DPR_NODE_ # # ent } , VI6_DPR_NODE_ # # ent }
# define VSP1_ENTITY_ROUTE_RPF(idx) \
{ VSP1_ENTITY_RPF , idx , VI6_DPR_RPF_ROUTE ( idx ) , \
{ 0 , } , VI6_DPR_NODE_RPF ( idx ) }
# define VSP1_ENTITY_ROUTE_UDS(idx) \
{ VSP1_ENTITY_UDS , idx , VI6_DPR_UDS_ROUTE ( idx ) , \
{ VI6_DPR_NODE_UDS ( idx ) } , VI6_DPR_NODE_UDS ( idx ) }
2017-11-27 15:45:42 -05:00
# define VSP1_ENTITY_ROUTE_UIF(idx) \
{ VSP1_ENTITY_UIF , idx , VI6_DPR_UIF_ROUTE ( idx ) , \
{ VI6_DPR_NODE_UIF ( idx ) } , VI6_DPR_NODE_UIF ( idx ) }
2016-02-24 19:10:04 -03:00
# define VSP1_ENTITY_ROUTE_WPF(idx) \
{ VSP1_ENTITY_WPF , idx , 0 , \
{ VI6_DPR_NODE_WPF ( idx ) } , VI6_DPR_NODE_WPF ( idx ) }
2013-07-10 18:37:27 -03:00
static const struct vsp1_route vsp1_routes [ ] = {
2017-05-25 00:16:57 +03:00
{ VSP1_ENTITY_BRS , 0 , VI6_DPR_ILV_BRS_ROUTE ,
{ VI6_DPR_NODE_BRS_IN ( 0 ) , VI6_DPR_NODE_BRS_IN ( 1 ) } , 0 } ,
2013-07-10 18:03:46 -03:00
{ VSP1_ENTITY_BRU , 0 , VI6_DPR_BRU_ROUTE ,
{ VI6_DPR_NODE_BRU_IN ( 0 ) , VI6_DPR_NODE_BRU_IN ( 1 ) ,
2015-09-07 08:05:39 -03:00
VI6_DPR_NODE_BRU_IN ( 2 ) , VI6_DPR_NODE_BRU_IN ( 3 ) ,
2016-02-24 19:10:04 -03:00
VI6_DPR_NODE_BRU_IN ( 4 ) } , VI6_DPR_NODE_BRU_OUT } ,
2015-11-11 23:04:44 -02:00
VSP1_ENTITY_ROUTE ( CLU ) ,
2016-02-24 20:40:22 -03:00
{ VSP1_ENTITY_HGO , 0 , 0 , { 0 , } , 0 } ,
2016-09-06 11:38:56 -03:00
{ VSP1_ENTITY_HGT , 0 , 0 , { 0 , } , 0 } ,
2016-02-24 19:10:04 -03:00
VSP1_ENTITY_ROUTE ( HSI ) ,
VSP1_ENTITY_ROUTE ( HST ) ,
2017-06-21 16:10:18 +03:00
{ VSP1_ENTITY_LIF , 0 , 0 , { 0 , } , 0 } ,
{ VSP1_ENTITY_LIF , 1 , 0 , { 0 , } , 0 } ,
2016-02-24 19:10:04 -03:00
VSP1_ENTITY_ROUTE ( LUT ) ,
VSP1_ENTITY_ROUTE_RPF ( 0 ) ,
VSP1_ENTITY_ROUTE_RPF ( 1 ) ,
VSP1_ENTITY_ROUTE_RPF ( 2 ) ,
VSP1_ENTITY_ROUTE_RPF ( 3 ) ,
VSP1_ENTITY_ROUTE_RPF ( 4 ) ,
VSP1_ENTITY_ROUTE ( SRU ) ,
VSP1_ENTITY_ROUTE_UDS ( 0 ) ,
VSP1_ENTITY_ROUTE_UDS ( 1 ) ,
VSP1_ENTITY_ROUTE_UDS ( 2 ) ,
2017-11-27 15:45:42 -05:00
VSP1_ENTITY_ROUTE_UIF ( 0 ) , /* Named UIF4 in the documentation */
VSP1_ENTITY_ROUTE_UIF ( 1 ) , /* Named UIF5 in the documentation */
2016-02-24 19:10:04 -03:00
VSP1_ENTITY_ROUTE_WPF ( 0 ) ,
VSP1_ENTITY_ROUTE_WPF ( 1 ) ,
VSP1_ENTITY_ROUTE_WPF ( 2 ) ,
VSP1_ENTITY_ROUTE_WPF ( 3 ) ,
2013-07-10 18:37:27 -03:00
} ;
2013-06-04 11:22:30 -03:00
int vsp1_entity_init ( struct vsp1_device * vsp1 , struct vsp1_entity * entity ,
2015-11-15 19:42:01 -02:00
const char * name , unsigned int num_pads ,
2016-02-15 22:10:26 -02:00
const struct v4l2_subdev_ops * ops , u32 function )
2013-06-04 11:22:30 -03:00
{
2015-11-15 19:42:01 -02:00
struct v4l2_subdev * subdev ;
2013-06-04 11:22:30 -03:00
unsigned int i ;
2015-11-15 19:42:01 -02:00
int ret ;
2013-06-04 11:22:30 -03:00
2013-07-10 18:37:27 -03:00
for ( i = 0 ; i < ARRAY_SIZE ( vsp1_routes ) ; + + i ) {
if ( vsp1_routes [ i ] . type = = entity - > type & &
vsp1_routes [ i ] . index = = entity - > index ) {
entity - > route = & vsp1_routes [ i ] ;
2013-06-04 11:22:30 -03:00
break ;
}
}
2013-07-10 18:37:27 -03:00
if ( i = = ARRAY_SIZE ( vsp1_routes ) )
2013-06-04 11:22:30 -03:00
return - EINVAL ;
2016-06-26 08:09:31 -03:00
mutex_init ( & entity - > lock ) ;
2013-06-04 11:22:30 -03:00
entity - > vsp1 = vsp1 ;
entity - > source_pad = num_pads - 1 ;
2015-11-15 19:14:22 -02:00
/* Allocate and initialize pads. */
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 14:07:58 -07:00
entity - > pads = devm_kcalloc ( vsp1 - > dev ,
num_pads , sizeof ( * entity - > pads ) ,
2013-06-04 11:22:30 -03:00
GFP_KERNEL ) ;
if ( entity - > pads = = NULL )
return - ENOMEM ;
for ( i = 0 ; i < num_pads - 1 ; + + i )
entity - > pads [ i ] . flags = MEDIA_PAD_FL_SINK ;
2016-09-07 09:09:53 -03:00
entity - > sources = devm_kcalloc ( vsp1 - > dev , max ( num_pads - 1 , 1U ) ,
sizeof ( * entity - > sources ) , GFP_KERNEL ) ;
if ( entity - > sources = = NULL )
return - ENOMEM ;
/* Single-pad entities only have a sink. */
entity - > pads [ num_pads - 1 ] . flags = num_pads > 1 ? MEDIA_PAD_FL_SOURCE
: MEDIA_PAD_FL_SINK ;
2013-06-04 11:22:30 -03:00
/* Initialize the media entity. */
2015-11-15 19:42:01 -02:00
ret = media_entity_pads_init ( & entity - > subdev . entity , num_pads ,
entity - > pads ) ;
if ( ret < 0 )
return ret ;
/* Initialize the V4L2 subdev. */
subdev = & entity - > subdev ;
v4l2_subdev_init ( subdev , ops ) ;
2016-02-15 22:10:26 -02:00
subdev - > entity . function = function ;
2015-11-15 19:42:01 -02:00
subdev - > entity . ops = & vsp1 - > media_ops ;
subdev - > flags | = V4L2_SUBDEV_FL_HAS_DEVNODE ;
snprintf ( subdev - > name , sizeof ( subdev - > name ) , " %s %s " ,
dev_name ( vsp1 - > dev ) , name ) ;
2015-11-15 20:09:08 -02:00
vsp1_entity_init_cfg ( subdev , NULL ) ;
2015-11-15 19:42:01 -02:00
2017-02-26 10:29:50 -03:00
/*
* Allocate the pad configuration to store formats and selection
2015-11-15 19:14:22 -02:00
* rectangles .
*/
entity - > config = v4l2_subdev_alloc_pad_config ( & entity - > subdev ) ;
if ( entity - > config = = NULL ) {
media_entity_cleanup ( & entity - > subdev . entity ) ;
return - ENOMEM ;
}
2015-11-15 19:42:01 -02:00
return 0 ;
2013-06-04 11:22:30 -03:00
}
void vsp1_entity_destroy ( struct vsp1_entity * entity )
{
2015-11-17 12:23:23 -02:00
if ( entity - > ops & & entity - > ops - > destroy )
entity - > ops - > destroy ( entity ) ;
2013-07-10 12:03:30 -03:00
if ( entity - > subdev . ctrl_handler )
v4l2_ctrl_handler_free ( entity - > subdev . ctrl_handler ) ;
2015-11-15 19:14:22 -02:00
v4l2_subdev_free_pad_config ( entity - > config ) ;
2013-06-04 11:22:30 -03:00
media_entity_cleanup ( & entity - > subdev . entity ) ;
}