Re: [PATCH v5] media: imx208: Add imx208 camera sensor driver

2018-10-01 Thread Helmut Grohne
Hi Laurent,

On Fri, Sep 28, 2018 at 03:49:38PM +0200, Laurent Pinchart wrote:
> I don't think we'll reach an agreement here if we don't start talking about 
> real use cases. Would you have some to share ?

Fair enough, but at that point, we very much disconnect from the imx208
in the subject.

I'm working with a stereo camera. In that setup, you have two image
sensors and infer a three dimensional structure from images captured at
equal time points. For that to happen, it is important that the image
sensors use the same settings. In particular, settings such as expoure
and gain must match. That in turn means that you cannot use the
automatic exposure mode that comes with your image sensor.

This is one reason for implementing exposure control outside of the
image sensor. Typically you can categorize your parameters into three
classes that affect the brightness of an image: aperture, shutter speed
and some kind of gain. If you know the units of these parameters, you
can estimate the effect of changing them on the resulting image.

The algorithm for controlling brightness can be quite generic if you
know the units. V4L2_CID_EXPOSURE_ABSOLUTE is given in 100 µs. That
tends to work well. Typically, you prefer increasing exposure over
increasing gain to avoid noise. Similarly, you prefer increasing
analogue gain over increasing digital gain. On the other hand, there is
a limit on exposure to avoid motion blur. If an algorithm knows valid
values for these parameters, it can produce settings independently of
what concrete image sensor you use.

> >  I can see two solutions here:
> >  
> >  1) Define the control range from 0 to 4 and treat it as an exponent
> >  of 2, so that the value for the sensor becomes (1 << val) * 256.
> >  (Suggested by Sakari offline.)
> >  
> >  This approach has the problem of losing the original unit (and scale)
> >  of the value.
> > 
> > This approach is the one where users will need to know which sensor they
> > talk to. The one where the hardware abstraction happens in userspace.
> > Can we please not do that?
> 
> Let's talk about it based on real use cases.

So if you change your gain from 0 to 1, your image becomes roughly twice
as bright. In the typical scenario that's too bright, so when increasing
gain, you simultaneously decrease something else (e.g. exposure). But if
you don't know the effect of your gain change, you cannot tell how much
your exposure needs to be reduced. The only way out here is just doing
it and reducing exposure afterwards. Users tend to not like the
flickering resulting from this approach.

> >  * If it is non-linear and has fewer than X (1025?) values, use the
> >integer menu.
> 
> 1024 ioctl calls to query the menu values ? :-( We need a better API than 
> that. I'm also concerned that it wouldn't be very usable by userspace. Having 
> a list of supported values is one thing, making efficient use of it is 
> another. Again, use cases :-)

You only need to query it once, but I'm not opposed to a better API
either. I just don't think it is that important or urgent.

> I expect many algorithms to need a mathematical view of the valid values, not 
> just a list. What particular algorithms do you have in mind ?

A very simple algorithm could go like this:
 * Assume that exposure time and gain have a linear effect on the
   brightness of a captured image. This tends to not hold exactly, but
   close enough.
 * Compare brightness of the previous frame with a target value.
 * Compute the product of current exposure time and gain. Adapt the
   product according to the brightness error.
 * Distribute this product to exposure time and gain such that exposure
   time is maximal below a user-defined limit and that gain is one of
   the valid values.

All you need to know for using this besides V4L2_CID_EXPOSURE_ABSOLUTE,
is the valid gain values.

Now I wonder, does this help in reaching a conclusion about whether
querying valid gain values is a relevant use case?

Helmut


Re: [PATCH 2/5] v4l: controls: Add support for exponential bases, prefixes and units

2018-10-01 Thread Helmut Grohne
On Fri, Sep 28, 2018 at 04:00:17PM +0200, Hans Verkuil wrote:
> On 09/25/2018 12:14 PM, Sakari Ailus wrote:
> > +/* V4L2 control unit prefixes */
> > +#define V4L2_CTRL_PREFIX_NANO  -9
> > +#define V4L2_CTRL_PREFIX_MICRO -6
> > +#define V4L2_CTRL_PREFIX_MILLI -3
> > +#define V4L2_CTRL_PREFIX_1 0
> 
> I would prefer PREFIX_NONE, since there is no prefix in this case.
> 
> I assume this prefix is only valid if the unit is not UNDEFINED and not
> NONE?

Why should it? The prefix is concerned with rescaling a value prior to
presenting it to a user. Even a unitless quantity or a value of
undefined unit can be reasonably scaled. Displaying a unit and scaling
look like orthogonal concepts to me.

> Is 'base' also dependent on a valid unit? (it doesn't appear to be)

I'd argue it should not depend on a valid unit like the prefix.

Helmut


Re: [PATCH 0/5] Add units to controls

2018-09-26 Thread Helmut Grohne
On Tue, Sep 25, 2018 at 02:30:31PM +0200, Sakari Ailus wrote:
> On Tue, Sep 25, 2018 at 01:48:02PM +0200, Helmut Grohne wrote:
> > 1. There are a number of controls whose value is not easily described as
> >either linear or exponential. I'm faced with at least two controls
> >that actually are floating point numbers. One with two bits for the
> >exponent and one (strange) bit for the mantissa (no joke) and another
> >with three bits for the exponent and four bits for the mantissa.
> >Neither can suitably be represented.

> The proposal does not address all potential situations, that's true.
> There's no way to try to represent everything out there (without
> enumerating the values) in an easily generalised way but something can be
> done.

Sure, but the rounding control flag would address that. The rounding
control flag could also solve exponential controls. Since there is a
certain overlap here. These proposals should be discussed together. We
should avoid solving problems twice.

> There are devices such as some flash LED controllers where the flash current
> if simply a value you can pick from the list. It's currently implemented as
> an integer control. AFAIR the driver is drivers/leds/leds-aat1290.c .

Possibly, relaxing the "each control id has a fixed type" requirement is
another option. Allowing an integer menu wherever an integer is
specified could solve issues such as these in a different way.

Again it is fine that your proposal, does not cover that. Still these
uapi changes are interdependent and therefore need to be considered
together.

> The fact is that the unit is specific to hardware. The documentation
> documents something, and often suggests a unit, but if the hardware does
> something else, then that's what you get --- independently of what the
> documentation says.
> 
> Hence the need to convey it via the API.

That is vaguely convincing. It still seems like a niche case.

> Some controls could have the unit set by the framework if that makes sense.

I'd use a stronger s/could/should/ here as it directly translates into
maintenance cost.

> Most drivers shouldn't actually need to touch this if they're fine with
> defaults (whenever a control has a default).

Exactly this. Therefore I think you shouldn't update smiapp, but the
framework instead.

> A macro or two, it's not a major change. From the user space point of view,
> does it make a difference if a control has no unit or when it's not known
> what the unit is?

There are situations where there is a difference. If you count things
(e.g. reference pictures V4L2_CID_MPEG_VIDEO_MAX_REF_PIC), there is no
unit, but that's different from unknown. Having unknown separate from no
unit also helps with the transition period where controls lack units.

Therefore, i'm in favour of keeping the distinction between unknown and
no unit. Still, I don't think that merging them is fundamentally
"wrong".

> Yes, I think [V4L2_CTRL_FLAG_EXPONENTIAL] can be dropped as I suggested.

Ok. Looking forward to the rounding flag then.

> > Thus, I think that control over the rounding is tightly related to this
> > patchset and needs to be discussed together.
> 
> It addresses some of the same problem area but the implementation is
> orthogonal to this.

I don't disagree here. Still I think that the question "what should be
implemented" (not how) is dependent on those other problems.

> Providing that would probably make the base field less useful: the valid
> control values could be enumerated by the user using TRY_EXT_CTRLS without
> the need to tell the valid values are powers of e.g. two.

After dropping V4L2_CTRL_FLAG_EXPONENTIAL, the base field is
meaningless, no?

> I don't really have a strong opinion on that actually when it comes to the
> API itself. The imx208 driver could proceed to use linear relation between
> the control value and the digital gain. My worry is just the driver
> implementation: this may not be entirely trivial. There's still no way to
> address this problem in a generic way otherwise.

Yeah, I'm mostly looking at this from an uapi pov (as that is the one
that cannot be changed later) and have no good answer here. Allowing
integer menus for integers would be easy from a driver pov though.

Helmut


Re: [PATCH 0/5] Add units to controls

2018-09-25 Thread Helmut Grohne
On Tue, Sep 25, 2018 at 12:14:29PM +0200, Sakari Ailus wrote:
> This set adds a few things to the current control framework in terms of
> what kind of information the user space may have on controls. It adds
> support for units and prefixes, exponential base as well as information on
> whether a control is linear or exponential, to struct v4l2_query_ext_ctrl.

That's a great improvement. Being able to give meaning to controls is
great. However, I see two significant weaknesses in the approach being
taken:

1. There are a number of controls whose value is not easily described as
   either linear or exponential. I'm faced with at least two controls
   that actually are floating point numbers. One with two bits for the
   exponent and one (strange) bit for the mantissa (no joke) and another
   with three bits for the exponent and four bits for the mantissa.
   Neither can suitably be represented.

   Since the value ranges are small for the cases I mentioned, I looked
   into using an integer menu. The present approach does not allow for
   replacing an integer with an integer menu though. Each control id has
   a fixed type. I'm not sure how to solve this.

2. The present implementation places the responsibility of assigning
   units and scales into drivers. A number of controls (e.g.
   V4L2_CID_EXPOSURE_ABSOLUTE, V4L2_CID_AUDIO_LIMITER_RELEASE_TIME,
   V4L2_CID_PIXEL_RATE, ...) clearly state the scale and unit in the
   documentation. Having each and every driver set units and scales in
   the documented way will lead to duplication and buggy code. Having
   each driver choose unit and scale will lead to inconsistency. It
   would be very good to have a mechanism that puts the framework in
   charge of maintaining units and scales for the standard control ids.

   What is a consumer supposed to do with a control that changes unit?
   The algorithm expected e.g. a duration. It might be able to convert
   to pixels, but what should it do if it gets back amperes? I argue
   that the unit should be a property of the control id and be
   documented (i.e. what is done now). If it is reported via an ioctl,
   the framework needs to be in charge of setting it.

   The story is much different for scales. Scaling the value up and down
   is something consumers can reasonably be expected to do. It allows
   shifting the value range such that the relevant values can be fully
   represented. Allowing drivers to change scales is much more
   reasonable. Still the framework should provide a default such that
   most drivers should not need any update.

I acknowledge that these expectations are high and see that they're
partially covered in your later remarks.

> The smiapp driver gains support for the feature. In the near term, some
> controls could also be assigned the unit automatically. The pixel rate,
> for instance. Fewer driver changes would be needed this way. A driver
> could override the value if there's a need to.

I believe that in the interest of keeping maintenance cost low, this
should happen rather sooner than later. Just even adding the support to
smiapp seems wrong when it would be possible to have the framework do
the work.

> I think I'll merge the undefined and no unit cases. Same for the
> exponential base actually --- the flag can be removed, too...

I'm not sure I understand. It reads like you are going to revert a
significant part of the patch.

> Regarding Ricardo's suggestion --- I was thinking of adding a control flag
> (yes, there are a few bits available) to tell how to round the value. The
> user could use the TRY_EXT_CTRLS IOCTL to figure out the next (or
> previous) control value by incrementing the current value and setting the
> appropriate flag. This is out of the scope of this set though.

This approach sounds really useful to me. Having control over the
rounding would allow reading supported control values with reasonable
effort. With such an approach, a very sparsely populated control becomes
feasible and with integer64 controls that'd likely allow representing
most exponential controls with linear values. If going this route, I
don't see an application of V4L2_CTRL_FLAG_EXPONENTIAL.

Thus, I think that control over the rounding is tightly related to this
patchset and needs to be discussed together.

Helmut


Re: [PATCH 3/5] Documentation: media: Document control exponential bases, units, prefixes

2018-09-25 Thread Helmut Grohne
On Tue, Sep 25, 2018 at 12:14:32PM +0200, Sakari Ailus wrote:
> +* - ``V4L2_CTRL_UNIT_PIXEL``
> +  - 5
> +  - A pixel in sensor's pixel matrix. This is a unit of time commonly 
> used
> +by camera sensors in e.g. exposure control, i.e. the time it takes 
> for
> + a sensor to read a pixel from the sensor's pixel matrix.
> +
> +* - ``V4L2_CTRL_UNIT_PIXEL``
> +  - 6

The latter V4L2_CTRL_UNIT_PIXEL looks like a typo that should say
V4L2_CTRL_UNIT_PIXELS_PER_SEC.

Helmut


Re: [PATCH 1/1] v4l: Remove support for crop default target in subdev drivers

2018-09-25 Thread Helmut Grohne
On Mon, Sep 24, 2018 at 04:42:27PM +0200, Sakari Ailus wrote:
> --- a/drivers/media/i2c/mt9t112.c
> +++ b/drivers/media/i2c/mt9t112.c
> @@ -888,12 +888,6 @@ static int mt9t112_get_selection(struct v4l2_subdev *sd,
>   sel->r.width = MAX_WIDTH;
>   sel->r.height = MAX_HEIGHT;
>   return 0;
> - case V4L2_SEL_TGT_CROP_DEFAULT:
> - sel->r.left = 0;
> - sel->r.top = 0;
> - sel->r.width = VGA_WIDTH;
> - sel->r.height = VGA_HEIGHT;
> - return 0;
>   case V4L2_SEL_TGT_CROP:
>   sel->r = priv->frame;
>   return 0;

Together with the change in soc_scale_crop.c, this constitutes an
(unintentional?) behaviour change. It was formerly reporting 640x480 and
will now be reporting 2048x1536. I cannot tell whether that is
reasonable.

> --- a/drivers/media/i2c/soc_camera/mt9t112.c
> +++ b/drivers/media/i2c/soc_camera/mt9t112.c
> @@ -884,12 +884,6 @@ static int mt9t112_get_selection(struct v4l2_subdev *sd,
>   sel->r.width = MAX_WIDTH;
>   sel->r.height = MAX_HEIGHT;
>   return 0;
> - case V4L2_SEL_TGT_CROP_DEFAULT:
> - sel->r.left = 0;
> - sel->r.top = 0;
> - sel->r.width = VGA_WIDTH;
> - sel->r.height = VGA_HEIGHT;
> - return 0;
>   case V4L2_SEL_TGT_CROP:
>   sel->r = priv->frame;
>   return 0;

This one looks duplicate. Is there a good reason to have two drivers for
mt9t112? This is lilely out of scope for the patch. Cced Jacopo Mondi as
he introduced the copy.

Other than your patch looks fine to me.

Helmut


Use of V4L2_SEL_TGT_CROP_DEFAULT in i2c subdev drivers

2018-09-24 Thread Helmut Grohne
Hi,

Documentation/media/uapi/v4l/v4l2-selection-targets.rst says that
V4L2_SEL_TGT_CROP_DEFAULT is not valid for subdev drivers. Looking into
drivers/media/i2c (which contains only subdev drivers except for
video-i2c.c), the following drivers implement V4L2_SEL_TGT_CROP_DEFAULT:

ak881x.c
mt9m111.c
mt9t112.c
ov2640.c
ov6650.c
ov772x.c
rj54n1cb0c.c
soc_camera/mt9m001.c
soc_camera/mt9t112.c
soc_camera/mt9v022.c
soc_camera/ov5642.c
soc_camera/ov772x.c
soc_camera/ov9640.c
soc_camera/ov9740.c
soc_camera/rj54n1cb0c.c
tvp5150.c

The majority of drivers behave equally for V4L2_SEL_TGT_CROP_DEFAULT and
V4L2_SEL_TGT_CROP_BOUNDS. The only exceptions are mt9t112.c and
soc_camera/mt9t112.c. Actually these two look very similar. A
significant fraction of differences is white space, case and operand
order.

Is this a bug in 16 drivers? Is this a documentation bug? Am I getting
something wrong?

Helmut


Re: [PATCH v5] media: imx208: Add imx208 camera sensor driver

2018-09-21 Thread Helmut Grohne
On Thu, Sep 20, 2018 at 11:00:26PM +0200, Laurent Pinchart wrote:
> On Thursday, 20 September 2018 23:16:47 EEST Sylwester Nawrocki wrote:
> > On 09/20/2018 06:49 PM, Grant Grundler wrote:
> > > On Thu, Sep 20, 2018 at 1:52 AM Tomasz Figa wrote:
> > >> We have a problem here. The sensor supports only a discrete range of
> > >> values here - {1, 2, 4, 8, 16} (multiplied by 256, since the value is
> > >> fixed point). This makes it possible for the userspace to set values
> > >> that are not allowed by the sensor specification and also leaves no
> > >> way to enumerate the supported values.

I'm not sure I understand this correctly. Tomasz appears to imply here
that the number of actually supported gain values is 5.

> > I'm not sure if it's best approach but I once did something similar for
> > the ov9650 sensor. The gain was fixed point 10-bits value with 4 bits
> > for fractional part. The driver reports values multiplied by 16. See
> > ov965x_set_gain() function in drivers/media/i2c/ov9650.c and "Table 4-1.
> > Total Gain to Control Bit Correlation" in the OV9650 datasheet for details.
> > The integer menu control just seemed not suitable for 2^10 values.

As long as values scale linearly (as is the case for fixed point
numbers) that seems like a reasonable approach to me. That assumption
appears to not hold for imx208 where the values scale exponentially.

> I've had a similar discussion on IRC recently with Helmut, who posted a nice 
> summary of the problem on the mailing list (see https://www.mail-archive.com/
> linux-media@vger.kernel.org/msg134502.html). This is a known issue, and while 
> I proposed the same approach, I understand that in some cases userspace may 
> need to know exactly what values are acceptable. In such a case, however, I 
> would expect userspace to have knowledge of the particular sensor model, so 
> the information may not need to come from the kernel.

A big reason to use V4L2 is to abstract hardware. Having to know what
sensor model you use runs counter that goal. Indeed, gain (whether
digital or analogue) can be abstracted in principle. I see little reason
to not do that.

> > Now the gain control has range 16...1984 out of which only 1024 values
> > are valid. It might not be best approach for a GUI but at least the driver
> > exposes mapping of all valid values, which could be enumerated with
> > VIDIOC_TRY_EXT_CTRLS if required, without a need for a driver-specific
> > user space code.

If you have very many values, a reasonable compromise could be reducing
the precision. If you try to represent a floating point number, values
with higher exponent will have larger "gaps" when represented as
integers for v4l2. A compromise could be increasing the step size and
thus removing a few of the gains with lower exponent.

> > >> I can see two solutions here:
> > >> 
> > >> 1) Define the control range from 0 to 4 and treat it as an exponent of
> > >> 2, so that the value for the sensor becomes (1 << val) * 256.
> > >> (Suggested by Sakari offline.)
> > >> 
> > >> This approach has the problem of losing the original unit (and scale)
> > >> of the value.

This approach is the one where users will need to know which sensor they
talk to. The one where the hardware abstraction happens in userspace.
Can we please not do that?

> > >> 2) Use an integer menu control, which reports only the supported
> > >> discrete values - {1, 2, 4, 8, 16}.

That's what I ended up doing, though I kinda deferred the problem as I
started using V4L2_CID_ISO_SENSITIVITY, which is an integer menu but not
exactly the right one. My choice will backfire once I submit the driver
though that'll still take a little while.

> > >> With this approach, userspace can enumerate the real gain values, but
> > >> we would either need to introduce a new control (e.g.
> > >> V4L2_CID_DIGITAL_GAIN_DISCRETE) or abuse the specification and
> > >> register V4L2_CID_DIGITAL_GAIN as an integer menu.
> > >> 
> > >> Any opinions or better ideas?

Abusing the specification sounds like it would break userspace. I'd
avoid doing that.

We do have a history of adding "duplicate" CIDs for gaining a better
specification. For instance, there is V4L2_CID_EXPOSURE (unspecified)
and then there came V4L2_CID_EXPOSURE_ABSOLUTE (unit 100 µs).
V4L2_CID_GAIN got split into V4L2_CID_ANALOGUE_GAIN and
V4L2_CID_DIGITAL_GAIN. Further splitting that into integer menu variants
of analogue and digital gain seems reasonable to me.

If doing so, I suggest using the following rules (up to discussion):
 * Drivers must not provide both the integer menu and an integer control
   for a single gain.
 * Define which value means "no amplification". For
   V4L2_CID_DIGITAL_GAIN this was defined as 0x100. Keeping that could
   be reasonable, but V4L2_CID_ANALOGUE_GAIN presently leavs that
   undefined.
 * If a gain is linear, use the integer control.
 * If it is non-linear and has fewer than X (1025?) values, use the
   integer menu.
 * Otherwise use the integer 

Re: V4L2 analogue gain contol

2018-08-27 Thread Helmut Grohne
Hi,

On Sun, Aug 26, 2018 at 08:52:09AM +0200, Pavel Machek wrote:
> > Can we give more structure to the analogue gain as exposed by V4L2?
> > Ideally, I'd like to query a driver for the possible gain values if
> > there are few (say < 256) and their factors (which are often given in
> > data sheets). The nature of gains though is that they are often similar
> > to floating point numbers (2 ** exp * (1 + mant / precision)), which
> > makes it difficult to represent them using min/max/step/default.
> 
> Yes, it would be nice to have uniform controls for that. And it would
> be good if mapping to "ISO" sensitivity from digital photography existed.

Thank you very much for this pointer.

There is V4L2_CID_ISO_SENSITIVITY. It is an integer menu, which means
that I can introspect the available values. It is already used by
s5c73m3 and m5mols. That looks mostly like what I need. It makes no
provision on how the image is amplified, whether digital or analogue.
I'd need analogue gain only here.

Reading the platform/exynos4-is/fimc and the i2c/s5c73m3 driver, I get
the impression that the scaling is not in accordance with
Documentation/media/uapi/v4l/extended-controls.rst ("standard ISO values
multiplied by 1000") though. -> Adding the maintainers/supporters to Cc.

> > Would it be reasonable to add a new V4L2_CID_ANALOGUE_GAIN_MENU that
> > claims linearity and uses fixed-point numbers like
> > V4L2_CID_DIGITAL_GAIN? There already is the integer menu
> > V4L2_CID_AUTO_EXPOSURE_BIAS, but it also affects the exposure.
> 
> I'm not sure if linear scale is really appropriate. You can expect
> camera to do ISO100 or ISO200, but if your camera supports ISO48,
> you don't really expect it to support ISO480100.

I may have been ambigue here. With "linear" I was not trying to imply
that cameras should support every possible value and maybe "linear" is
not the property I actually need.

What I need is a correspondence between gain value (the value you pass
to V4L2_CID_ANALOGUE_GAIN) and amplification factor (brightness increase
of the resulting image). A linear connection is the simplest of course,
but logarithmic works as well in principle.

My idea of using an integer menu here was that a significant number of
cameras have a low count of valid gain settings. For them, listing all
valid values may be a legitimate option. Indeed, that's what happened
for V4L2_CID_ISO_SENSITIVITY.

> ./drivers/media/i2c/et8ek8/et8ek8_driver.c already does that.
> 
> IOW logarithmic scale would be more appropriate; min/max would be
> nice, and step 

I'm sorry for missing this driver in the analysis. It certainly adds to
the picture.

Note however that simply logarithmic with a step will not be a
one-size-fits-all. Fixed point numbers do not map to a logarithmic scale
with fixed steps. You can achieve fewer "holes" in your representation,
but you won't get rid of them entirely.

In the majority of cases, you could represent the gain as a product of a
logarithmic and a linear scale each with fixed steps. Is that an option?

> > An important application is implementing a custom gain control when the
> > built-in auto exposure is not applicable.
> 
> Looking at et8ek8 again, perhaps that's the right solution? Userland
> just sets the gain, and the driver automatically selects best
> analog/digital gain combination.
> 
> /*
>  * This table describes what should be written to the sensor register
>   * for each gain value. The gain(index in the table) is in terms of
>* 0.1EV, i.e. 10 indexes in the table give 2 time more gain [0] in
> * the *analog gain, [1] in the digital gain
>  *
>   * Analog gain [dB] = 20*log10(regvalue/32); 0x20..0x100
>*/

That may work (even for just analogue gain), but it comes at a little
loss of flexibility. You stop exposing a number of gain values and
combinations. In some cases, you loose more than half of the valid
configurations.

Striking a balance between a simple and a flexible interface of course
is difficult. I'm not opposed to providing such a simple interface, but
I'd also like to retain the flexibility (with another and likely more
complex interface).

Given your reply, I see three significant alternatives to my proposal:

 * V4L2_CID_ISO_SENSITIVITY (even though it may use digital gain)

 * V4L2_CID_ANALOGUE_GAIN_ISO could be an integer menu control modeled
   after V4L2_CID_ISO_SENSITIVITY.

 * V4L2_CID_ANALOGUE_GAIN_LOG x + V4L2_CID_ANALOGUE_GAIN_LINEAR y such
   that the actual gain amplification value is 2 ** x * y (where x and y
   are each fixed point numbers with a to-be-determined fixed point).

I guess I'll try to work with V4L2_CID_ISO_SENSITIVITY.

Helmut


Re: [PATCH] media: aptina-pll: allow approximating the requested pix_clock

2018-08-27 Thread Helmut Grohne
On Sat, Aug 25, 2018 at 01:32:47PM +0200, Sakari Ailus wrote:
> On Fri, Aug 24, 2018 at 02:05:17PM +0200, Helmut Grohne wrote:
> > Take for instance MT9M024. The data sheet
> > (http://www.mouser.com/ds/2/308/MT9M024-D-606228.pdf) allows deducing
> > the following limits:
> > 
> > const struct aptina_pll_limits mt9m024_limits = {
> > .ext_clock_min = 600,
> > .ext_clock_max = 5000,
> > .int_clock_min = 200,
> > .int_clock_max = 2400,
> > .out_clock_min = 38400,
> > .out_clock_max = 76800,
> > .pix_clock_max = 7425,
> > .n_min = 1,
> > .n_max = 63,
> > .m_min = 32,
> > .m_max = 255,
> > .p1_min = 4,
> > .p1_max = 16,
> > };
> > 
> > Now if you choose ext_clock and pix_clock maximal within the given
> > limits, the existing aptina_pll_calculate gives up. Lowering the
> > pix_clock does not help either. Even down to 73 MHz, it is unable to
> > find any pll configuration.
> > 
> > The new algorithm finds a solution (n=11, m=98, p1=6) with 7.5 KHz
> > error. Incidentally, that solution is close to the one given by the
> > vendor tool (n=22, m=196, p1=6).
> 
> These values don't seem valid for 6 MHz --- the frequency after the PLL is
> less than 384 MHz. Did you use a different external clock frequency?

I wrote that I used the maximal external clock frequency, which is 50
MHz. For that value, the output clock is within the requested bounds.
Are you implying that the chosen pll parameters should be valid for all
possible external clocks simultaneously?

Helmut


Re: [PATCH] media: aptina-pll: allow approximating the requested pix_clock

2018-08-24 Thread Helmut Grohne
Hi Laurent,

Thank you for taking the time to reply to my patch and to my earlier
questions.

On Thu, Aug 23, 2018 at 01:12:15PM +0200, Laurent Pinchart wrote:
> Could you please share numbers, ideally when run in kernel space ?

Can you explain the benefits of profiling this inside the kernel rather
than outside? Doing it outside is much simpler, so I'd like to
understand your reasons. The next question is what kind of system to
profile on. I guess doing it on an X86 will not help. Typical users will
use some arm CPU and integer division on arm is slower than on x86. Is a
Cortex A9 ok?

If you can provide more relevant inputs, that'd also help. I was able to
derive an example input from the dt bindings for mt9p031 (ext=6MHz,
pix=96MHz) and also used random inputs for testing. Getting more
real-world inputs would help in producing a useful benchmark.

> This patch is very hard to review as you rewrite the whole, removing all the 
> documentation for the existing algorithm, without documenting the new one. 

That's not entirely fair. Unlike the original algorithm, I've split it
to multiple functions and unlike the original algorithm, I've documented
pre- and post-conditions. In a sense, that's actually more
documentation. At least, you now see what the functions are supposed to
be doing.

Inside the alogrithm, I've often writting which precondition
(in)equation I used in which particular step.

The variable naming choice makes it very clear that the first step is
reducing the value ranges for n, m, and p1 as much as possible before
proceeding to an actual parameter computation.

There was little choice in removing much of the old algorithm as the
approach of using gcd is numerically unstable. I actually kept
everything until the first gcd computation.

> There's also no example of a failing case with the existing code that works 
> with yours.

That is an unfortunate omission. I should have thought of this and
should have given it upfront. I'm sorry.

Take for instance MT9M024. The data sheet
(http://www.mouser.com/ds/2/308/MT9M024-D-606228.pdf) allows deducing
the following limits:

const struct aptina_pll_limits mt9m024_limits = {
.ext_clock_min = 600,
.ext_clock_max = 5000,
.int_clock_min = 200,
.int_clock_max = 2400,
.out_clock_min = 38400,
.out_clock_max = 76800,
.pix_clock_max = 7425,
.n_min = 1,
.n_max = 63,
.m_min = 32,
.m_max = 255,
.p1_min = 4,
.p1_max = 16,
};

Now if you choose ext_clock and pix_clock maximal within the given
limits, the existing aptina_pll_calculate gives up. Lowering the
pix_clock does not help either. Even down to 73 MHz, it is unable to
find any pll configuration.

The new algorithm finds a solution (n=11, m=98, p1=6) with 7.5 KHz
error. Incidentally, that solution is close to the one given by the
vendor tool (n=22, m=196, p1=6).

> Could you please document the algorithm in details (especially explaining the 
> background ideas), and share at least one use case, with with numbers for all 
> the input and output parameters ?

I'll try to improve the documentation in the next version. Summarizing
the idea is something I can do, but beyond that I don't see much to add
beyond prose.

Ahead of posting a V2, let me suggest this:

/* The first part of the algorithm reduces the given aptina_pll_limits
 * for n, m and p1 using the (in)equalities and the concrete values for
 * ext_clock and pix_clock in order to reduce the search space.
 *
 * The main loop iterates over all remaining possible p1 values and
 * computes the necessary out_clock frequency. The ext_clock / out_clock
 * ratio is then approximated with n / m within their respective bounds.
 * For each parameter choice, the preconditions must be rechecked,
 * because integer rounding errors may result in violating some of the
 * preconditions. The parameter set with the least frequency error is
 * returned.
 */

Is this what you are looking for?

Helmut


Re: [PATCH] media: aptina-pll: allow approximating the requested pix_clock

2018-08-24 Thread Helmut Grohne
Hi Sakari,

Thank you for taking the time to look into the issue.

On Thu, Aug 23, 2018 at 01:30:12PM +0200, Sakari Ailus wrote:
> Knowing the formula, the limits as well as the external clock frequency, it
> should be relatively straightforward to come up with a functional pixel
> clock value. Was there a practical problem in coming up with such a value?

I've added a concrete example to my other reply and should have done
that with posting the initial question. I'm sorry for not having done it
earlier.

> You can't pick a value at random; it needs to be one that actually works.
> The purpose of having an exact frequency is that the typical systems where
> these devices are being used, as I explained earlier, is that having a
> random frequency, albeit with which the sensor could possibly work, the
> other devices in the system may not do so.

We already refuted the concept of an "exact frequency". In nature, it
simply isn't exact. Every board will have a slightly different
frequency no matter how precise you calculate it.

I'm not after random frequencies in any case. The goal of course is to
approximate the requested frequency as good as possible. In particular,
when the requested pix_clock allows using a parameter set that attains
the frequency exactly, that parameter set will be emitted rather than
some other approximation. Only for parameters where the old algorithm
returns -EINVAL there should be an observable difference.

Using an exact frequency is difficult here. How am I supposed to write
e.g. 74242424.24242424... Hz into the device tree?

Helmut


[PATCH] media: aptina-pll: allow approximating the requested pix_clock

2018-08-23 Thread Helmut Grohne
Clock frequencies are not exact values, but rather imprecise, physical
properties. The present pll computation however, treats them as exact.
It tries to compute parameters that attain the requested pix_clock
exactly. Failing that, it gives up.

The new implementation approximates the requested pix_clock and reports
the actual value resulting from the computed parameters. If the
requested pix_clock can be attained, the original behaviour of
maximizing p1 is retained.

Experiments with the algorithm in userspace on an arm device show that
the computational cost is negligible compared to executing a binary for
all practical inputs.

Signed-off-by: Helmut Grohne 
---
 drivers/media/i2c/aptina-pll.c | 263 -
 drivers/media/i2c/mt9m032.c|  15 ++-
 2 files changed, 165 insertions(+), 113 deletions(-)

I tried using aptina_pll_calculate in a driver for a similar image sensor.
Using it, I was unable to find a pix_clock value such that the computation was
successful. Most of the practical parameters result in a non-integer pix_clock,
something that struct pll cannot represent.

The driver is not ready for submission at this point, but the changes to
aptina_pll_calculate are reasonable on their own, which is why I submit them
separately now.

Helmut

diff --git a/drivers/media/i2c/aptina-pll.c b/drivers/media/i2c/aptina-pll.c
index 224ae4e4cf8b..249018772b2b 100644
--- a/drivers/media/i2c/aptina-pll.c
+++ b/drivers/media/i2c/aptina-pll.c
@@ -2,6 +2,7 @@
  * Aptina Sensor PLL Configuration
  *
  * Copyright (C) 2012 Laurent Pinchart 
+ * Copyright (C) 2018 Intenta GmbH
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -14,23 +15,84 @@
  */
 
 #include 
-#include 
 #include 
-#include 
+#include 
 #include 
 
 #include "aptina-pll.h"
 
+/* A variant of mult_frac that works even when (x % denom) * numer produces a
+ * 32bit overflow.
+ */
+#define mult_frac_exact(x, numer, denom) \
+   ((u32)div_u64(mul_u32_u32((x), (numer)), (denom)))
+
+static unsigned int absdiff(unsigned int x, unsigned int y)
+{
+   return x > y ? x - y : y - x;
+}
+
+/* Find n_min <= *np <= n_max and d_min <= *dp <= d_max such that *np / *dp
+ * approximates n_target / d_target.
+ */
+static int approximate_fraction(unsigned int n_min, unsigned int n_max,
+   unsigned int d_min, unsigned int d_max,
+   unsigned int n_target, unsigned int d_target,
+   unsigned int *np, unsigned int *dp)
+{
+   unsigned int d, best_err = UINT_MAX;
+
+   d_min = max(d_min, mult_frac_exact(n_min, d_target, n_target));
+   d_max = min(d_max, mult_frac_exact(n_max, d_target, n_target) + 1);
+   if (d_min > d_max)
+   return -EINVAL;
+
+   for (d = d_min; d < d_max; ++d) {
+   unsigned int n = mult_frac_exact(d, n_target, d_target);
+
+   if (n >= n_min) {
+   unsigned int err = absdiff(
+   n_target, mult_frac_exact(n, d_target, d));
+
+   if (err < best_err) {
+   best_err = err;
+   *np = n;
+   *dp = d;
+   }
+   if (err == 0)
+   return 0;
+   }
+   ++n;
+   if (n <= n_max) {
+   unsigned int err = absdiff(
+   n_target, mult_frac_exact(n, d_target, d));
+
+   if (err < best_err) {
+   best_err = err;
+   *np = n;
+   *dp = d;
+   }
+   }
+   }
+   return best_err == UINT_MAX ? -EINVAL : 0;
+}
+
+/* Find parameters n, m, p1 such that:
+ *   n_min <= n <= n_max
+ *   m_min <= m <= m_max
+ *   p1_min <= p1 <= p1_max, even
+ *   int_clock_min <= ext_clock / n <= int_clock_max
+ *   out_clock_min <= ext_clock / n * m <= out_clock_max
+ *   pix_clock = ext_clock / n * m / p1 (approximately)
+ *   p1 is maximized
+ * Report the achieved pix_clock (input/output parameter).
+ */
 int aptina_pll_calculate(struct device *dev,
 const struct aptina_pll_limits *limits,
 struct aptina_pll *pll)
 {
-   unsigned int mf_min;
-   unsigned int mf_max;
-   unsigned int p1_min;
-   unsigned int p1_max;
-   unsigned int p1;
-   unsigned int div;
+   unsigned int n_min, n_max, m_min, m_max, p1_min, p1_max, p1;
+   unsigned int clock_err = UINT_MAX;
 
dev_dbg(dev, "PLL: ext clock %u pix clock %u\n",
pll->ext_clock, pll->pix_clock);
@@ -46,120 +108,103 @@ int aptina_pll_cal

V4L2 analogue gain contol

2018-08-22 Thread Helmut Grohne
Hi,

I've been looking at various image sensor drivers to see how they expose
gains, in particular analogue ones. What I found in 4.18 looks like a
mess to me.

In particular, my interest is about separation of analogue vs digital
gain and an understanding of what effect a change in gain has on the
brightness of an image. The latter is characterized in the following
table in the "linear" column.

driver  | CID | register name   | min | max  | def | linear | 
comments
+-+-+-+--+-++-
adv7343 | G   | ADV7343_DAC2_OUTPUT_LEVEL   | -64 | 64   | 0   ||
adv7393 | G   | ADV7393_DAC123_OUTPUT_LEVEL | -64 | 64   | 0   ||
imx258  | A   | IMX258_REG_ANALOG_GAIN  | 0   | 8191 | 0   ||
imx274  | G   | multiple| |  | | yes| [1]
mt9m032 | G   | MT9M032_GAIN_ALL| 0   | 127  | 64  | no | [2]
mt9m111 | G   | GLOBAL_GAIN | 0   | 252  | 32  | no | [3]
mt9p031 | G   | MT9P031_GLOBAL_GAIN | 8   | 1024 | 8   | no | [4]
mt9v011 | G   | multiple| 0   | 4063 | 32  ||
mt9v032 | G   | MT9V032_ANALOG_GAIN | 16  | 64   | 16  | no | [5]
ov13858 | A   | OV13858_REG_ANALOG_GAIN | 0   | 8191 | 128 ||
ov2685  | A   | OV2685_REG_GAIN | 0   | 2047 | 54  ||
ov5640  | G   | OV5640_REG_AEC_PK_REAL_GAIN | 0   | 1023 | 0   ||
ov5670  | A   | OV5670_REG_ANALOG_GAIN  | 0   | 8191 | 128 ||
ov5695  | A   | OV5695_REG_ANALOG_GAIN  | 16  | 248  | 248 ||
mt9m001 | G   | MT9M001_GLOBAL_GAIN | 0   | 127  | 64  | no |
mt9v022 | G   | MT9V022_ANALOG_GAIN | 0   | 127  | 64  ||

CID:
  A -> V4L2_CID_ANALOGUE_GAIN
  G -> V4L2_CID_GAIN, no V4L2_CID_ANALOGUE_GAIN present
step: always 1
comments:
[1] controls a product of analogue and digital gain, value scales
roughly linear
[2] code comments contradict data sheet
[3] it is not clear whether it also controls a digital gain.
[4] controls a combination of analogue and digital gain
[5] analogue only

The documentation (extended-controls.rst) says that the digital gain is
supposed to be a linear fixed-point number with 0x100 meaning factor 1.
The situation for analogue is much less precise.

Typically, the number of analogue gains is much smaller than the number
of digital gains. No driver exposes more than 13 bit for the analogue
gain and half of them use at most 8 bits.

Can we give more structure to the analogue gain as exposed by V4L2?
Ideally, I'd like to query a driver for the possible gain values if
there are few (say < 256) and their factors (which are often given in
data sheets). The nature of gains though is that they are often similar
to floating point numbers (2 ** exp * (1 + mant / precision)), which
makes it difficult to represent them using min/max/step/default.

Would it be reasonable to add a new V4L2_CID_ANALOGUE_GAIN_MENU that
claims linearity and uses fixed-point numbers like
V4L2_CID_DIGITAL_GAIN? There already is the integer menu
V4L2_CID_AUTO_EXPOSURE_BIAS, but it also affects the exposure.

An important application is implementing a custom gain control when the
built-in auto exposure is not applicable.

Helmut


Re: why does aptina_pll_calculate insist on exact division?

2018-08-14 Thread Helmut Grohne
Hi,

Thank you for the quick and helpful answer.

On Tue, Aug 14, 2018 at 09:30:14AM +0200, Laurent Pinchart wrote:
> How do you mean ? The only place where pix_clock_max is used is in the 
> following code:
> 
> if (pll->pix_clock == 0 || pll->pix_clock > limits->pix_clock_max) {
> dev_err(dev, "pll: invalid pixel clock frequency.\n");
> return -EINVAL;
> }
> 
> aptina_pll_calculate() rejects a request pixel clock value higher than the 
> pixel clock frequency higher limit, which is also given by the caller. That 
> shouldn't happen, it would be a bug in the caller.

Of course, I am trying values lower than pix_clock_max. For a number of
imagers, that pix_clock_max is 74.25 MHz. It seems that any pix_clock of
at least 72 MHz is rejected here.

> I'm not sure what you mean by avoiding fractional numbers. Could you please 
> elaborate ? Please keep in mind that I last touched the code 6 years, so my 
> memory isn't exactly fresh.

The first thing the code does is computing the gcd of pix_clock and
ext_clock. Immediately, it conludes that m must be a multiple of
pix_clock / gcd(pix_clock, ext_clock). Varying either clock value
slightly causes large jumps in the computed gcd value (in particular, it
will be 1 whenever either clock happens to be a prime number).

> If you mean using floating point operations to calculate PLL parameters, 
> remember that the code runs in the Linux kernel, where floating point isn't 
> allowed. You would thus have to implement the algorithm using fixed-point 
> calculation.

I'm not after using floating points. In a sense, we are already
fixed-point calculation and the precision is 1 Hz. Rounding errors in
that range look ok to me.

> There's no such thing as an exact frequency anyway, as it's a physical value. 
> I'd got for 50 MHz for simplicity.

That's exactly my point. The exact value should not matter. However, for
the present aptina_pll_calculate, the exact value matters a lot. Were
you to use 4991 Hz as ext_clock (which happens to be prime, but
reasonably close), aptina_pll_calculate fails entirely as m is deemed to
be a multiple of the pix_clock in Hz. No imager allows for such large m
values and thus aptina_pll_calculate rejects any such configuration with
-EINVAL.

I'm arguing that rather than failing to compute pll parameters, it
should compromise on exactness. Presently, aptina_pll_calculate ensures
that whenever it is successful, the assertion pix_clock = ext_clock / n
* m / p1 holds exactly and all intermediate values are whole numbers.
I'm arguing that having it hold exactly reduces utility of
aptina_pll_calculate, because frequencies are not exact in the real
world. There is no need to have whole numbered frequencies.

> aptina_pll_calculate() also approximates the requested frequency, but as it 
> appears from your test, fails in some cases. That's certainly an issue in the 
> code and should be fixed. Feel free to convince the manufacturer to release 
> their PLL parameters computation code under the GPL ;-)

We both know that the exercise of extracting code from manufacturers is
futile.

However you appear to imply that aptina_pll_calculate should approximate
the requested frequency. That's not what it does today. That's a useful
answer to me already and I'll be looking into doing the work of coming
up with an alternative lifting the requirement.

> Again, please elaborate on what you mean by avoiding fractional numbers. I 
> would certainly be open to a different algorithm (or possibly fixes to the 
> existing code), as long as it fulfills the requirements behind the current 
> implementation. In particular the code should compute the optimum PLL 
> parameters when multiple options are possible, and its complexity should be 
> lower than O(n^2) (ideally O(1), if not possible O(n)).

Beware though that discussing complexities requires more precision as to
what "n" means here. The code interprets it as n = p1_max - p1_min (not
accounting for the gcd computation), which is not the usual
interpretation. What you really want is that it completes in a
reasonable amount of time on slow, embedded devices for any input.

Once you lift the exactness requirement, you optimize multiple aspects
simultaneously. The present code maximizes P1, but we also want to
minimize the difference between the requested pix_clock and the
resulting pix_clock. There has to be some kind of trade-off here. The
trade-off chosen by the present code is to always have that difference
be 0. Once non-zero differences are allowed, optimum is no longer
well-defined.

So could you go into more detail as to what "optimum PLL parameters"
mean to you?

Helmut


why does aptina_pll_calculate insist on exact division?

2018-08-14 Thread Helmut Grohne
Hi,

I tried using the aptina_pll_calculate for a "new" imager and ran into
problems. After filling out aptina_pll_limits from the data sheet, I was
having a hard time finding a valid pix_clock. Most of the ones I tried
are rejected by aptina_pll_calculate for various reasons. In particular,
no pix_clock close to pix_clock_max is allowed.

Why does the calculation method insist on exact division and avoiding
fractional numbers?

I'm using an ext_clock of 50 MHz. This clock is derived from a 33 MHz
clock and the 50 MHz is not attained exactly. Rather it ends up being
more like 49.76 Hz. This raises the question, what value I should
put into ext_clock (or the corresponding device tree property). Should I
use the requested frequency or the actual frequency? Worse, depending on
the precise value of the ext_clock, aptina_pll_calculate may or may not
be able to compute pll parameters.

On the other hand, the manufacturer provided configuration tool happily
computes pll parameters that result in close, but not exactly, the
requested pix_clock. In particular, the pll parameters do not
necessarily result in a whole number. It appears to merely approximate
the requested frequency.

Can you explain where the requirement to avoid fractional numbers comes
from? Would it be reasonable to use a different algorithm that avoids
this requirement?

Helmut


V4L2_CID_USER_MAX217X_BASE == V4L2_CID_USER_IMX_BASE

2018-06-22 Thread Helmut Grohne
Hi,

I found it strange that the macros V4L2_CID_USER_MAX217X_BASE and
V4L2_CID_USER_IMX_BASE have equal value even though each of them state
that they reserved a range. Those reservations look conflicting to me.

The macro V4L2_CID_USER_MAX217X_BASE came first, and
V4L2_CID_USER_IMX_BASE was introduced in e130291212df ("media: Add i.MX
media core driver") with the conflicting assignment (not a merge error).
The authors of that patch mostly make up the recipient list.

Is such a conflict fixable at all given that it resides in a uapi
header?

Helmut