BACKPORT: media: v4l: move helper functions for fractions from uvc to v4l2-common
The functions uvc_simplify_fraction and uvc_fraction_to_interval are generic helpers which are also useful for other v4l2 drivers. This patch moves them to v4l2-common. Tested-by: Daniel Scally <dan.scally@ideasonboard.com> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Link: https://lore.kernel.org/r/20220909221335.15033-2-m.grzeschik@pengutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit 6ba8b8d45335180523df8f1b6cd1c995a3dbf560) arakesh: resolved minor conflicts in include/media/v4l2-common.h and drivers/media/v4l2-core/v4l2-common.c Bug: 259171206 Change-Id: I17eea1ef6788ba98599b1d8a12499147ebef7d60 Signed-off-by: Avichal Rakesh <arakesh@google.com>
This commit is contained in:
committed by
bengris32
parent
2a3e5091fa
commit
0b4875713c
@@ -265,86 +265,6 @@ static u32 uvc_colorspace(const u8 primaries)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Simplify a fraction using a simple continued fraction decomposition. The
|
||||
* idea here is to convert fractions such as 333333/10000000 to 1/30 using
|
||||
* 32 bit arithmetic only. The algorithm is not perfect and relies upon two
|
||||
* arbitrary parameters to remove non-significative terms from the simple
|
||||
* continued fraction decomposition. Using 8 and 333 for n_terms and threshold
|
||||
* respectively seems to give nice results.
|
||||
*/
|
||||
void uvc_simplify_fraction(u32 *numerator, u32 *denominator,
|
||||
unsigned int n_terms, unsigned int threshold)
|
||||
{
|
||||
u32 *an;
|
||||
u32 x, y, r;
|
||||
unsigned int i, n;
|
||||
|
||||
an = kmalloc_array(n_terms, sizeof(*an), GFP_KERNEL);
|
||||
if (an == NULL)
|
||||
return;
|
||||
|
||||
/* Convert the fraction to a simple continued fraction. See
|
||||
* https://mathforum.org/dr.math/faq/faq.fractions.html
|
||||
* Stop if the current term is bigger than or equal to the given
|
||||
* threshold.
|
||||
*/
|
||||
x = *numerator;
|
||||
y = *denominator;
|
||||
|
||||
for (n = 0; n < n_terms && y != 0; ++n) {
|
||||
an[n] = x / y;
|
||||
if (an[n] >= threshold) {
|
||||
if (n < 2)
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
|
||||
r = x - an[n] * y;
|
||||
x = y;
|
||||
y = r;
|
||||
}
|
||||
|
||||
/* Expand the simple continued fraction back to an integer fraction. */
|
||||
x = 0;
|
||||
y = 1;
|
||||
|
||||
for (i = n; i > 0; --i) {
|
||||
r = y;
|
||||
y = an[i-1] * y + x;
|
||||
x = r;
|
||||
}
|
||||
|
||||
*numerator = y;
|
||||
*denominator = x;
|
||||
kfree(an);
|
||||
}
|
||||
|
||||
/* Convert a fraction to a frame interval in 100ns multiples. The idea here is
|
||||
* to compute numerator / denominator * 10000000 using 32 bit fixed point
|
||||
* arithmetic only.
|
||||
*/
|
||||
u32 uvc_fraction_to_interval(u32 numerator, u32 denominator)
|
||||
{
|
||||
u32 multiplier;
|
||||
|
||||
/* Saturate the result if the operation would overflow. */
|
||||
if (denominator == 0 ||
|
||||
numerator/denominator >= ((u32)-1)/10000000)
|
||||
return (u32)-1;
|
||||
|
||||
/* Divide both the denominator and the multiplier by two until
|
||||
* numerator * multiplier doesn't overflow. If anyone knows a better
|
||||
* algorithm please let me know.
|
||||
*/
|
||||
multiplier = 10000000;
|
||||
while (numerator > ((u32)-1)/multiplier) {
|
||||
multiplier /= 2;
|
||||
denominator /= 2;
|
||||
}
|
||||
|
||||
return denominator ? numerator * multiplier / denominator : 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Terminal and unit management
|
||||
*/
|
||||
|
||||
@@ -376,7 +376,7 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
|
||||
mutex_unlock(&stream->mutex);
|
||||
|
||||
denominator = 10000000;
|
||||
uvc_simplify_fraction(&numerator, &denominator, 8, 333);
|
||||
v4l2_simplify_fraction(&numerator, &denominator, 8, 333);
|
||||
|
||||
memset(parm, 0, sizeof(*parm));
|
||||
parm->type = stream->type;
|
||||
@@ -417,7 +417,7 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
|
||||
else
|
||||
timeperframe = parm->parm.output.timeperframe;
|
||||
|
||||
interval = uvc_fraction_to_interval(timeperframe.numerator,
|
||||
interval = v4l2_fraction_to_interval(timeperframe.numerator,
|
||||
timeperframe.denominator);
|
||||
uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",
|
||||
timeperframe.numerator, timeperframe.denominator, interval);
|
||||
@@ -471,7 +471,7 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
|
||||
/* Return the actual frame period. */
|
||||
timeperframe.numerator = probe.dwFrameInterval;
|
||||
timeperframe.denominator = 10000000;
|
||||
uvc_simplify_fraction(&timeperframe.numerator,
|
||||
v4l2_simplify_fraction(&timeperframe.numerator,
|
||||
&timeperframe.denominator, 8, 333);
|
||||
|
||||
if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
|
||||
@@ -1295,7 +1295,7 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh,
|
||||
fival->discrete.numerator =
|
||||
frame->dwFrameInterval[index];
|
||||
fival->discrete.denominator = 10000000;
|
||||
uvc_simplify_fraction(&fival->discrete.numerator,
|
||||
v4l2_simplify_fraction(&fival->discrete.numerator,
|
||||
&fival->discrete.denominator, 8, 333);
|
||||
} else {
|
||||
fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
|
||||
@@ -1305,11 +1305,11 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh,
|
||||
fival->stepwise.max.denominator = 10000000;
|
||||
fival->stepwise.step.numerator = frame->dwFrameInterval[2];
|
||||
fival->stepwise.step.denominator = 10000000;
|
||||
uvc_simplify_fraction(&fival->stepwise.min.numerator,
|
||||
v4l2_simplify_fraction(&fival->stepwise.min.numerator,
|
||||
&fival->stepwise.min.denominator, 8, 333);
|
||||
uvc_simplify_fraction(&fival->stepwise.max.numerator,
|
||||
v4l2_simplify_fraction(&fival->stepwise.max.numerator,
|
||||
&fival->stepwise.max.denominator, 8, 333);
|
||||
uvc_simplify_fraction(&fival->stepwise.step.numerator,
|
||||
v4l2_simplify_fraction(&fival->stepwise.step.numerator,
|
||||
&fival->stepwise.step.denominator, 8, 333);
|
||||
}
|
||||
|
||||
|
||||
@@ -802,9 +802,6 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
|
||||
struct uvc_xu_control_query *xqry);
|
||||
|
||||
/* Utility functions */
|
||||
void uvc_simplify_fraction(u32 *numerator, u32 *denominator,
|
||||
unsigned int n_terms, unsigned int threshold);
|
||||
u32 uvc_fraction_to_interval(u32 numerator, u32 denominator);
|
||||
struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts,
|
||||
u8 epaddr);
|
||||
|
||||
|
||||
@@ -444,3 +444,127 @@ int v4l2_s_parm_cap(struct video_device *vdev,
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(v4l2_s_parm_cap);
|
||||
|
||||
s64 v4l2_get_link_freq(struct v4l2_ctrl_handler *handler, unsigned int mul,
|
||||
unsigned int div)
|
||||
{
|
||||
struct v4l2_ctrl *ctrl;
|
||||
s64 freq;
|
||||
|
||||
ctrl = v4l2_ctrl_find(handler, V4L2_CID_LINK_FREQ);
|
||||
if (ctrl) {
|
||||
struct v4l2_querymenu qm = { .id = V4L2_CID_LINK_FREQ };
|
||||
int ret;
|
||||
|
||||
qm.index = v4l2_ctrl_g_ctrl(ctrl);
|
||||
|
||||
ret = v4l2_querymenu(handler, &qm);
|
||||
if (ret)
|
||||
return -ENOENT;
|
||||
|
||||
freq = qm.value;
|
||||
} else {
|
||||
if (!mul || !div)
|
||||
return -ENOENT;
|
||||
|
||||
ctrl = v4l2_ctrl_find(handler, V4L2_CID_PIXEL_RATE);
|
||||
if (!ctrl)
|
||||
return -ENOENT;
|
||||
|
||||
freq = div_u64(v4l2_ctrl_g_ctrl_int64(ctrl) * mul, div);
|
||||
|
||||
pr_warn("%s: Link frequency estimated using pixel rate: result might be inaccurate\n",
|
||||
__func__);
|
||||
pr_warn("%s: Consider implementing support for V4L2_CID_LINK_FREQ in the transmitter driver\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
return freq > 0 ? freq : -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(v4l2_get_link_freq);
|
||||
|
||||
/*
|
||||
* Simplify a fraction using a simple continued fraction decomposition. The
|
||||
* idea here is to convert fractions such as 333333/10000000 to 1/30 using
|
||||
* 32 bit arithmetic only. The algorithm is not perfect and relies upon two
|
||||
* arbitrary parameters to remove non-significative terms from the simple
|
||||
* continued fraction decomposition. Using 8 and 333 for n_terms and threshold
|
||||
* respectively seems to give nice results.
|
||||
*/
|
||||
void v4l2_simplify_fraction(u32 *numerator, u32 *denominator,
|
||||
unsigned int n_terms, unsigned int threshold)
|
||||
{
|
||||
u32 *an;
|
||||
u32 x, y, r;
|
||||
unsigned int i, n;
|
||||
|
||||
an = kmalloc_array(n_terms, sizeof(*an), GFP_KERNEL);
|
||||
if (an == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Convert the fraction to a simple continued fraction. See
|
||||
* https://en.wikipedia.org/wiki/Continued_fraction
|
||||
* Stop if the current term is bigger than or equal to the given
|
||||
* threshold.
|
||||
*/
|
||||
x = *numerator;
|
||||
y = *denominator;
|
||||
|
||||
for (n = 0; n < n_terms && y != 0; ++n) {
|
||||
an[n] = x / y;
|
||||
if (an[n] >= threshold) {
|
||||
if (n < 2)
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
|
||||
r = x - an[n] * y;
|
||||
x = y;
|
||||
y = r;
|
||||
}
|
||||
|
||||
/* Expand the simple continued fraction back to an integer fraction. */
|
||||
x = 0;
|
||||
y = 1;
|
||||
|
||||
for (i = n; i > 0; --i) {
|
||||
r = y;
|
||||
y = an[i-1] * y + x;
|
||||
x = r;
|
||||
}
|
||||
|
||||
*numerator = y;
|
||||
*denominator = x;
|
||||
kfree(an);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(v4l2_simplify_fraction);
|
||||
|
||||
/*
|
||||
* Convert a fraction to a frame interval in 100ns multiples. The idea here is
|
||||
* to compute numerator / denominator * 10000000 using 32 bit fixed point
|
||||
* arithmetic only.
|
||||
*/
|
||||
u32 v4l2_fraction_to_interval(u32 numerator, u32 denominator)
|
||||
{
|
||||
u32 multiplier;
|
||||
|
||||
/* Saturate the result if the operation would overflow. */
|
||||
if (denominator == 0 ||
|
||||
numerator/denominator >= ((u32)-1)/10000000)
|
||||
return (u32)-1;
|
||||
|
||||
/*
|
||||
* Divide both the denominator and the multiplier by two until
|
||||
* numerator * multiplier doesn't overflow. If anyone knows a better
|
||||
* algorithm please let me know.
|
||||
*/
|
||||
multiplier = 10000000;
|
||||
while (numerator > ((u32)-1)/multiplier) {
|
||||
multiplier /= 2;
|
||||
denominator /= 2;
|
||||
}
|
||||
|
||||
return denominator ? numerator * multiplier / denominator : 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(v4l2_fraction_to_interval);
|
||||
|
||||
@@ -384,4 +384,29 @@ int v4l2_g_parm_cap(struct video_device *vdev,
|
||||
int v4l2_s_parm_cap(struct video_device *vdev,
|
||||
struct v4l2_subdev *sd, struct v4l2_streamparm *a);
|
||||
|
||||
/**
|
||||
* v4l2_get_link_freq - Get link rate from transmitter
|
||||
*
|
||||
* @handler: The transmitter's control handler
|
||||
* @mul: The multiplier between pixel rate and link frequency. Bits per pixel on
|
||||
* D-PHY, samples per clock on parallel. 0 otherwise.
|
||||
* @div: The divisor between pixel rate and link frequency. Number of data lanes
|
||||
* times two on D-PHY, 1 on parallel. 0 otherwise.
|
||||
*
|
||||
* This function is intended for obtaining the link frequency from the
|
||||
* transmitter sub-devices. It returns the link rate, either from the
|
||||
* V4L2_CID_LINK_FREQ control implemented by the transmitter, or value
|
||||
* calculated based on the V4L2_CID_PIXEL_RATE implemented by the transmitter.
|
||||
*
|
||||
* Returns link frequency on success, otherwise a negative error code:
|
||||
* -ENOENT: Link frequency or pixel rate control not found
|
||||
* -EINVAL: Invalid link frequency value
|
||||
*/
|
||||
s64 v4l2_get_link_freq(struct v4l2_ctrl_handler *handler, unsigned int mul,
|
||||
unsigned int div);
|
||||
|
||||
void v4l2_simplify_fraction(u32 *numerator, u32 *denominator,
|
||||
unsigned int n_terms, unsigned int threshold);
|
||||
u32 v4l2_fraction_to_interval(u32 numerator, u32 denominator);
|
||||
|
||||
#endif /* V4L2_COMMON_H_ */
|
||||
|
||||
Reference in New Issue
Block a user