2010-01-21 11:39:52 +03:00
/*
* uvc_entity . c - - USB Video Class driver
*
* Copyright ( C ) 2005 - 2011
* Laurent Pinchart ( laurent . pinchart @ ideasonboard . com )
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
*/
# include <linux/kernel.h>
# include <linux/list.h>
# include <linux/videodev2.h>
# include <media/v4l2-common.h>
# include "uvcvideo.h"
2015-12-11 20:16:34 +03:00
static int uvc_mc_create_links ( struct uvc_video_chain * chain ,
2015-09-03 14:46:06 +03:00
struct uvc_entity * entity )
2010-01-21 11:39:52 +03:00
{
const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE ;
2011-06-29 01:17:48 +04:00
struct media_entity * sink ;
2010-01-21 11:39:52 +03:00
unsigned int i ;
2011-06-29 01:17:48 +04:00
int ret ;
sink = ( UVC_ENTITY_TYPE ( entity ) = = UVC_TT_STREAMING )
? ( entity - > vdev ? & entity - > vdev - > entity : NULL )
: & entity - > subdev . entity ;
if ( sink = = NULL )
return 0 ;
2010-01-21 11:39:52 +03:00
for ( i = 0 ; i < entity - > num_pads ; + + i ) {
2010-01-21 14:56:19 +03:00
struct media_entity * source ;
2011-06-29 01:17:48 +04:00
struct uvc_entity * remote ;
u8 remote_pad ;
2010-01-21 14:56:19 +03:00
2010-01-21 11:39:52 +03:00
if ( ! ( entity - > pads [ i ] . flags & MEDIA_PAD_FL_SINK ) )
continue ;
remote = uvc_entity_by_id ( chain - > dev , entity - > baSourceID [ i ] ) ;
if ( remote = = NULL )
return - EINVAL ;
2011-09-07 02:16:18 +04:00
source = ( UVC_ENTITY_TYPE ( remote ) = = UVC_TT_STREAMING )
2011-06-29 01:17:48 +04:00
? ( remote - > vdev ? & remote - > vdev - > entity : NULL )
: & remote - > subdev . entity ;
if ( source = = NULL )
continue ;
2010-01-21 14:56:19 +03:00
2010-01-21 11:39:52 +03:00
remote_pad = remote - > num_pads - 1 ;
2015-08-07 14:14:38 +03:00
ret = media_create_pad_link ( source , remote_pad ,
2010-01-21 14:56:19 +03:00
sink , i , flags ) ;
2010-01-21 11:39:52 +03:00
if ( ret < 0 )
return ret ;
}
2015-09-03 14:46:06 +03:00
return 0 ;
2010-01-21 11:39:52 +03:00
}
2017-08-08 15:56:24 +03:00
static const struct v4l2_subdev_ops uvc_subdev_ops = {
2010-01-21 11:39:52 +03:00
} ;
void uvc_mc_cleanup_entity ( struct uvc_entity * entity )
{
2010-01-21 14:56:19 +03:00
if ( UVC_ENTITY_TYPE ( entity ) ! = UVC_TT_STREAMING )
media_entity_cleanup ( & entity - > subdev . entity ) ;
else if ( entity - > vdev ! = NULL )
media_entity_cleanup ( & entity - > vdev - > entity ) ;
2010-01-21 11:39:52 +03:00
}
2015-12-11 20:16:35 +03:00
static int uvc_mc_init_entity ( struct uvc_video_chain * chain ,
struct uvc_entity * entity )
2010-01-21 11:39:52 +03:00
{
2010-01-21 14:56:19 +03:00
int ret ;
if ( UVC_ENTITY_TYPE ( entity ) ! = UVC_TT_STREAMING ) {
v4l2_subdev_init ( & entity - > subdev , & uvc_subdev_ops ) ;
strlcpy ( entity - > subdev . name , entity - > name ,
sizeof ( entity - > subdev . name ) ) ;
2015-12-11 12:44:40 +03:00
ret = media_entity_pads_init ( & entity - > subdev . entity ,
2015-08-06 15:25:57 +03:00
entity - > num_pads , entity - > pads ) ;
2015-12-11 20:16:35 +03:00
if ( ret < 0 )
return ret ;
ret = v4l2_device_register_subdev ( & chain - > dev - > vdev ,
& entity - > subdev ) ;
2011-06-29 01:17:48 +04:00
} else if ( entity - > vdev ! = NULL ) {
2015-12-11 12:44:40 +03:00
ret = media_entity_pads_init ( & entity - > vdev - > entity ,
2015-08-06 15:25:57 +03:00
entity - > num_pads , entity - > pads ) ;
2012-08-03 11:35:10 +04:00
if ( entity - > flags & UVC_ENTITY_FLAG_DEFAULT )
entity - > vdev - > entity . flags | = MEDIA_ENT_FL_DEFAULT ;
2011-06-29 01:17:48 +04:00
} else
ret = 0 ;
2010-01-21 11:39:52 +03:00
2010-01-21 14:56:19 +03:00
return ret ;
2010-01-21 11:39:52 +03:00
}
int uvc_mc_register_entities ( struct uvc_video_chain * chain )
{
struct uvc_entity * entity ;
int ret ;
list_for_each_entry ( entity , & chain - > entities , chain ) {
2015-12-11 20:16:35 +03:00
ret = uvc_mc_init_entity ( chain , entity ) ;
2010-01-21 11:39:52 +03:00
if ( ret < 0 ) {
uvc_printk ( KERN_INFO , " Failed to initialize entity for "
" entity %u \n " , entity - > id ) ;
return ret ;
}
}
2015-09-03 14:46:06 +03:00
list_for_each_entry ( entity , & chain - > entities , chain ) {
2015-12-11 20:16:34 +03:00
ret = uvc_mc_create_links ( chain , entity ) ;
2015-09-03 14:46:06 +03:00
if ( ret < 0 ) {
2015-12-11 20:16:34 +03:00
uvc_printk ( KERN_INFO , " Failed to create links for "
2015-09-03 14:46:06 +03:00
" entity %u \n " , entity - > id ) ;
return ret ;
}
}
2010-01-21 11:39:52 +03:00
return 0 ;
}