Merge tag 'v3.14.25' into backport/v3.14.24-ltsi-rc1+v3.14.25/snapshot-merge.wip
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / media / platform / vsp1 / vsp1_entity.c
index 0226e47..79af71d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * vsp1_entity.c  --  R-Car VSP1 Base Entity
  *
- * Copyright (C) 2013 Renesas Corporation
+ * Copyright (C) 2013-2014 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
 
 #include "vsp1.h"
 #include "vsp1_entity.h"
+#include "vsp1_video.h"
+
+bool vsp1_entity_is_streaming(struct vsp1_entity *entity)
+{
+       bool streaming;
+
+       mutex_lock(&entity->lock);
+       streaming = entity->streaming;
+       mutex_unlock(&entity->lock);
+
+       return streaming;
+}
+
+int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming)
+{
+       int ret;
+
+       mutex_lock(&entity->lock);
+       entity->streaming = streaming;
+       mutex_unlock(&entity->lock);
+
+       if (!streaming)
+               return 0;
+
+       if (!entity->subdev.ctrl_handler)
+               return 0;
+
+       ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler);
+       if (ret < 0) {
+               mutex_lock(&entity->lock);
+               entity->streaming = false;
+               mutex_unlock(&entity->lock);
+       }
+
+       return ret;
+}
 
 /* -----------------------------------------------------------------------------
  * V4L2 Subdevice Operations
@@ -100,8 +136,10 @@ static int vsp1_entity_link_setup(struct media_entity *entity,
                if (source->sink)
                        return -EBUSY;
                source->sink = remote->entity;
+               source->sink_pad = remote->index;
        } else {
                source->sink = NULL;
+               source->sink_pad = 0;
        }
 
        return 0;
@@ -116,44 +154,47 @@ const struct media_entity_operations vsp1_media_ops = {
  * Initialization
  */
 
+static const struct vsp1_route vsp1_routes[] = {
+       { VSP1_ENTITY_BRU, 0, VI6_DPR_BRU_ROUTE,
+         { VI6_DPR_NODE_BRU_IN(0), VI6_DPR_NODE_BRU_IN(1),
+           VI6_DPR_NODE_BRU_IN(2), VI6_DPR_NODE_BRU_IN(3), } },
+       { VSP1_ENTITY_HSI, 0, VI6_DPR_HSI_ROUTE, { VI6_DPR_NODE_HSI, } },
+       { VSP1_ENTITY_HST, 0, VI6_DPR_HST_ROUTE, { VI6_DPR_NODE_HST, } },
+       { VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, } },
+       { VSP1_ENTITY_LUT, 0, VI6_DPR_LUT_ROUTE, { VI6_DPR_NODE_LUT, } },
+       { VSP1_ENTITY_RPF, 0, VI6_DPR_RPF_ROUTE(0), { VI6_DPR_NODE_RPF(0), } },
+       { VSP1_ENTITY_RPF, 1, VI6_DPR_RPF_ROUTE(1), { VI6_DPR_NODE_RPF(1), } },
+       { VSP1_ENTITY_RPF, 2, VI6_DPR_RPF_ROUTE(2), { VI6_DPR_NODE_RPF(2), } },
+       { VSP1_ENTITY_RPF, 3, VI6_DPR_RPF_ROUTE(3), { VI6_DPR_NODE_RPF(3), } },
+       { VSP1_ENTITY_RPF, 4, VI6_DPR_RPF_ROUTE(4), { VI6_DPR_NODE_RPF(4), } },
+       { VSP1_ENTITY_SRU, 0, VI6_DPR_SRU_ROUTE, { VI6_DPR_NODE_SRU, } },
+       { VSP1_ENTITY_UDS, 0, VI6_DPR_UDS_ROUTE(0), { VI6_DPR_NODE_UDS(0), } },
+       { VSP1_ENTITY_UDS, 1, VI6_DPR_UDS_ROUTE(1), { VI6_DPR_NODE_UDS(1), } },
+       { VSP1_ENTITY_UDS, 2, VI6_DPR_UDS_ROUTE(2), { VI6_DPR_NODE_UDS(2), } },
+       { VSP1_ENTITY_WPF, 0, 0, { VI6_DPR_NODE_WPF(0), } },
+       { VSP1_ENTITY_WPF, 1, 0, { VI6_DPR_NODE_WPF(1), } },
+       { VSP1_ENTITY_WPF, 2, 0, { VI6_DPR_NODE_WPF(2), } },
+       { VSP1_ENTITY_WPF, 3, 0, { VI6_DPR_NODE_WPF(3), } },
+};
+
 int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
                     unsigned int num_pads)
 {
-       static const struct {
-               unsigned int id;
-               unsigned int reg;
-       } routes[] = {
-               { VI6_DPR_NODE_HSI, VI6_DPR_HSI_ROUTE },
-               { VI6_DPR_NODE_HST, VI6_DPR_HST_ROUTE },
-               { VI6_DPR_NODE_LIF, 0 },
-               { VI6_DPR_NODE_LUT, VI6_DPR_LUT_ROUTE },
-               { VI6_DPR_NODE_RPF(0), VI6_DPR_RPF_ROUTE(0) },
-               { VI6_DPR_NODE_RPF(1), VI6_DPR_RPF_ROUTE(1) },
-               { VI6_DPR_NODE_RPF(2), VI6_DPR_RPF_ROUTE(2) },
-               { VI6_DPR_NODE_RPF(3), VI6_DPR_RPF_ROUTE(3) },
-               { VI6_DPR_NODE_RPF(4), VI6_DPR_RPF_ROUTE(4) },
-               { VI6_DPR_NODE_SRU, VI6_DPR_SRU_ROUTE },
-               { VI6_DPR_NODE_UDS(0), VI6_DPR_UDS_ROUTE(0) },
-               { VI6_DPR_NODE_UDS(1), VI6_DPR_UDS_ROUTE(1) },
-               { VI6_DPR_NODE_UDS(2), VI6_DPR_UDS_ROUTE(2) },
-               { VI6_DPR_NODE_WPF(0), 0 },
-               { VI6_DPR_NODE_WPF(1), 0 },
-               { VI6_DPR_NODE_WPF(2), 0 },
-               { VI6_DPR_NODE_WPF(3), 0 },
-       };
-
        unsigned int i;
 
-       for (i = 0; i < ARRAY_SIZE(routes); ++i) {
-               if (routes[i].id == entity->id) {
-                       entity->route = routes[i].reg;
+       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];
                        break;
                }
        }
 
-       if (i == ARRAY_SIZE(routes))
+       if (i == ARRAY_SIZE(vsp1_routes))
                return -EINVAL;
 
+       mutex_init(&entity->lock);
+
        entity->vsp1 = vsp1;
        entity->source_pad = num_pads - 1;
 
@@ -182,7 +223,11 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
 
 void vsp1_entity_destroy(struct vsp1_entity *entity)
 {
+       if (entity->video)
+               vsp1_video_cleanup(entity->video);
        if (entity->subdev.ctrl_handler)
                v4l2_ctrl_handler_free(entity->subdev.ctrl_handler);
        media_entity_cleanup(&entity->subdev.entity);
+
+       mutex_destroy(&entity->lock);
 }