Message ID | 20220908194750.3750310-2-m.grzeschik@pengutronix.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | usb: gadget: uvc: use configfs entries for negotiation and v4l2 VIDIOCS | expand |
Hi Michael - thanks for the patch On 08/09/2022 20:47, Michael Grzeschik wrote: > 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. > > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> This and #2 make sense to me, so for these two: Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> Tested-by: Daniel Scally <dan.scally@ideasonboard.com> > > --- > v1 -> v7: - > v7 -> v8: - ported all style fixes and broken links from latest version on rebase > v8 -> v13: - > > drivers/media/usb/uvc/uvc_driver.c | 84 -------------------------- > drivers/media/usb/uvc/uvc_v4l2.c | 14 ++--- > drivers/media/usb/uvc/uvcvideo.h | 3 - > drivers/media/v4l2-core/v4l2-common.c | 86 +++++++++++++++++++++++++++ > include/media/v4l2-common.h | 4 ++ > 5 files changed, 97 insertions(+), 94 deletions(-) > > diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c > index 9c05776f11d1f0..0f14dee4b6d794 100644 > --- a/drivers/media/usb/uvc/uvc_driver.c > +++ b/drivers/media/usb/uvc/uvc_driver.c > @@ -329,90 +329,6 @@ static enum v4l2_ycbcr_encoding uvc_ycbcr_enc(const u8 matrix_coefficients) > return V4L2_YCBCR_ENC_DEFAULT; /* Reserved */ > } > > -/* > - * 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://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); > -} > - > -/* > - * 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 > */ > diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c > index 4cc3fa6b8c9812..f4d4c33b6dfbd7 100644 > --- a/drivers/media/usb/uvc/uvc_v4l2.c > +++ b/drivers/media/usb/uvc/uvc_v4l2.c > @@ -386,7 +386,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; > @@ -427,7 +427,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_dbg(stream->dev, FORMAT, "Setting frame interval to %u/%u (%u)\n", > timeperframe.numerator, timeperframe.denominator, interval); > @@ -481,7 +481,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) { > @@ -1275,7 +1275,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; > @@ -1285,11 +1285,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); > } > > diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h > index 24c911aeebce56..ff710bdd38b3fd 100644 > --- a/drivers/media/usb/uvc/uvcvideo.h > +++ b/drivers/media/usb/uvc/uvcvideo.h > @@ -911,9 +911,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); > u16 uvc_endpoint_max_bpi(struct usb_device *dev, struct usb_host_endpoint *ep); > diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c > index e0fbe6ba4b6c49..40f56e044640d7 100644 > --- a/drivers/media/v4l2-core/v4l2-common.c > +++ b/drivers/media/v4l2-core/v4l2-common.c > @@ -484,3 +484,89 @@ s64 v4l2_get_link_freq(struct v4l2_ctrl_handler *handler, unsigned int mul, > 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); > diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h > index b708d63995f458..725ff91b26e063 100644 > --- a/include/media/v4l2-common.h > +++ b/include/media/v4l2-common.h > @@ -540,6 +540,10 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, u32 pixelformat, > 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); > + > static inline u64 v4l2_buffer_get_timestamp(const struct v4l2_buffer *buf) > { > /*
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 9c05776f11d1f0..0f14dee4b6d794 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -329,90 +329,6 @@ static enum v4l2_ycbcr_encoding uvc_ycbcr_enc(const u8 matrix_coefficients) return V4L2_YCBCR_ENC_DEFAULT; /* Reserved */ } -/* - * 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://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); -} - -/* - * 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 */ diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 4cc3fa6b8c9812..f4d4c33b6dfbd7 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -386,7 +386,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; @@ -427,7 +427,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_dbg(stream->dev, FORMAT, "Setting frame interval to %u/%u (%u)\n", timeperframe.numerator, timeperframe.denominator, interval); @@ -481,7 +481,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) { @@ -1275,7 +1275,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; @@ -1285,11 +1285,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); } diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 24c911aeebce56..ff710bdd38b3fd 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -911,9 +911,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); u16 uvc_endpoint_max_bpi(struct usb_device *dev, struct usb_host_endpoint *ep); diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index e0fbe6ba4b6c49..40f56e044640d7 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -484,3 +484,89 @@ s64 v4l2_get_link_freq(struct v4l2_ctrl_handler *handler, unsigned int mul, 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); diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index b708d63995f458..725ff91b26e063 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -540,6 +540,10 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, u32 pixelformat, 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); + static inline u64 v4l2_buffer_get_timestamp(const struct v4l2_buffer *buf) { /*
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. Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> --- v1 -> v7: - v7 -> v8: - ported all style fixes and broken links from latest version on rebase v8 -> v13: - drivers/media/usb/uvc/uvc_driver.c | 84 -------------------------- drivers/media/usb/uvc/uvc_v4l2.c | 14 ++--- drivers/media/usb/uvc/uvcvideo.h | 3 - drivers/media/v4l2-core/v4l2-common.c | 86 +++++++++++++++++++++++++++ include/media/v4l2-common.h | 4 ++ 5 files changed, 97 insertions(+), 94 deletions(-)