v4l: vsp1: Add support for multiple LIF instances
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Wed, 21 Jun 2017 13:10:18 +0000 (16:10 +0300)
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Thu, 3 Aug 2017 13:17:20 +0000 (16:17 +0300)
The VSP2-DL instance (present in the H3 ES2.0 and M3-N SoCs) has two LIF
instances. Adapt the driver infrastructure to support multiple LIFs.
Support for multiple display pipelines will be added separately.

The change to the entity routing table removes the ability to connect
the LIF output to the HGO or HGT histogram generators. This feature is
only available on Gen2 hardware, isn't supported by the rest of the
driver, and has no known use case, so this isn't an issue.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Acked-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
drivers/media/platform/vsp1/vsp1.h
drivers/media/platform/vsp1/vsp1_drm.c
drivers/media/platform/vsp1/vsp1_drv.c
drivers/media/platform/vsp1/vsp1_entity.c
drivers/media/platform/vsp1/vsp1_lif.c
drivers/media/platform/vsp1/vsp1_lif.h
drivers/media/platform/vsp1/vsp1_regs.h

index 73858a0..78ef838 100644 (file)
@@ -41,11 +41,11 @@ struct vsp1_rwpf;
 struct vsp1_sru;
 struct vsp1_uds;
 
+#define VSP1_MAX_LIF           2
 #define VSP1_MAX_RPF           5
 #define VSP1_MAX_UDS           3
 #define VSP1_MAX_WPF           4
 
-#define VSP1_HAS_LIF           (1 << 0)
 #define VSP1_HAS_LUT           (1 << 1)
 #define VSP1_HAS_SRU           (1 << 2)
 #define VSP1_HAS_BRU           (1 << 3)
@@ -61,6 +61,7 @@ struct vsp1_device_info {
        const char *model;
        unsigned int gen;
        unsigned int features;
+       unsigned int lif_count;
        unsigned int rpf_count;
        unsigned int uds_count;
        unsigned int wpf_count;
@@ -84,7 +85,7 @@ struct vsp1_device {
        struct vsp1_hgt *hgt;
        struct vsp1_hsit *hsi;
        struct vsp1_hsit *hst;
-       struct vsp1_lif *lif;
+       struct vsp1_lif *lif[VSP1_MAX_LIF];
        struct vsp1_lut *lut;
        struct vsp1_rwpf *rpf[VSP1_MAX_RPF];
        struct vsp1_sru *sru;
index daaafe7..4e1b893 100644 (file)
@@ -181,7 +181,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
                format.format.code);
 
        format.pad = LIF_PAD_SINK;
-       ret = v4l2_subdev_call(&vsp1->lif->entity.subdev, pad, set_fmt, NULL,
+       ret = v4l2_subdev_call(&vsp1->lif[0]->entity.subdev, pad, set_fmt, NULL,
                               &format);
        if (ret < 0)
                return ret;
@@ -599,15 +599,15 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
 
        vsp1->bru->entity.sink = &vsp1->wpf[0]->entity;
        vsp1->bru->entity.sink_pad = 0;
-       vsp1->wpf[0]->entity.sink = &vsp1->lif->entity;
+       vsp1->wpf[0]->entity.sink = &vsp1->lif[0]->entity;
        vsp1->wpf[0]->entity.sink_pad = 0;
 
        list_add_tail(&vsp1->bru->entity.list_pipe, &pipe->entities);
        list_add_tail(&vsp1->wpf[0]->entity.list_pipe, &pipe->entities);
-       list_add_tail(&vsp1->lif->entity.list_pipe, &pipe->entities);
+       list_add_tail(&vsp1->lif[0]->entity.list_pipe, &pipe->entities);
 
        pipe->bru = &vsp1->bru->entity;
-       pipe->lif = &vsp1->lif->entity;
+       pipe->lif = &vsp1->lif[0]->entity;
        pipe->output = vsp1->wpf[0];
        pipe->output->pipe = pipe;
        pipe->frame_end = vsp1_du_pipeline_frame_end;
index d1682a9..962e4c3 100644 (file)
@@ -168,10 +168,13 @@ static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
                        return ret;
        }
 
-       if (vsp1->lif) {
-               ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
+       for (i = 0; i < vsp1->info->lif_count; ++i) {
+               if (!vsp1->lif[i])
+                       continue;
+
+               ret = media_create_pad_link(&vsp1->wpf[i]->entity.subdev.entity,
                                            RWPF_PAD_SOURCE,
-                                           &vsp1->lif->entity.subdev.entity,
+                                           &vsp1->lif[i]->entity.subdev.entity,
                                            LIF_PAD_SINK, 0);
                if (ret < 0)
                        return ret;
@@ -334,18 +337,23 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
        }
 
        /*
-        * The LIF is only supported when used in conjunction with the DU, in
+        * The LIFs are only supported when used in conjunction with the DU, in
         * which case the userspace API is disabled. If the userspace API is
-        * enabled skip the LIF, even when present.
+        * enabled skip the LIFs, even when present.
         */
-       if (vsp1->info->features & VSP1_HAS_LIF && !vsp1->info->uapi) {
-               vsp1->lif = vsp1_lif_create(vsp1);
-               if (IS_ERR(vsp1->lif)) {
-                       ret = PTR_ERR(vsp1->lif);
-                       goto done;
-               }
+       if (!vsp1->info->uapi) {
+               for (i = 0; i < vsp1->info->lif_count; ++i) {
+                       struct vsp1_lif *lif;
+
+                       lif = vsp1_lif_create(vsp1, i);
+                       if (IS_ERR(lif)) {
+                               ret = PTR_ERR(lif);
+                               goto done;
+                       }
 
-               list_add_tail(&vsp1->lif->entity.list_dev, &vsp1->entities);
+                       vsp1->lif[i] = lif;
+                       list_add_tail(&lif->entity.list_dev, &vsp1->entities);
+               }
        }
 
        if (vsp1->info->features & VSP1_HAS_LUT) {
@@ -638,8 +646,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
                .version = VI6_IP_VERSION_MODEL_VSPD_GEN2,
                .model = "VSP1-D",
                .gen = 2,
-               .features = VSP1_HAS_BRU | VSP1_HAS_HGO | VSP1_HAS_LIF
-                         | VSP1_HAS_LUT,
+               .features = VSP1_HAS_BRU | VSP1_HAS_HGO | VSP1_HAS_LUT,
+               .lif_count = 1,
                .rpf_count = 4,
                .uds_count = 1,
                .wpf_count = 1,
@@ -672,8 +680,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
                .version = VI6_IP_VERSION_MODEL_VSPD_V2H,
                .model = "VSP1V-D",
                .gen = 2,
-               .features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT
-                         | VSP1_HAS_LIF,
+               .features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT,
+               .lif_count = 1,
                .rpf_count = 4,
                .uds_count = 1,
                .wpf_count = 1,
@@ -721,7 +729,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
                .version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
                .model = "VSP2-D",
                .gen = 3,
-               .features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_WPF_VFLIP,
+               .features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP,
+               .lif_count = 1,
                .rpf_count = 5,
                .wpf_count = 2,
                .num_bru_inputs = 5,
@@ -729,7 +738,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
                .version = VI6_IP_VERSION_MODEL_VSPD_V3,
                .model = "VSP2-D",
                .gen = 3,
-               .features = VSP1_HAS_BRS | VSP1_HAS_BRU | VSP1_HAS_LIF,
+               .features = VSP1_HAS_BRS | VSP1_HAS_BRU,
+               .lif_count = 1,
                .rpf_count = 5,
                .wpf_count = 1,
                .num_bru_inputs = 5,
@@ -737,7 +747,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
                .version = VI6_IP_VERSION_MODEL_VSPDL_GEN3,
                .model = "VSP2-DL",
                .gen = 3,
-               .features = VSP1_HAS_BRS | VSP1_HAS_BRU | VSP1_HAS_LIF,
+               .features = VSP1_HAS_BRS | VSP1_HAS_BRU,
+               .lif_count = 2,
                .rpf_count = 5,
                .wpf_count = 2,
                .num_bru_inputs = 5,
index c06f7db..54de150 100644 (file)
@@ -468,7 +468,8 @@ static const struct vsp1_route vsp1_routes[] = {
        { VSP1_ENTITY_HGT, 0, 0, { 0, }, 0 },
        VSP1_ENTITY_ROUTE(HSI),
        VSP1_ENTITY_ROUTE(HST),
-       { VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, }, VI6_DPR_NODE_LIF },
+       { VSP1_ENTITY_LIF, 0, 0, { 0, }, 0 },
+       { VSP1_ENTITY_LIF, 1, 0, { 0, }, 0 },
        VSP1_ENTITY_ROUTE(LUT),
        VSP1_ENTITY_ROUTE_RPF(0),
        VSP1_ENTITY_ROUTE_RPF(1),
index 702487f..e6fa16d 100644 (file)
@@ -30,7 +30,7 @@
 static inline void vsp1_lif_write(struct vsp1_lif *lif, struct vsp1_dl_list *dl,
                                  u32 reg, u32 data)
 {
-       vsp1_dl_list_write(dl, reg, data);
+       vsp1_dl_list_write(dl, reg + lif->entity.index * VI6_LIF_OFFSET, data);
 }
 
 /* -----------------------------------------------------------------------------
@@ -165,7 +165,7 @@ static const struct vsp1_entity_operations lif_entity_ops = {
  * Initialization and Cleanup
  */
 
-struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1)
+struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1, unsigned int index)
 {
        struct vsp1_lif *lif;
        int ret;
@@ -176,6 +176,7 @@ struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1)
 
        lif->entity.ops = &lif_entity_ops;
        lif->entity.type = VSP1_ENTITY_LIF;
+       lif->entity.index = index;
 
        /*
         * The LIF is never exposed to userspace, but media entity registration
index 7b35879..3417339 100644 (file)
@@ -32,6 +32,6 @@ static inline struct vsp1_lif *to_lif(struct v4l2_subdev *subdev)
        return container_of(subdev, struct vsp1_lif, entity.subdev);
 }
 
-struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1);
+struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1, unsigned int index);
 
 #endif /* __VSP1_LIF_H__ */
index ab439a6..007e2bb 100644 (file)
 #define VI6_DPR_NODE_HST               30
 #define VI6_DPR_NODE_HSI               31
 #define VI6_DPR_NODE_BRS_IN(n)         (38 + (n))
-#define VI6_DPR_NODE_LIF               55
+#define VI6_DPR_NODE_LIF               55              /* Gen2 only */
 #define VI6_DPR_NODE_WPF(n)            (56 + (n))
 #define VI6_DPR_NODE_UNUSED            63
 
  * LIF Control Registers
  */
 
+#define VI6_LIF_OFFSET                 (-0x100)
+
 #define VI6_LIF_CTRL                   0x3b00
 #define VI6_LIF_CTRL_OBTH_MASK         (0x7ff << 16)
 #define VI6_LIF_CTRL_OBTH_SHIFT                16