aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSakari Ailus <sakari.ailus@iki.fi>2016-02-21 11:25:10 -0500
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2016-03-03 10:32:49 -0500
commit506a47eb4cab9706a9c007e22fadaae79c4cf491 (patch)
tree50a8468c0b06e097f7059e6ee77cb114e1510f50
parenta77bf7048addfbd59ec2208f3172207d90d42c9a (diff)
[media] v4l: omap3isp: Use V4L2 graph PM operations
Power on devices represented by entities in the graph through the pipeline state using V4L2 graph PM operations instead of what was in the omap3isp driver. Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
-rw-r--r--drivers/media/platform/omap3isp/isp.c213
-rw-r--r--drivers/media/platform/omap3isp/isp.h4
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.c13
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.h1
4 files changed, 6 insertions, 225 deletions
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index f9e5245f26ac..5d54e2c6c16b 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -64,6 +64,7 @@
64 64
65#include <media/v4l2-common.h> 65#include <media/v4l2-common.h>
66#include <media/v4l2-device.h> 66#include <media/v4l2-device.h>
67#include <media/v4l2-mc.h>
67#include <media/v4l2-of.h> 68#include <media/v4l2-of.h>
68 69
69#include "isp.h" 70#include "isp.h"
@@ -657,216 +658,6 @@ static irqreturn_t isp_isr(int irq, void *_isp)
657} 658}
658 659
659/* ----------------------------------------------------------------------------- 660/* -----------------------------------------------------------------------------
660 * Pipeline power management
661 *
662 * Entities must be powered up when part of a pipeline that contains at least
663 * one open video device node.
664 *
665 * To achieve this use the entity use_count field to track the number of users.
666 * For entities corresponding to video device nodes the use_count field stores
667 * the users count of the node. For entities corresponding to subdevs the
668 * use_count field stores the total number of users of all video device nodes
669 * in the pipeline.
670 *
671 * The omap3isp_pipeline_pm_use() function must be called in the open() and
672 * close() handlers of video device nodes. It increments or decrements the use
673 * count of all subdev entities in the pipeline.
674 *
675 * To react to link management on powered pipelines, the link setup notification
676 * callback updates the use count of all entities in the source and sink sides
677 * of the link.
678 */
679
680/*
681 * isp_pipeline_pm_use_count - Count the number of users of a pipeline
682 * @entity: The entity
683 *
684 * Return the total number of users of all video device nodes in the pipeline.
685 */
686static int isp_pipeline_pm_use_count(struct media_entity *entity,
687 struct media_entity_graph *graph)
688{
689 int use = 0;
690
691 media_entity_graph_walk_start(graph, entity);
692
693 while ((entity = media_entity_graph_walk_next(graph))) {
694 if (is_media_entity_v4l2_io(entity))
695 use += entity->use_count;
696 }
697
698 return use;
699}
700
701/*
702 * isp_pipeline_pm_power_one - Apply power change to an entity
703 * @entity: The entity
704 * @change: Use count change
705 *
706 * Change the entity use count by @change. If the entity is a subdev update its
707 * power state by calling the core::s_power operation when the use count goes
708 * from 0 to != 0 or from != 0 to 0.
709 *
710 * Return 0 on success or a negative error code on failure.
711 */
712static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
713{
714 struct v4l2_subdev *subdev;
715 int ret;
716
717 subdev = is_media_entity_v4l2_subdev(entity)
718 ? media_entity_to_v4l2_subdev(entity) : NULL;
719
720 if (entity->use_count == 0 && change > 0 && subdev != NULL) {
721 ret = v4l2_subdev_call(subdev, core, s_power, 1);
722 if (ret < 0 && ret != -ENOIOCTLCMD)
723 return ret;
724 }
725
726 entity->use_count += change;
727 WARN_ON(entity->use_count < 0);
728
729 if (entity->use_count == 0 && change < 0 && subdev != NULL)
730 v4l2_subdev_call(subdev, core, s_power, 0);
731
732 return 0;
733}
734
735/*
736 * isp_pipeline_pm_power - Apply power change to all entities in a pipeline
737 * @entity: The entity
738 * @change: Use count change
739 *
740 * Walk the pipeline to update the use count and the power state of all non-node
741 * entities.
742 *
743 * Return 0 on success or a negative error code on failure.
744 */
745static int isp_pipeline_pm_power(struct media_entity *entity, int change,
746 struct media_entity_graph *graph)
747{
748 struct media_entity *first = entity;
749 int ret = 0;
750
751 if (!change)
752 return 0;
753
754 media_entity_graph_walk_start(graph, entity);
755
756 while (!ret && (entity = media_entity_graph_walk_next(graph)))
757 if (is_media_entity_v4l2_subdev(entity))
758 ret = isp_pipeline_pm_power_one(entity, change);
759
760 if (!ret)
761 return ret;
762
763 media_entity_graph_walk_start(graph, first);
764
765 while ((first = media_entity_graph_walk_next(graph))
766 && first != entity)
767 if (is_media_entity_v4l2_subdev(first))
768 isp_pipeline_pm_power_one(first, -change);
769
770 return ret;
771}
772
773/*
774 * omap3isp_pipeline_pm_use - Update the use count of an entity
775 * @entity: The entity
776 * @use: Use (1) or stop using (0) the entity
777 *
778 * Update the use count of all entities in the pipeline and power entities on or
779 * off accordingly.
780 *
781 * Return 0 on success or a negative error code on failure. Powering entities
782 * off is assumed to never fail. No failure can occur when the use parameter is
783 * set to 0.
784 */
785int omap3isp_pipeline_pm_use(struct media_entity *entity, int use,
786 struct media_entity_graph *graph)
787{
788 int change = use ? 1 : -1;
789 int ret;
790
791 mutex_lock(&entity->graph_obj.mdev->graph_mutex);
792
793 /* Apply use count to node. */
794 entity->use_count += change;
795 WARN_ON(entity->use_count < 0);
796
797 /* Apply power change to connected non-nodes. */
798 ret = isp_pipeline_pm_power(entity, change, graph);
799 if (ret < 0)
800 entity->use_count -= change;
801
802 mutex_unlock(&entity->graph_obj.mdev->graph_mutex);
803
804 return ret;
805}
806
807/*
808 * isp_pipeline_link_notify - Link management notification callback
809 * @link: The link
810 * @flags: New link flags that will be applied
811 * @notification: The link's state change notification type (MEDIA_DEV_NOTIFY_*)
812 *
813 * React to link management on powered pipelines by updating the use count of
814 * all entities in the source and sink sides of the link. Entities are powered
815 * on or off accordingly.
816 *
817 * Return 0 on success or a negative error code on failure. Powering entities
818 * off is assumed to never fail. This function will not fail for disconnection
819 * events.
820 */
821static int isp_pipeline_link_notify(struct media_link *link, u32 flags,
822 unsigned int notification)
823{
824 struct media_entity_graph *graph =
825 &container_of(link->graph_obj.mdev, struct isp_device,
826 media_dev)->pm_count_graph;
827 struct media_entity *source = link->source->entity;
828 struct media_entity *sink = link->sink->entity;
829 int source_use;
830 int sink_use;
831 int ret = 0;
832
833 if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) {
834 ret = media_entity_graph_walk_init(graph,
835 link->graph_obj.mdev);
836 if (ret)
837 return ret;
838 }
839
840 source_use = isp_pipeline_pm_use_count(source, graph);
841 sink_use = isp_pipeline_pm_use_count(sink, graph);
842
843 if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
844 !(flags & MEDIA_LNK_FL_ENABLED)) {
845 /* Powering off entities is assumed to never fail. */
846 isp_pipeline_pm_power(source, -sink_use, graph);
847 isp_pipeline_pm_power(sink, -source_use, graph);
848 return 0;
849 }
850
851 if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH &&
852 (flags & MEDIA_LNK_FL_ENABLED)) {
853
854 ret = isp_pipeline_pm_power(source, sink_use, graph);
855 if (ret < 0)
856 return ret;
857
858 ret = isp_pipeline_pm_power(sink, source_use, graph);
859 if (ret < 0)
860 isp_pipeline_pm_power(source, -sink_use, graph);
861 }
862
863 if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH)
864 media_entity_graph_walk_cleanup(graph);
865
866 return ret;
867}
868
869/* -----------------------------------------------------------------------------
870 * Pipeline stream management 661 * Pipeline stream management
871 */ 662 */
872 663
@@ -1889,7 +1680,7 @@ static int isp_register_entities(struct isp_device *isp)
1889 strlcpy(isp->media_dev.model, "TI OMAP3 ISP", 1680 strlcpy(isp->media_dev.model, "TI OMAP3 ISP",
1890 sizeof(isp->media_dev.model)); 1681 sizeof(isp->media_dev.model));
1891 isp->media_dev.hw_revision = isp->revision; 1682 isp->media_dev.hw_revision = isp->revision;
1892 isp->media_dev.link_notify = isp_pipeline_link_notify; 1683 isp->media_dev.link_notify = v4l2_pipeline_link_notify;
1893 media_device_init(&isp->media_dev); 1684 media_device_init(&isp->media_dev);
1894 1685
1895 isp->v4l2_dev.mdev = &isp->media_dev; 1686 isp->v4l2_dev.mdev = &isp->media_dev;
diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h
index 49b7f71ac968..7e6f6638433b 100644
--- a/drivers/media/platform/omap3isp/isp.h
+++ b/drivers/media/platform/omap3isp/isp.h
@@ -177,7 +177,6 @@ struct isp_device {
177 struct v4l2_device v4l2_dev; 177 struct v4l2_device v4l2_dev;
178 struct v4l2_async_notifier notifier; 178 struct v4l2_async_notifier notifier;
179 struct media_device media_dev; 179 struct media_device media_dev;
180 struct media_entity_graph pm_count_graph;
181 struct device *dev; 180 struct device *dev;
182 u32 revision; 181 u32 revision;
183 182
@@ -267,9 +266,6 @@ void omap3isp_subclk_enable(struct isp_device *isp,
267void omap3isp_subclk_disable(struct isp_device *isp, 266void omap3isp_subclk_disable(struct isp_device *isp,
268 enum isp_subclk_resource res); 267 enum isp_subclk_resource res);
269 268
270int omap3isp_pipeline_pm_use(struct media_entity *entity, int use,
271 struct media_entity_graph *graph);
272
273int omap3isp_register_entities(struct platform_device *pdev, 269int omap3isp_register_entities(struct platform_device *pdev,
274 struct v4l2_device *v4l2_dev); 270 struct v4l2_device *v4l2_dev);
275void omap3isp_unregister_entities(struct platform_device *pdev); 271void omap3isp_unregister_entities(struct platform_device *pdev);
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index 2aff755ff77c..ac76d2901501 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -22,8 +22,10 @@
22#include <linux/sched.h> 22#include <linux/sched.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/vmalloc.h> 24#include <linux/vmalloc.h>
25
25#include <media/v4l2-dev.h> 26#include <media/v4l2-dev.h>
26#include <media/v4l2-ioctl.h> 27#include <media/v4l2-ioctl.h>
28#include <media/v4l2-mc.h>
27#include <media/videobuf2-dma-contig.h> 29#include <media/videobuf2-dma-contig.h>
28 30
29#include "ispvideo.h" 31#include "ispvideo.h"
@@ -1292,12 +1294,7 @@ static int isp_video_open(struct file *file)
1292 goto done; 1294 goto done;
1293 } 1295 }
1294 1296
1295 ret = media_entity_graph_walk_init(&handle->graph, 1297 ret = v4l2_pipeline_pm_use(&video->video.entity, 1);
1296 &video->isp->media_dev);
1297 if (ret)
1298 goto done;
1299
1300 ret = omap3isp_pipeline_pm_use(&video->video.entity, 1, &handle->graph);
1301 if (ret < 0) { 1298 if (ret < 0) {
1302 omap3isp_put(video->isp); 1299 omap3isp_put(video->isp);
1303 goto done; 1300 goto done;
@@ -1328,7 +1325,6 @@ static int isp_video_open(struct file *file)
1328done: 1325done:
1329 if (ret < 0) { 1326 if (ret < 0) {
1330 v4l2_fh_del(&handle->vfh); 1327 v4l2_fh_del(&handle->vfh);
1331 media_entity_graph_walk_cleanup(&handle->graph);
1332 kfree(handle); 1328 kfree(handle);
1333 } 1329 }
1334 1330
@@ -1348,8 +1344,7 @@ static int isp_video_release(struct file *file)
1348 vb2_queue_release(&handle->queue); 1344 vb2_queue_release(&handle->queue);
1349 mutex_unlock(&video->queue_lock); 1345 mutex_unlock(&video->queue_lock);
1350 1346
1351 omap3isp_pipeline_pm_use(&video->video.entity, 0, &handle->graph); 1347 v4l2_pipeline_pm_use(&video->video.entity, 0);
1352 media_entity_graph_walk_cleanup(&handle->graph);
1353 1348
1354 /* Release the file handle. */ 1349 /* Release the file handle. */
1355 v4l2_fh_del(vfh); 1350 v4l2_fh_del(vfh);
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 156429878d64..6a48d5879c56 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -189,7 +189,6 @@ struct isp_video_fh {
189 struct vb2_queue queue; 189 struct vb2_queue queue;
190 struct v4l2_format format; 190 struct v4l2_format format;
191 struct v4l2_fract timeperframe; 191 struct v4l2_fract timeperframe;
192 struct media_entity_graph graph;
193}; 192};
194 193
195#define to_isp_video_fh(fh) container_of(fh, struct isp_video_fh, vfh) 194#define to_isp_video_fh(fh) container_of(fh, struct isp_video_fh, vfh)