diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2014-04-16 16:41:25 +0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-07-17 16:18:09 +0400 |
commit | 0ba2aeb6dab80920edd9cf5b93b1ea4d6913b8f3 (patch) | |
tree | dd9f045fa482ee601cdf4ee67c649530f22abc5e /drivers/media/v4l2-core/v4l2-ctrls.c | |
parent | 7d6bc608e062f6b6667c9eeeb17055f017ecadb1 (diff) | |
download | linux-0ba2aeb6dab80920edd9cf5b93b1ea4d6913b8f3.tar.xz |
[media] v4l2-ctrls: increase internal min/max/step/def to 64 bit
While VIDIOC_QUERYCTRL is limited to 32 bit min/max/step/def values
for controls, the upcoming VIDIOC_QUERY_EXT_CTRL isn't. So increase
the internal representation to 64 bits in preparation.
Because of these changes the msi3101 driver has been modified slightly
to fix a formatting issue (%d becomes %lld), vivi had to be modified
as well to cope with the new 64-bit min/max values and the PIXEL_RATE
control in a few sensor drivers required proper min/max/def values.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ctrls.c')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-ctrls.c | 93 |
1 files changed, 57 insertions, 36 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 55c683254102..e132fa21ccd6 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -877,7 +877,7 @@ const char *v4l2_ctrl_get_name(u32 id) EXPORT_SYMBOL(v4l2_ctrl_get_name); void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, - s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags) + s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags) { *name = v4l2_ctrl_get_name(id); *flags = 0; @@ -1041,14 +1041,23 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, *type = V4L2_CTRL_TYPE_INTEGER; *flags |= V4L2_CTRL_FLAG_READ_ONLY; break; - case V4L2_CID_MPEG_VIDEO_DEC_FRAME: case V4L2_CID_MPEG_VIDEO_DEC_PTS: - *flags |= V4L2_CTRL_FLAG_VOLATILE; - /* Fall through */ + *type = V4L2_CTRL_TYPE_INTEGER64; + *flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY; + *min = *def = 0; + *max = 0x1ffffffffLL; + *step = 1; + break; + case V4L2_CID_MPEG_VIDEO_DEC_FRAME: + *type = V4L2_CTRL_TYPE_INTEGER64; + *flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY; + *min = *def = 0; + *max = 0x7fffffffffffffffLL; + *step = 1; + break; case V4L2_CID_PIXEL_RATE: *type = V4L2_CTRL_TYPE_INTEGER64; *flags |= V4L2_CTRL_FLAG_READ_ONLY; - *min = *max = *step = *def = 0; break; default: *type = V4L2_CTRL_TYPE_INTEGER; @@ -1352,7 +1361,7 @@ static int cluster_changed(struct v4l2_ctrl *master) /* Control range checking */ static int check_range(enum v4l2_ctrl_type type, - s32 min, s32 max, u32 step, s32 def) + s64 min, s64 max, u64 step, s64 def) { switch (type) { case V4L2_CTRL_TYPE_BOOLEAN: @@ -1360,7 +1369,8 @@ static int check_range(enum v4l2_ctrl_type type, return -ERANGE; /* fall through */ case V4L2_CTRL_TYPE_INTEGER: - if (step <= 0 || min > max || def < min || def > max) + case V4L2_CTRL_TYPE_INTEGER64: + if (step == 0 || min > max || def < min || def > max) return -ERANGE; return 0; case V4L2_CTRL_TYPE_BITMASK: @@ -1385,23 +1395,30 @@ static int check_range(enum v4l2_ctrl_type type, } } +/* Round towards the closest legal value */ +#define ROUND_TO_RANGE(val, offset_type, ctrl) \ +({ \ + offset_type offset; \ + val += (ctrl)->step / 2; \ + val = clamp_t(typeof(val), val, \ + (ctrl)->minimum, (ctrl)->maximum); \ + offset = (val) - (ctrl)->minimum; \ + offset = (ctrl)->step * (offset / (ctrl)->step); \ + val = (ctrl)->minimum + offset; \ + 0; \ +}) + /* Validate a new control */ static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c) { size_t len; - u32 offset; - s32 val; switch (ctrl->type) { case V4L2_CTRL_TYPE_INTEGER: - /* Round towards the closest legal value */ - val = c->value + ctrl->step / 2; - val = clamp(val, ctrl->minimum, ctrl->maximum); - offset = val - ctrl->minimum; - offset = ctrl->step * (offset / ctrl->step); - c->value = ctrl->minimum + offset; - return 0; + return ROUND_TO_RANGE(*(s32 *)&c->value, u32, ctrl); + case V4L2_CTRL_TYPE_INTEGER64: + return ROUND_TO_RANGE(*(s64 *)&c->value64, u64, ctrl); case V4L2_CTRL_TYPE_BOOLEAN: c->value = !!c->value; @@ -1427,9 +1444,6 @@ static int validate_new(const struct v4l2_ctrl *ctrl, c->value = 0; return 0; - case V4L2_CTRL_TYPE_INTEGER64: - return 0; - case V4L2_CTRL_TYPE_STRING: len = strlen(c->string); if (len < ctrl->minimum) @@ -1653,7 +1667,7 @@ unlock: static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, const char *name, enum v4l2_ctrl_type type, - s32 min, s32 max, u32 step, s32 def, + s64 min, s64 max, u64 step, s64 def, u32 flags, const char * const *qmenu, const s64 *qmenu_int, void *priv) { @@ -1738,10 +1752,10 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, const s64 *qmenu_int = cfg->qmenu_int; enum v4l2_ctrl_type type = cfg->type; u32 flags = cfg->flags; - s32 min = cfg->min; - s32 max = cfg->max; - u32 step = cfg->step; - s32 def = cfg->def; + s64 min = cfg->min; + s64 max = cfg->max; + u64 step = cfg->step; + s64 def = cfg->def; if (name == NULL) v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step, @@ -1774,7 +1788,7 @@ EXPORT_SYMBOL(v4l2_ctrl_new_custom); /* Helper function for standard non-menu controls */ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, - u32 id, s32 min, s32 max, u32 step, s32 def) + u32 id, s64 min, s64 max, u64 step, s64 def) { const char *name; enum v4l2_ctrl_type type; @@ -1794,15 +1808,17 @@ EXPORT_SYMBOL(v4l2_ctrl_new_std); /* Helper function for standard menu controls */ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, - u32 id, s32 max, s32 mask, s32 def) + u32 id, u8 _max, u64 mask, u8 _def) { const char * const *qmenu = NULL; const s64 *qmenu_int = NULL; unsigned int qmenu_int_len = 0; const char *name; enum v4l2_ctrl_type type; - s32 min; - s32 step; + s64 min; + s64 max = _max; + s64 def = _def; + u64 step; u32 flags; v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); @@ -1823,14 +1839,16 @@ EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); /* Helper function for standard menu controls with driver defined menu */ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl, - const struct v4l2_ctrl_ops *ops, u32 id, s32 max, - s32 mask, s32 def, const char * const *qmenu) + const struct v4l2_ctrl_ops *ops, u32 id, u8 _max, + u64 mask, u8 _def, const char * const *qmenu) { enum v4l2_ctrl_type type; const char *name; u32 flags; - s32 step; - s32 min; + u64 step; + s64 min; + s64 max = _max; + s64 def = _def; /* v4l2_ctrl_new_std_menu_items() should only be called for * standard controls without a standard menu. @@ -1854,12 +1872,14 @@ EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items); /* Helper function for standard integer menu controls */ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, - u32 id, s32 max, s32 def, const s64 *qmenu_int) + u32 id, u8 _max, u8 _def, const s64 *qmenu_int) { const char *name; enum v4l2_ctrl_type type; - s32 min; - s32 step; + s64 min; + u64 step; + s64 max = _max; + s64 def = _def; u32 flags; v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); @@ -2887,13 +2907,14 @@ void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void EXPORT_SYMBOL(v4l2_ctrl_notify); int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, - s32 min, s32 max, u32 step, s32 def) + s64 min, s64 max, u64 step, s64 def) { int ret = check_range(ctrl->type, min, max, step, def); struct v4l2_ext_control c; switch (ctrl->type) { case V4L2_CTRL_TYPE_INTEGER: + case V4L2_CTRL_TYPE_INTEGER64: case V4L2_CTRL_TYPE_BOOLEAN: case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_INTEGER_MENU: |