2009-12-09 14:39:58 +03:00
/*
* Media device
*
* Copyright ( C ) 2010 Nokia Corporation
*
* Contacts : Laurent Pinchart < laurent . pinchart @ ideasonboard . com >
* Sakari Ailus < sakari . ailus @ iki . fi >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# ifndef _MEDIA_DEVICE_H
# define _MEDIA_DEVICE_H
# include <linux/list.h>
2010-03-07 21:04:59 +03:00
# include <linux/mutex.h>
2009-12-09 14:39:58 +03:00
# include <media/media-devnode.h>
2009-12-09 14:40:00 +03:00
# include <media/media-entity.h>
2009-12-09 14:39:58 +03:00
2015-12-16 16:32:17 +03:00
struct ida ;
2012-01-30 20:46:54 +04:00
struct device ;
2016-02-12 02:41:21 +03:00
/**
* struct media_entity_notify - Media Entity Notify
*
* @ list : List head
* @ notify_data : Input data to invoke the callback
* @ notify : Callback function pointer
*
* Drivers may register a callback to take action when
* new entities get registered with the media device .
*/
struct media_entity_notify {
struct list_head list ;
void * notify_data ;
void ( * notify ) ( struct media_entity * entity , void * notify_data ) ;
} ;
2009-12-09 14:39:58 +03:00
/**
* struct media_device - Media device
* @ dev : Parent device
* @ devnode : Media device node
2016-02-11 19:24:23 +03:00
* @ driver_name : Optional device driver name . If not set , calls to
* % MEDIA_IOC_DEVICE_INFO will return dev - > driver - > name .
* This is needed for USB drivers for example , as otherwise
* they ' ll all appear as if the driver name was " usb " .
2009-12-09 14:39:58 +03:00
* @ model : Device model name
* @ serial : Device serial number ( optional )
* @ bus_info : Unique and stable device location identifier
* @ hw_revision : Hardware device revision
* @ driver_version : Device driver version
2015-08-23 15:40:26 +03:00
* @ topology_version : Monotonic counter for storing the version of the graph
* topology . Should be incremented each time the topology changes .
2015-12-16 19:28:01 +03:00
* @ id : Unique ID used on the last registered graph object
2015-12-16 18:58:31 +03:00
* @ entity_internal_idx : Unique internal entity ID used by the graph traversal
* algorithms
* @ entity_internal_idx_max : Allocated internal entity indices
2009-12-09 14:40:00 +03:00
* @ entities : List of registered entities
2015-08-21 15:23:22 +03:00
* @ interfaces : List of registered interfaces
2015-08-23 14:00:33 +03:00
* @ pads : List of registered pads
* @ links : List of registered links
2016-02-12 02:41:21 +03:00
* @ entity_notify : List of registered entity_notify callbacks
[media] media-device: get rid of the spinlock
Right now, the lock schema for media_device struct is messy,
since sometimes, it is protected via a spin lock, while, for
media graph traversal, it is protected by a mutex.
Solve this conflict by always using a mutex.
As a side effect, this prevents a bug when the media notifiers
is called at atomic context, while running the notifier callback:
BUG: sleeping function called from invalid context at mm/slub.c:1289
in_atomic(): 1, irqs_disabled(): 0, pid: 3479, name: modprobe
4 locks held by modprobe/3479:
#0: (&dev->mutex){......}, at: [<ffffffff81ce8933>] __driver_attach+0xa3/0x160
#1: (&dev->mutex){......}, at: [<ffffffff81ce8941>] __driver_attach+0xb1/0x160
#2: (register_mutex#5){+.+.+.}, at: [<ffffffffa10596c7>] usb_audio_probe+0x257/0x1c90 [snd_usb_audio]
#3: (&(&mdev->lock)->rlock){+.+.+.}, at: [<ffffffffa0e6051b>] media_device_register_entity+0x1cb/0x700 [media]
CPU: 2 PID: 3479 Comm: modprobe Not tainted 4.5.0-rc3+ #49
Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015
0000000000000000 ffff8803b3f6f288 ffffffff81933901 ffff8803c4bae000
ffff8803c4bae5c8 ffff8803b3f6f2b0 ffffffff811c6af5 ffff8803c4bae000
ffffffff8285d7f6 0000000000000509 ffff8803b3f6f2f0 ffffffff811c6ce5
Call Trace:
[<ffffffff81933901>] dump_stack+0x85/0xc4
[<ffffffff811c6af5>] ___might_sleep+0x245/0x3a0
[<ffffffff811c6ce5>] __might_sleep+0x95/0x1a0
[<ffffffff8155aade>] kmem_cache_alloc_trace+0x20e/0x300
[<ffffffffa0e66e3d>] ? media_add_link+0x4d/0x140 [media]
[<ffffffffa0e66e3d>] media_add_link+0x4d/0x140 [media]
[<ffffffffa0e69931>] media_create_pad_link+0xa1/0x600 [media]
[<ffffffffa0fe11b3>] au0828_media_graph_notify+0x173/0x360 [au0828]
[<ffffffffa0e68a6a>] ? media_gobj_create+0x1ba/0x480 [media]
[<ffffffffa0e606fb>] media_device_register_entity+0x3ab/0x700 [media]
Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2016-04-06 16:55:24 +03:00
* @ graph_mutex : Protects access to struct media_device data
2016-02-21 19:25:08 +03:00
* @ pm_count_walk : Graph walk for power state walk . Access serialised using
* graph_mutex .
2016-02-12 02:41:22 +03:00
*
* @ source_priv : Driver Private data for enable / disable source handlers
* @ enable_source : Enable Source Handler function pointer
* @ disable_source : Disable Source Handler function pointer
*
2016-04-06 16:55:25 +03:00
* @ link_notify : Link state change notification callback . This callback is
* called with the graph_mutex held .
2009-12-09 14:39:58 +03:00
*
* This structure represents an abstract high - level media device . It allows easy
* access to entities and provides basic media device - level support . The
* structure can be allocated directly or embedded in a larger structure .
*
* The parent @ dev is a physical device . It must be set before registering the
* media device .
*
* @ model is a descriptive model name exported through sysfs . It doesn ' t have to
* be unique .
2016-02-12 02:41:22 +03:00
*
* @ enable_source is a handler to find source entity for the
* sink entity and activate the link between them if source
* entity is free . Drivers should call this handler before
* accessing the source .
*
* @ disable_source is a handler to find source entity for the
* sink entity and deactivate the link between them . Drivers
* should call this handler to release the source .
*
* Note : Bridge driver is expected to implement and set the
* handler when media_device is registered or when
* bridge driver finds the media_device during probe .
* Bridge driver sets source_priv with information
* necessary to run enable / disable source handlers .
*
* Use - case : find tuner entity connected to the decoder
* entity and check if it is available , and activate the
* the link between them from enable_source and deactivate
* from disable_source .
2009-12-09 14:39:58 +03:00
*/
struct media_device {
/* dev->driver_data points to this struct. */
struct device * dev ;
2016-04-28 01:28:26 +03:00
struct media_devnode * devnode ;
2009-12-09 14:39:58 +03:00
char model [ 32 ] ;
2016-02-11 19:24:23 +03:00
char driver_name [ 32 ] ;
2009-12-09 14:39:58 +03:00
char serial [ 40 ] ;
char bus_info [ 32 ] ;
u32 hw_revision ;
u32 driver_version ;
2009-12-09 14:40:00 +03:00
2016-03-16 15:34:39 +03:00
u64 topology_version ;
2015-08-23 15:40:26 +03:00
2015-12-16 19:28:01 +03:00
u32 id ;
2015-12-16 16:32:17 +03:00
struct ida entity_internal_idx ;
int entity_internal_idx_max ;
2015-08-14 18:47:48 +03:00
2009-12-09 14:40:00 +03:00
struct list_head entities ;
2015-08-21 15:23:22 +03:00
struct list_head interfaces ;
2015-08-23 14:00:33 +03:00
struct list_head pads ;
struct list_head links ;
2009-12-09 14:40:00 +03:00
2016-02-12 02:41:21 +03:00
/* notify callback list invoked when a new entity is registered */
struct list_head entity_notify ;
2010-03-07 21:04:59 +03:00
/* Serializes graph operations. */
struct mutex graph_mutex ;
2016-02-21 19:25:08 +03:00
struct media_entity_graph pm_count_walk ;
2009-12-09 14:40:03 +03:00
2016-02-12 02:41:22 +03:00
void * source_priv ;
int ( * enable_source ) ( struct media_entity * entity ,
struct media_pipeline * pipe ) ;
void ( * disable_source ) ( struct media_entity * entity ) ;
2013-05-31 17:37:26 +04:00
int ( * link_notify ) ( struct media_link * link , u32 flags ,
unsigned int notification ) ;
2009-12-09 14:39:58 +03:00
} ;
2016-02-22 17:42:04 +03:00
/* We don't need to include pci.h or usb.h here */
struct pci_dev ;
struct usb_device ;
2015-06-05 23:11:54 +03:00
# ifdef CONFIG_MEDIA_CONTROLLER
2013-05-31 17:37:26 +04:00
/* Supported link_notify @notification values. */
# define MEDIA_DEV_NOTIFY_PRE_LINK_CH 0
# define MEDIA_DEV_NOTIFY_POST_LINK_CH 1
2015-12-16 16:44:32 +03:00
/**
* media_entity_enum_init - Initialise an entity enumeration
*
2015-12-16 18:58:31 +03:00
* @ ent_enum : Entity enumeration to be initialised
2015-12-16 16:44:32 +03:00
* @ mdev : The related media device
*
* Returns zero on success or a negative error code .
*/
static inline __must_check int media_entity_enum_init (
struct media_entity_enum * ent_enum , struct media_device * mdev )
{
return __media_entity_enum_init ( ent_enum ,
mdev - > entity_internal_idx_max + 1 ) ;
}
2015-12-12 01:57:08 +03:00
/**
* media_device_init ( ) - Initializes a media device element
*
* @ mdev : pointer to struct & media_device
*
* This function initializes the media device prior to its registration .
* The media device initialization and registration is split in two functions
* to avoid race conditions and make the media device available to user - space
* before the media graph has been completed .
*
* So drivers need to first initialize the media device , register any entity
* within the media device , create pad to pad links and then finally register
* the media device by calling media_device_register ( ) as a final step .
*/
void media_device_init ( struct media_device * mdev ) ;
/**
* media_device_cleanup ( ) - Cleanups a media device element
*
* @ mdev : pointer to struct & media_device
*
* This function that will destroy the graph_mutex that is
* initialized in media_device_init ( ) .
*/
void media_device_cleanup ( struct media_device * mdev ) ;
2015-12-11 16:06:08 +03:00
/**
* __media_device_register ( ) - Registers a media device element
*
* @ mdev : pointer to struct & media_device
* @ owner : should be filled with % THIS_MODULE
*
* Users , should , instead , call the media_device_register ( ) macro .
*
* The caller is responsible for initializing the media_device structure before
* registration . The following fields must be set :
*
* - dev must point to the parent device ( usually a & pci_dev , & usb_interface or
* & platform_device instance ) .
*
* - model must be filled with the device model name as a NUL - terminated UTF - 8
* string . The device / model revision must not be stored in this field .
*
* The following fields are optional :
*
* - serial is a unique serial number stored as a NUL - terminated ASCII string .
* The field is big enough to store a GUID in text form . If the hardware
* doesn ' t provide a unique serial number this field must be left empty .
*
* - bus_info represents the location of the device in the system as a
* NUL - terminated ASCII string . For PCI / PCIe devices bus_info must be set to
* " PCI: " ( or " PCIe: " ) followed by the value of pci_name ( ) . For USB devices ,
* the usb_make_path ( ) function must be used . This field is used by
* applications to distinguish between otherwise identical devices that don ' t
* provide a serial number .
*
* - hw_revision is the hardware device revision in a driver - specific format .
* When possible the revision should be formatted with the KERNEL_VERSION
* macro .
*
* - driver_version is formatted with the KERNEL_VERSION macro . The version
* minor must be incremented when new features are added to the userspace API
* without breaking binary compatibility . The version major must be
* incremented when binary compatibility is broken .
*
* Notes :
*
* Upon successful registration a character device named media [ 0 - 9 ] + is created .
* The device major and minor numbers are dynamic . The model name is exported as
* a sysfs attribute .
*
* Unregistering a media device that hasn ' t been registered is * NOT * safe .
2015-12-16 18:53:04 +03:00
*
* Return : returns zero on success or a negative error code .
2015-12-11 16:06:08 +03:00
*/
2013-12-12 19:38:17 +04:00
int __must_check __media_device_register ( struct media_device * mdev ,
struct module * owner ) ;
# define media_device_register(mdev) __media_device_register(mdev, THIS_MODULE)
2015-12-11 16:06:08 +03:00
/**
2016-03-16 15:04:03 +03:00
* media_device_unregister ( ) - Unregisters a media device element
2015-12-11 16:06:08 +03:00
*
* @ mdev : pointer to struct & media_device
2015-12-16 18:53:04 +03:00
*
*
* It is safe to call this function on an unregistered ( but initialised )
* media device .
2015-12-11 16:06:08 +03:00
*/
2009-12-09 14:39:58 +03:00
void media_device_unregister ( struct media_device * mdev ) ;
2015-12-11 16:06:08 +03:00
/**
* media_device_register_entity ( ) - registers a media entity inside a
* previously registered media device .
*
* @ mdev : pointer to struct & media_device
* @ entity : pointer to struct & media_entity to be registered
*
* Entities are identified by a unique positive integer ID . The media
* controller framework will such ID automatically . IDs are not guaranteed
* to be contiguous , and the ID number can change on newer Kernel versions .
* So , neither the driver nor userspace should hardcode ID numbers to refer
* to the entities , but , instead , use the framework to find the ID , when
* needed .
*
* The media_entity name , type and flags fields should be initialized before
* calling media_device_register_entity ( ) . Entities embedded in higher - level
* standard structures can have some of those fields set by the higher - level
* framework .
*
* If the device has pads , media_entity_pads_init ( ) should be called before
* this function . Otherwise , the & media_entity . @ pad and & media_entity . @ num_pads
* should be zeroed before calling this function .
*
* Entities have flags that describe the entity capabilities and state :
*
* % MEDIA_ENT_FL_DEFAULT indicates the default entity for a given type .
* This can be used to report the default audio and video devices or the
* default camera sensor .
2015-12-11 17:41:12 +03:00
*
* NOTE : Drivers should set the entity function before calling this function .
* Please notice that the values % MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN and
* % MEDIA_ENT_F_UNKNOWN should not be used by the drivers .
2015-12-11 16:06:08 +03:00
*/
2009-12-09 14:40:00 +03:00
int __must_check media_device_register_entity ( struct media_device * mdev ,
struct media_entity * entity ) ;
2015-12-11 16:06:08 +03:00
/*
* media_device_unregister_entity ( ) - unregisters a media entity .
*
* @ entity : pointer to struct & media_entity to be unregistered
*
* All links associated with the entity and all PADs are automatically
* unregistered from the media_device when this function is called .
*
* Unregistering an entity will not change the IDs of the other entities and
* the previoully used ID will never be reused for a newly registered entities .
*
* When a media device is unregistered , all its entities are unregistered
* automatically . No manual entities unregistration is then required .
*
* Note : the media_entity instance itself must be freed explicitly by
* the driver if required .
*/
2009-12-09 14:40:00 +03:00
void media_device_unregister_entity ( struct media_entity * entity ) ;
2015-12-13 13:36:58 +03:00
2016-02-12 02:41:21 +03:00
/**
* media_device_register_entity_notify ( ) - Registers a media entity_notify
* callback
*
* @ mdev : The media device
* @ nptr : The media_entity_notify
*
* Note : When a new entity is registered , all the registered
* media_entity_notify callbacks are invoked .
*/
int __must_check media_device_register_entity_notify ( struct media_device * mdev ,
struct media_entity_notify * nptr ) ;
/**
* media_device_unregister_entity_notify ( ) - Unregister a media entity notify
* callback
*
* @ mdev : The media device
* @ nptr : The media_entity_notify
*
*/
void media_device_unregister_entity_notify ( struct media_device * mdev ,
struct media_entity_notify * nptr ) ;
2015-12-13 13:36:58 +03:00
/**
* media_device_get_devres ( ) - get media device as device resource
* creates if one doesn ' t exist
*
* @ dev : pointer to struct & device .
*
* Sometimes , the media controller & media_device needs to be shared by more
* than one driver . This function adds support for that , by dynamically
* allocating the & media_device and allowing it to be obtained from the
* struct & device associated with the common device where all sub - device
* components belong . So , for example , on an USB device with multiple
* interfaces , each interface may be handled by a separate per - interface
* drivers . While each interface have its own & device , they all share a
* common & device associated with the hole USB device .
*/
2015-06-03 18:12:53 +03:00
struct media_device * media_device_get_devres ( struct device * dev ) ;
2015-12-13 13:36:58 +03:00
/**
* media_device_find_devres ( ) - find media device as device resource
*
* @ dev : pointer to struct & device .
*/
2015-06-03 18:12:53 +03:00
struct media_device * media_device_find_devres ( struct device * dev ) ;
2009-12-09 14:40:00 +03:00
/* Iterate over all entities. */
# define media_device_for_each_entity(entity, mdev) \
2015-08-23 13:51:33 +03:00
list_for_each_entry ( entity , & ( mdev ) - > entities , graph_obj . list )
2009-12-09 14:40:00 +03:00
2015-08-23 13:51:22 +03:00
/* Iterate over all interfaces. */
# define media_device_for_each_intf(intf, mdev) \
2015-08-23 13:51:33 +03:00
list_for_each_entry ( intf , & ( mdev ) - > interfaces , graph_obj . list )
2015-08-23 13:51:22 +03:00
2015-08-23 14:00:33 +03:00
/* Iterate over all pads. */
# define media_device_for_each_pad(pad, mdev) \
list_for_each_entry ( pad , & ( mdev ) - > pads , graph_obj . list )
/* Iterate over all links. */
# define media_device_for_each_link(link, mdev) \
list_for_each_entry ( link , & ( mdev ) - > links , graph_obj . list )
2016-02-22 17:42:04 +03:00
/**
* media_device_pci_init ( ) - create and initialize a
* struct & media_device from a PCI device .
*
2016-02-22 18:10:49 +03:00
* @ mdev : pointer to struct & media_device
2016-02-22 17:42:04 +03:00
* @ pci_dev : pointer to struct pci_dev
* @ name : media device name . If % NULL , the routine will use the default
* name for the pci device , given by pci_name ( ) macro .
*/
2016-02-22 18:10:49 +03:00
void media_device_pci_init ( struct media_device * mdev ,
struct pci_dev * pci_dev ,
const char * name ) ;
2016-02-22 17:42:04 +03:00
/**
* __media_device_usb_init ( ) - create and initialize a
* struct & media_device from a PCI device .
*
2016-02-22 18:10:49 +03:00
* @ mdev : pointer to struct & media_device
2016-02-22 17:42:04 +03:00
* @ udev : pointer to struct usb_device
* @ board_name : media device name . If % NULL , the routine will use the usb
* product name , if available .
* @ driver_name : name of the driver . if % NULL , the routine will use the name
* given by udev - > dev - > driver - > name , with is usually the wrong
* thing to do .
*
* NOTE : It is better to call media_device_usb_init ( ) instead , as
* such macro fills driver_name with % KBUILD_MODNAME .
*/
2016-02-22 18:10:49 +03:00
void __media_device_usb_init ( struct media_device * mdev ,
struct usb_device * udev ,
const char * board_name ,
const char * driver_name ) ;
2016-02-22 17:42:04 +03:00
2015-06-05 23:11:54 +03:00
# else
static inline int media_device_register ( struct media_device * mdev )
{
return 0 ;
}
static inline void media_device_unregister ( struct media_device * mdev )
{
}
static inline int media_device_register_entity ( struct media_device * mdev ,
struct media_entity * entity )
{
return 0 ;
}
static inline void media_device_unregister_entity ( struct media_entity * entity )
{
}
2016-02-12 02:41:21 +03:00
static inline int media_device_register_entity_notify (
struct media_device * mdev ,
struct media_entity_notify * nptr )
{
return 0 ;
}
static inline void media_device_unregister_entity_notify (
struct media_device * mdev ,
struct media_entity_notify * nptr )
{
}
2015-06-05 23:11:54 +03:00
static inline struct media_device * media_device_get_devres ( struct device * dev )
{
return NULL ;
}
static inline struct media_device * media_device_find_devres ( struct device * dev )
{
return NULL ;
}
2016-02-22 17:42:04 +03:00
2016-02-22 18:10:49 +03:00
static inline void media_device_pci_init ( struct media_device * mdev ,
struct pci_dev * pci_dev ,
char * name )
2016-02-22 17:42:04 +03:00
{
}
2016-02-22 18:10:49 +03:00
static inline void __media_device_usb_init ( struct media_device * mdev ,
struct usb_device * udev ,
char * board_name ,
char * driver_name )
2016-02-22 17:42:04 +03:00
{
}
2015-06-05 23:11:54 +03:00
# endif /* CONFIG_MEDIA_CONTROLLER */
2016-02-22 17:42:04 +03:00
2016-02-22 18:10:49 +03:00
# define media_device_usb_init(mdev, udev, name) \
__media_device_usb_init ( mdev , udev , name , KBUILD_MODNAME )
2016-02-22 17:42:04 +03:00
2009-12-09 14:39:58 +03:00
# endif