media: v4l2-ctrls: add v4l2_ctrl_modify_dimensions
authorHans Verkuil <hverkuil-cisco@xs4all.nl>
Mon, 11 Jul 2022 10:21:09 +0000 (12:21 +0200)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Fri, 19 Aug 2022 11:47:54 +0000 (13:47 +0200)
Add a new function to modify the dimensions of an array control.

This is typically used if the array size depends on e.g. the currently
selected video format.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/v4l2-core/v4l2-ctrls-api.c
include/media/v4l2-ctrls.h

index 6f1b72c59e8ea46fbaaef1aae5267dec10b5bf47..878da859210691cd7bbeab38c53bfb80a929a495 100644 (file)
@@ -989,6 +989,42 @@ int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
 }
 EXPORT_SYMBOL(__v4l2_ctrl_modify_range);
 
+int __v4l2_ctrl_modify_dimensions(struct v4l2_ctrl *ctrl,
+                                 u32 dims[V4L2_CTRL_MAX_DIMS])
+{
+       unsigned int elems = 1;
+       unsigned int i;
+       void *p_array;
+
+       lockdep_assert_held(ctrl->handler->lock);
+
+       if (!ctrl->is_array || ctrl->is_dyn_array)
+               return -EINVAL;
+
+       for (i = 0; i < ctrl->nr_of_dims; i++)
+               elems *= dims[i];
+       if (elems == 0)
+               return -EINVAL;
+       p_array = kvzalloc(2 * elems * ctrl->elem_size, GFP_KERNEL);
+       if (!p_array)
+               return -ENOMEM;
+       kvfree(ctrl->p_array);
+       ctrl->p_array_alloc_elems = elems;
+       ctrl->elems = elems;
+       ctrl->new_elems = elems;
+       ctrl->p_array = p_array;
+       ctrl->p_new.p = p_array;
+       ctrl->p_cur.p = p_array + elems * ctrl->elem_size;
+       for (i = 0; i < ctrl->nr_of_dims; i++)
+               ctrl->dims[i] = dims[i];
+       for (i = 0; i < elems; i++)
+               ctrl->type_ops->init(ctrl, i, ctrl->p_cur);
+       cur_to_new(ctrl);
+       send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_VALUE);
+       return 0;
+}
+EXPORT_SYMBOL(__v4l2_ctrl_modify_dimensions);
+
 /* Implement VIDIOC_QUERY_EXT_CTRL */
 int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc)
 {
index c7a082c319d42f656ef9a82cc810074e3bd80fb2..60796030957949dba400e39fa84c45af7eab235e 100644 (file)
@@ -957,6 +957,59 @@ static inline int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
        return rval;
 }
 
+/**
+ *__v4l2_ctrl_modify_dimensions() - Unlocked variant of v4l2_ctrl_modify_dimensions()
+ *
+ * @ctrl:      The control to update.
+ * @dims:      The control's new dimensions.
+ *
+ * Update the dimensions of an array control on the fly. The elements of the
+ * array are reset to their default value, even if the dimensions are
+ * unchanged.
+ *
+ * An error is returned if @dims is invalid for this control.
+ *
+ * The caller is responsible for acquiring the control handler mutex on behalf
+ * of __v4l2_ctrl_modify_dimensions().
+ *
+ * Note: calling this function when the same control is used in pending requests
+ * is untested. It should work (a request with the wrong size of the control
+ * will drop that control silently), but it will be very confusing.
+ */
+int __v4l2_ctrl_modify_dimensions(struct v4l2_ctrl *ctrl,
+                                 u32 dims[V4L2_CTRL_MAX_DIMS]);
+
+/**
+ * v4l2_ctrl_modify_dimensions() - Update the dimensions of an array control.
+ *
+ * @ctrl:      The control to update.
+ * @dims:      The control's new dimensions.
+ *
+ * Update the dimensions of an array control on the fly. The elements of the
+ * array are reset to their default value, even if the dimensions are
+ * unchanged.
+ *
+ * An error is returned if @dims is invalid for this control type.
+ *
+ * This function assumes that the control handler is not locked and will
+ * take the lock itself.
+ *
+ * Note: calling this function when the same control is used in pending requests
+ * is untested. It should work (a request with the wrong size of the control
+ * will drop that control silently), but it will be very confusing.
+ */
+static inline int v4l2_ctrl_modify_dimensions(struct v4l2_ctrl *ctrl,
+                                             u32 dims[V4L2_CTRL_MAX_DIMS])
+{
+       int rval;
+
+       v4l2_ctrl_lock(ctrl);
+       rval = __v4l2_ctrl_modify_dimensions(ctrl, dims);
+       v4l2_ctrl_unlock(ctrl);
+
+       return rval;
+}
+
 /**
  * v4l2_ctrl_notify() - Function to set a notify callback for a control.
  *