[media] v4l: vsp1: Factorize get pad format code
[deliverable/linux.git] / drivers / media / platform / vsp1 / vsp1_uds.c
index bba67770cf9567d6be4a0d0d9bb4377918c38026..59dd53c0d2be83abd01fb8a95c5f9e4a5e93221c 100644 (file)
@@ -17,6 +17,7 @@
 #include <media/v4l2-subdev.h>
 
 #include "vsp1.h"
+#include "vsp1_dl.h"
 #include "vsp1_uds.h"
 
 #define UDS_MIN_SIZE                           4U
  * Device Access
  */
 
-static inline void vsp1_uds_write(struct vsp1_uds *uds, u32 reg, u32 data)
+static inline void vsp1_uds_write(struct vsp1_uds *uds, struct vsp1_dl_list *dl,
+                                 u32 reg, u32 data)
 {
-       vsp1_write(uds->entity.vsp1,
-                  reg + uds->entity.index * VI6_UDS_OFFSET, data);
+       vsp1_dl_list_write(dl, reg + uds->entity.index * VI6_UDS_OFFSET, data);
 }
 
 /* -----------------------------------------------------------------------------
  * Scaling Computation
  */
 
-void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha)
+void vsp1_uds_set_alpha(struct vsp1_uds *uds, struct vsp1_dl_list *dl,
+                       unsigned int alpha)
 {
-       vsp1_uds_write(uds, VI6_UDS_ALPVAL, alpha << VI6_UDS_ALPVAL_VAL0_SHIFT);
+       vsp1_uds_write(uds, dl, VI6_UDS_ALPVAL,
+                      alpha << VI6_UDS_ALPVAL_VAL0_SHIFT);
 }
 
 /*
@@ -104,60 +107,6 @@ static unsigned int uds_compute_ratio(unsigned int input, unsigned int output)
        return (input - 1) * 4096 / (output - 1);
 }
 
-/* -----------------------------------------------------------------------------
- * V4L2 Subdevice Core Operations
- */
-
-static int uds_s_stream(struct v4l2_subdev *subdev, int enable)
-{
-       struct vsp1_uds *uds = to_uds(subdev);
-       const struct v4l2_mbus_framefmt *output;
-       const struct v4l2_mbus_framefmt *input;
-       unsigned int hscale;
-       unsigned int vscale;
-       bool multitap;
-
-       if (!enable)
-               return 0;
-
-       input = &uds->entity.formats[UDS_PAD_SINK];
-       output = &uds->entity.formats[UDS_PAD_SOURCE];
-
-       hscale = uds_compute_ratio(input->width, output->width);
-       vscale = uds_compute_ratio(input->height, output->height);
-
-       dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", hscale, vscale);
-
-       /* Multi-tap scaling can't be enabled along with alpha scaling when
-        * scaling down with a factor lower than or equal to 1/2 in either
-        * direction.
-        */
-       if (uds->scale_alpha && (hscale >= 8192 || vscale >= 8192))
-               multitap = false;
-       else
-               multitap = true;
-
-       vsp1_uds_write(uds, VI6_UDS_CTRL,
-                      (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) |
-                      (multitap ? VI6_UDS_CTRL_BC : 0));
-
-       vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH,
-                      (uds_passband_width(hscale)
-                               << VI6_UDS_PASS_BWIDTH_H_SHIFT) |
-                      (uds_passband_width(vscale)
-                               << VI6_UDS_PASS_BWIDTH_V_SHIFT));
-
-       /* Set the scaling ratios and the output size. */
-       vsp1_uds_write(uds, VI6_UDS_SCALE,
-                      (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) |
-                      (vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
-       vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE,
-                      (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
-                      (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
-
-       return 0;
-}
-
 /* -----------------------------------------------------------------------------
  * V4L2 Subdevice Pad Operations
  */
@@ -178,16 +127,22 @@ static int uds_enum_mbus_code(struct v4l2_subdev *subdev,
 
                code->code = codes[code->index];
        } else {
+               struct v4l2_subdev_pad_config *config;
                struct v4l2_mbus_framefmt *format;
 
+               config = vsp1_entity_get_pad_config(&uds->entity, cfg,
+                                                   code->which);
+               if (!config)
+                       return -EINVAL;
+
                /* The UDS can't perform format conversion, the sink format is
                 * always identical to the source format.
                 */
                if (code->index)
                        return -EINVAL;
 
-               format = vsp1_entity_get_pad_format(&uds->entity, cfg,
-                                                   UDS_PAD_SINK, code->which);
+               format = vsp1_entity_get_pad_format(&uds->entity, config,
+                                                   UDS_PAD_SINK);
                code->code = format->code;
        }
 
@@ -199,10 +154,15 @@ static int uds_enum_frame_size(struct v4l2_subdev *subdev,
                               struct v4l2_subdev_frame_size_enum *fse)
 {
        struct vsp1_uds *uds = to_uds(subdev);
+       struct v4l2_subdev_pad_config *config;
        struct v4l2_mbus_framefmt *format;
 
-       format = vsp1_entity_get_pad_format(&uds->entity, cfg,
-                                           UDS_PAD_SINK, fse->which);
+       config = vsp1_entity_get_pad_config(&uds->entity, cfg, fse->which);
+       if (!config)
+               return -EINVAL;
+
+       format = vsp1_entity_get_pad_format(&uds->entity, config,
+                                           UDS_PAD_SINK);
 
        if (fse->index || fse->code != format->code)
                return -EINVAL;
@@ -222,20 +182,9 @@ static int uds_enum_frame_size(struct v4l2_subdev *subdev,
        return 0;
 }
 
-static int uds_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
-                         struct v4l2_subdev_format *fmt)
-{
-       struct vsp1_uds *uds = to_uds(subdev);
-
-       fmt->format = *vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad,
-                                                 fmt->which);
-
-       return 0;
-}
-
-static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_pad_config *cfg,
-                          unsigned int pad, struct v4l2_mbus_framefmt *fmt,
-                          enum v4l2_subdev_format_whence which)
+static void uds_try_format(struct vsp1_uds *uds,
+                          struct v4l2_subdev_pad_config *config,
+                          unsigned int pad, struct v4l2_mbus_framefmt *fmt)
 {
        struct v4l2_mbus_framefmt *format;
        unsigned int minimum;
@@ -254,8 +203,8 @@ static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_pad_config *
 
        case UDS_PAD_SOURCE:
                /* The UDS scales but can't perform format conversion. */
-               format = vsp1_entity_get_pad_format(&uds->entity, cfg,
-                                                   UDS_PAD_SINK, which);
+               format = vsp1_entity_get_pad_format(&uds->entity, config,
+                                                   UDS_PAD_SINK);
                fmt->code = format->code;
 
                uds_output_limits(format->width, &minimum, &maximum);
@@ -269,25 +218,30 @@ static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_pad_config *
        fmt->colorspace = V4L2_COLORSPACE_SRGB;
 }
 
-static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
+static int uds_set_format(struct v4l2_subdev *subdev,
+                         struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct vsp1_uds *uds = to_uds(subdev);
+       struct v4l2_subdev_pad_config *config;
        struct v4l2_mbus_framefmt *format;
 
-       uds_try_format(uds, cfg, fmt->pad, &fmt->format, fmt->which);
+       config = vsp1_entity_get_pad_config(&uds->entity, cfg, fmt->which);
+       if (!config)
+               return -EINVAL;
 
-       format = vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad,
-                                           fmt->which);
+       uds_try_format(uds, config, fmt->pad, &fmt->format);
+
+       format = vsp1_entity_get_pad_format(&uds->entity, config, fmt->pad);
        *format = fmt->format;
 
        if (fmt->pad == UDS_PAD_SINK) {
                /* Propagate the format to the source pad. */
-               format = vsp1_entity_get_pad_format(&uds->entity, cfg,
-                                                   UDS_PAD_SOURCE, fmt->which);
+               format = vsp1_entity_get_pad_format(&uds->entity, config,
+                                                   UDS_PAD_SOURCE);
                *format = fmt->format;
 
-               uds_try_format(uds, cfg, UDS_PAD_SOURCE, format, fmt->which);
+               uds_try_format(uds, config, UDS_PAD_SOURCE, format);
        }
 
        return 0;
@@ -297,55 +251,97 @@ static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con
  * V4L2 Subdevice Operations
  */
 
-static struct v4l2_subdev_video_ops uds_video_ops = {
-       .s_stream = uds_s_stream,
-};
-
 static struct v4l2_subdev_pad_ops uds_pad_ops = {
+       .init_cfg = vsp1_entity_init_cfg,
        .enum_mbus_code = uds_enum_mbus_code,
        .enum_frame_size = uds_enum_frame_size,
-       .get_fmt = uds_get_format,
+       .get_fmt = vsp1_subdev_get_pad_format,
        .set_fmt = uds_set_format,
 };
 
 static struct v4l2_subdev_ops uds_ops = {
-       .video  = &uds_video_ops,
        .pad    = &uds_pad_ops,
 };
 
+/* -----------------------------------------------------------------------------
+ * VSP1 Entity Operations
+ */
+
+static void uds_configure(struct vsp1_entity *entity,
+                         struct vsp1_pipeline *pipe,
+                         struct vsp1_dl_list *dl)
+{
+       struct vsp1_uds *uds = to_uds(&entity->subdev);
+       const struct v4l2_mbus_framefmt *output;
+       const struct v4l2_mbus_framefmt *input;
+       unsigned int hscale;
+       unsigned int vscale;
+       bool multitap;
+
+       input = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config,
+                                          UDS_PAD_SINK);
+       output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config,
+                                           UDS_PAD_SOURCE);
+
+       hscale = uds_compute_ratio(input->width, output->width);
+       vscale = uds_compute_ratio(input->height, output->height);
+
+       dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", hscale, vscale);
+
+       /* Multi-tap scaling can't be enabled along with alpha scaling when
+        * scaling down with a factor lower than or equal to 1/2 in either
+        * direction.
+        */
+       if (uds->scale_alpha && (hscale >= 8192 || vscale >= 8192))
+               multitap = false;
+       else
+               multitap = true;
+
+       vsp1_uds_write(uds, dl, VI6_UDS_CTRL,
+                      (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) |
+                      (multitap ? VI6_UDS_CTRL_BC : 0));
+
+       vsp1_uds_write(uds, dl, VI6_UDS_PASS_BWIDTH,
+                      (uds_passband_width(hscale)
+                               << VI6_UDS_PASS_BWIDTH_H_SHIFT) |
+                      (uds_passband_width(vscale)
+                               << VI6_UDS_PASS_BWIDTH_V_SHIFT));
+
+       /* Set the scaling ratios and the output size. */
+       vsp1_uds_write(uds, dl, VI6_UDS_SCALE,
+                      (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) |
+                      (vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
+       vsp1_uds_write(uds, dl, VI6_UDS_CLIP_SIZE,
+                      (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
+                      (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
+}
+
+static const struct vsp1_entity_operations uds_entity_ops = {
+       .configure = uds_configure,
+};
+
 /* -----------------------------------------------------------------------------
  * Initialization and Cleanup
  */
 
 struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index)
 {
-       struct v4l2_subdev *subdev;
        struct vsp1_uds *uds;
+       char name[6];
        int ret;
 
        uds = devm_kzalloc(vsp1->dev, sizeof(*uds), GFP_KERNEL);
        if (uds == NULL)
                return ERR_PTR(-ENOMEM);
 
+       uds->entity.ops = &uds_entity_ops;
        uds->entity.type = VSP1_ENTITY_UDS;
        uds->entity.index = index;
 
-       ret = vsp1_entity_init(vsp1, &uds->entity, 2);
+       sprintf(name, "uds.%u", index);
+       ret = vsp1_entity_init(vsp1, &uds->entity, name, 2, &uds_ops);
        if (ret < 0)
                return ERR_PTR(ret);
 
-       /* Initialize the V4L2 subdev. */
-       subdev = &uds->entity.subdev;
-       v4l2_subdev_init(subdev, &uds_ops);
-
-       subdev->entity.ops = &vsp1->media_ops;
-       subdev->internal_ops = &vsp1_subdev_internal_ops;
-       snprintf(subdev->name, sizeof(subdev->name), "%s uds.%u",
-                dev_name(vsp1->dev), index);
-       v4l2_set_subdevdata(subdev, uds);
-       subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-
-       vsp1_entity_init_formats(subdev, NULL);
-
        return uds;
 }
This page took 0.051343 seconds and 5 git commands to generate.