|
|
@@ -542,6 +542,7 @@ static void media_device_release(struct media_devnode *mdev)
|
|
|
int __must_check media_device_register_entity(struct media_device *mdev,
|
|
|
struct media_entity *entity)
|
|
|
{
|
|
|
+ struct media_entity_notify *notify, *next;
|
|
|
unsigned int i;
|
|
|
int ret;
|
|
|
|
|
|
@@ -581,6 +582,11 @@ int __must_check media_device_register_entity(struct media_device *mdev,
|
|
|
media_gobj_create(mdev, MEDIA_GRAPH_PAD,
|
|
|
&entity->pads[i].graph_obj);
|
|
|
|
|
|
+ /* invoke entity_notify callbacks */
|
|
|
+ list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
|
|
|
+ (notify)->notify(entity, notify->notify_data);
|
|
|
+ }
|
|
|
+
|
|
|
spin_unlock(&mdev->lock);
|
|
|
|
|
|
return 0;
|
|
|
@@ -614,6 +620,8 @@ static void __media_device_unregister_entity(struct media_entity *entity)
|
|
|
/* Remove the entity */
|
|
|
media_gobj_destroy(&entity->graph_obj);
|
|
|
|
|
|
+ /* invoke entity_notify callbacks to handle entity removal?? */
|
|
|
+
|
|
|
entity->graph_obj.mdev = NULL;
|
|
|
}
|
|
|
|
|
|
@@ -646,6 +654,7 @@ void media_device_init(struct media_device *mdev)
|
|
|
INIT_LIST_HEAD(&mdev->interfaces);
|
|
|
INIT_LIST_HEAD(&mdev->pads);
|
|
|
INIT_LIST_HEAD(&mdev->links);
|
|
|
+ INIT_LIST_HEAD(&mdev->entity_notify);
|
|
|
spin_lock_init(&mdev->lock);
|
|
|
mutex_init(&mdev->graph_mutex);
|
|
|
ida_init(&mdev->entity_internal_idx);
|
|
|
@@ -691,11 +700,40 @@ int __must_check __media_device_register(struct media_device *mdev,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(__media_device_register);
|
|
|
|
|
|
+int __must_check media_device_register_entity_notify(struct media_device *mdev,
|
|
|
+ struct media_entity_notify *nptr)
|
|
|
+{
|
|
|
+ spin_lock(&mdev->lock);
|
|
|
+ list_add_tail(&nptr->list, &mdev->entity_notify);
|
|
|
+ spin_unlock(&mdev->lock);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(media_device_register_entity_notify);
|
|
|
+
|
|
|
+/*
|
|
|
+ * Note: Should be called with mdev->lock held.
|
|
|
+ */
|
|
|
+static void __media_device_unregister_entity_notify(struct media_device *mdev,
|
|
|
+ struct media_entity_notify *nptr)
|
|
|
+{
|
|
|
+ list_del(&nptr->list);
|
|
|
+}
|
|
|
+
|
|
|
+void media_device_unregister_entity_notify(struct media_device *mdev,
|
|
|
+ struct media_entity_notify *nptr)
|
|
|
+{
|
|
|
+ spin_lock(&mdev->lock);
|
|
|
+ __media_device_unregister_entity_notify(mdev, nptr);
|
|
|
+ spin_unlock(&mdev->lock);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(media_device_unregister_entity_notify);
|
|
|
+
|
|
|
void media_device_unregister(struct media_device *mdev)
|
|
|
{
|
|
|
struct media_entity *entity;
|
|
|
struct media_entity *next;
|
|
|
struct media_interface *intf, *tmp_intf;
|
|
|
+ struct media_entity_notify *notify, *nextp;
|
|
|
|
|
|
if (mdev == NULL)
|
|
|
return;
|
|
|
@@ -712,6 +750,10 @@ void media_device_unregister(struct media_device *mdev)
|
|
|
list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
|
|
|
__media_device_unregister_entity(entity);
|
|
|
|
|
|
+ /* Remove all entity_notify callbacks from the media device */
|
|
|
+ list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list)
|
|
|
+ __media_device_unregister_entity_notify(mdev, notify);
|
|
|
+
|
|
|
/* Remove all interfaces from the media device */
|
|
|
list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
|
|
|
graph_obj.list) {
|