RE: [PATCH v3 1/1] [media] i2c: add support for OV13858 sensor

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Tomasz,

Here's my comments.

Thanks,
Hyungwoo
 
-----Original Message-----
> From: Tomasz Figa [mailto:tfiga@xxxxxxxxxxxx] 
> Sent: Sunday, May 28, 2017 7:56 PM
> To: Yang, Hyungwoo <hyungwoo.yang@xxxxxxxxx>
> Cc: Sakari Ailus <sakari.ailus@xxxxxx>; linux-media@xxxxxxxxxxxxxxx; sakari.ailus@xxxxxxxxxxxxxxx; Zheng, Jian Xu <jian.xu.zheng@xxxxxxxxx>; Hsu, Cedric <cedric.hsu@xxxxxxxxx>
> Subject: Re: [PATCH v3 1/1] [media] i2c: add support for OV13858 sensor
> 
> Hi Hyungwoo,
> 
> On Mon, May 29, 2017 at 8:26 AM, Yang, Hyungwoo <hyungwoo.yang@xxxxxxxxx> wrote:
> >
> > Hi Sakari,
> >
> > Here's my comments.
> >
> > -Hyungwoo
> >
> >
> > -----Original Message-----
> >> From: Sakari Ailus [mailto:sakari.ailus@xxxxxx]
> >> Sent: Saturday, May 27, 2017 1:31 PM
> >> To: Yang, Hyungwoo <hyungwoo.yang@xxxxxxxxx>
> >> Cc: linux-media@xxxxxxxxxxxxxxx; sakari.ailus@xxxxxxxxxxxxxxx; Zheng, 
> >> Jian Xu <jian.xu.zheng@xxxxxxxxx>; Hsu, Cedric 
> >> <cedric.hsu@xxxxxxxxx>; tfiga@xxxxxxxxxxxx
> >> Subject: Re: [PATCH v3 1/1] [media] i2c: add support for OV13858 
> >> sensor
> >>
> >> Hi Hyungwoo,
> >>
> >> Thanks for the update. A few comments below.
> >>
> [snip]
> >> > +/* Update VTS that meets expected vertical blanking */ static int 
> >> > +ov13858_update_vblank(struct ov13858 *ov13858,
> >> > +                            struct v4l2_ctrl *ctrl) {
> >> > +   return ov13858_write_reg(
> >> > +                   ov13858, OV13858_REG_VTS,
> >> > +                   OV13858_REG_VALUE_16BIT,
> >> > +                   ov13858->cur_mode->height + 
> >> > +ov13858->vblank->val); }
> >> > +
> >> > +/* Update analog gain */
> >> > +static int ov13858_update_analog_gain(struct ov13858 *ov13858,
> >> > +                                 struct v4l2_ctrl *ctrl) {
> >> > +   return ov13858_write_reg(ov13858, OV13858_REG_ANALOG_GAIN,
> >> > +                            OV13858_REG_VALUE_16BIT, ctrl->val);
> >>
> >> I think I'd move what the four above functions do to ov13858_set_ctrl() unless they're used in more than one location.
> >
> > Why ? Personally I like this. Since there  wouldn't be any difference in generated machine code, I want to keep this if there's no strict rule on this.
> 
> Personally I wouldn't probably care about this, but I see one advantage of Sakari's suggestion.
> 
> Namely, it improves code readability, because there is less indirection and the person reading ov13858_set_ctrl() instantly knows that all it does is directly writing the control value to hardware registers. Otherwise, with the indirection in current version, until you read ov13858_update_analog_gain() (or such), you don't know whether it does some extra processing, power management or whatnot.
> 
> If ov13858_update_analog_gain() did more than just a simple register write, it would indeed make sense to separate it, as it's intuitive that a separate function means some more complicated work. (And vice versa, it's counter-intuitive to have a function that is only there to call a register accessor.)
> 

This is my habit for people who doesn't have datasheet for h/w or people who doesn't need(want) to know about detail. Yeah, my habit is especially for those h/w which have many bit-fields in a register and I believe this kind of separation helps these people. I know the registers in this sensor is very much straightforward.

> >
> >>
> >> > +}
> >> > +
> >> > +static int ov13858_set_ctrl(struct v4l2_ctrl *ctrl) {
> >> > +   struct ov13858 *ov13858 = container_of(ctrl->handler,
> >> > +                                          struct ov13858, ctrl_handler);
> >> > +   struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
> >> > +   int ret;
> >> > +
> >> > +   /* Propagate change of current control to all related controls */
> >> > +   switch (ctrl->id) {
> >> > +   case V4L2_CID_VBLANK:
> >> > +           ov13858_update_exposure_limits(ov13858);
> >> > +           break;
> >> > +   };
> >> > +
> >> > +   /*
> >> > +    * Applying V4L2 control value only happens
> >> > +    * when power is up for streaming
> >> > +    */
> >> > +   if (pm_runtime_get_if_in_use(&client->dev) <= 0)
> >> > +           return 0;
> >> > +
> >> > +   ret = 0;
> >> > +   switch (ctrl->id) {
> >> > +   case V4L2_CID_ANALOGUE_GAIN:
> >> > +           ret = ov13858_update_analog_gain(ov13858, ctrl);
> >> > +           break;
> >> > +   case V4L2_CID_EXPOSURE:
> >> > +           ret = ov13858_update_exposure(ov13858, ctrl);
> >> > +           break;
> >> > +   case V4L2_CID_VBLANK:
> >> > +           ret = ov13858_update_vblank(ov13858, ctrl);
> >> > +           break;
> >> > +   default:
> >> > +           dev_info(&client->dev,
> >> > +                    "ctrl(id:0x%x,val:0x%x) is not handled\n",
> >> > +                    ctrl->id, ctrl->val);
> >> > +           break;
> >> > +   };
> >> > +
> >> > +   pm_runtime_put(&client->dev);
> >> > +
> >> > +   return ret;
> >> > +}
> >> > +
> >                 :
> >                 :
> >> > +/*
> >> > + * Prepare streaming by writing default values and customized values.
> >> > + * This should be called with ov13858->mutex acquired.
> >> > + */
> >> > +static int ov13858_prepare_streaming(struct ov13858 *ov13858) {
> >> > +   struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
> >> > +   const struct ov13858_reg_list *reg_list;
> >> > +   int ret, link_freq_index;
> >> > +
> >> > +   /* Get out of from software reset */
> >> > +   ret = ov13858_write_reg(ov13858, OV13858_REG_SOFTWARE_RST,
> >> > +                           OV13858_REG_VALUE_08BIT, OV13858_SOFTWARE_RST);
> >> > +   if (ret) {
> >> > +           dev_err(&client->dev, "%s failed to set powerup registers\n",
> >> > +                   __func__);
> >> > +           return ret;
> >> > +   }
> >> > +
> >> > +   /* Setup PLL */
> >> > +   link_freq_index = ov13858->cur_mode->link_freq_index;
> >> > +   reg_list = &link_freq_configs[link_freq_index].reg_list;
> >> > +   ret = ov13858_write_reg_list(ov13858, reg_list);
> >> > +   if (ret) {
> >> > +           dev_err(&client->dev, "%s failed to set plls\n", __func__);
> >> > +           return ret;
> >> > +   }
> >> > +
> >> > +   /* Apply default values of current mode */
> >> > +   reg_list = &ov13858->cur_mode->reg_list;
> >> > +   ret = ov13858_write_reg_list(ov13858, reg_list);
> >> > +   if (ret) {
> >> > +           dev_err(&client->dev, "%s failed to set mode\n", __func__);
> >> > +           return ret;
> >> > +   }
> >> > +
> >> > +   /* Apply customized values from user */
> >> > +   return __v4l2_ctrl_handler_setup(ov13858->sd.ctrl_handler);
> >> > +}
> >> > +
> >> > +/* Start streaming */
> >> > +static int ov13858_start_streaming(struct ov13858 *ov13858) {
> >> > +   int ret;
> >> > +
> >> > +   /* Write default & customized values */
> >> > +   ret = ov13858_prepare_streaming(ov13858);
> >>
> >> Could you merge this with ov13858_prepare_streaming()?
> >>
> >
> > Why ? I want to keep this. If you want to worry about 1 more jump then, if it is really there, I can make this function "inline"
> 
> I doubt it's about the number of jumps. The same argument of code readability as I mentioned above applies here as well. I see no point in having ov13858_start_streaming() separate if all it does on top of
> ov13858_prepare_streaming() is a register write, it is counter-intuitive for readers of the code.

Here, it's the same. I believe this kind of code very much readable for people who doesn't have much experiences(or dummies like me) and who just wants to know control flow(not detail about h/w).

> 
> Best regards,
> Tomasz




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux