[PATCHv2 5/5] adv7842: enable reduced fps detection

2018-08-15 Thread Hans Verkuil
From: Hans Verkuil 

The pixelclock detection of the adv7842 is precise enough to detect
if the framerate is 60 Hz or 59.94 Hz (aka "reduced fps").

Implement this detection.

Signed-off-by: Hans Verkuil 
---
 drivers/media/i2c/adv7842.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 4f8fbdd00e35..999d621f5667 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -1525,6 +1525,7 @@ static void 
adv7842_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
v4l2_find_dv_timings_cap(timings, adv7842_get_dv_timings_cap(sd),
is_digital_input(sd) ? 25 : 100,
adv7842_check_dv_timings, NULL);
+   timings->bt.flags |= V4L2_DV_FL_CAN_DETECT_REDUCED_FPS;
 }
 
 static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
@@ -1596,6 +1597,14 @@ static int adv7842_query_dv_timings(struct v4l2_subdev 
*sd,
bt->il_vbackporch = 0;
}
adv7842_fill_optional_dv_timings_fields(sd, timings);
+   if ((timings->bt.flags & V4L2_DV_FL_CAN_REDUCE_FPS) &&
+   freq < bt->pixelclock) {
+   u32 reduced_freq = (bt->pixelclock / 1001) * 1000;
+   u32 delta_freq = abs(freq - reduced_freq);
+
+   if (delta_freq < (bt->pixelclock - reduced_freq) / 2)
+   timings->bt.flags |= V4L2_DV_FL_REDUCED_FPS;
+   }
} else {
/* find format
 * Since LCVS values are inaccurate [REF_03, p. 339-340],
-- 
2.18.0



Re: [PATCHv2 5/5] adv7842: enable reduced fps detection

2018-08-15 Thread kbuild test robot
Hi Hans,

I love your patch! Yet something to improve:

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.18 next-20180815]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Hans-Verkuil/Handling-of-reduced-FPS-in-V4L2/20180816-051924
base:   git://linuxtv.org/media_tree.git master
config: i386-randconfig-a0-201832 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/media/i2c/adv7842.o: In function `adv7842_query_dv_timings':
>> drivers/media/i2c/adv7842.c:1602: undefined reference to `__udivdi3'

vim +1602 drivers/media/i2c/adv7842.c

  1530  
  1531  static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
  1532  struct v4l2_dv_timings *timings)
  1533  {
  1534  struct adv7842_state *state = to_state(sd);
  1535  struct v4l2_bt_timings *bt = &timings->bt;
  1536  struct stdi_readback stdi = { 0 };
  1537  
  1538  v4l2_dbg(1, debug, sd, "%s:\n", __func__);
  1539  
  1540  memset(timings, 0, sizeof(struct v4l2_dv_timings));
  1541  
  1542  /* SDP block */
  1543  if (state->mode == ADV7842_MODE_SDP)
  1544  return -ENODATA;
  1545  
  1546  /* read STDI */
  1547  if (read_stdi(sd, &stdi)) {
  1548  state->restart_stdi_once = true;
  1549  v4l2_dbg(1, debug, sd, "%s: no valid signal\n", 
__func__);
  1550  return -ENOLINK;
  1551  }
  1552  bt->interlaced = stdi.interlaced ?
  1553  V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
  1554  bt->standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
  1555  V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT;
  1556  
  1557  if (is_digital_input(sd)) {
  1558  u32 freq;
  1559  
  1560  timings->type = V4L2_DV_BT_656_1120;
  1561  
  1562  bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + 
hdmi_read(sd, 0x08);
  1563  bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + 
hdmi_read(sd, 0x0a);
  1564  freq = ((hdmi_read(sd, 0x51) << 1) + (hdmi_read(sd, 
0x52) >> 7)) * 100;
  1565  freq += ((hdmi_read(sd, 0x52) & 0x7f) * 7813);
  1566  if (is_hdmi(sd)) {
  1567  /* adjust for deep color mode */
  1568  freq = freq * 8 / (((hdmi_read(sd, 0x0b) & 
0xc0) >> 6) * 2 + 8);
  1569  }
  1570  bt->pixelclock = freq;
  1571  bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 +
  1572  hdmi_read(sd, 0x21);
  1573  bt->hsync = (hdmi_read(sd, 0x22) & 0x03) * 256 +
  1574  hdmi_read(sd, 0x23);
  1575  bt->hbackporch = (hdmi_read(sd, 0x24) & 0x03) * 256 +
  1576  hdmi_read(sd, 0x25);
  1577  bt->vfrontporch = ((hdmi_read(sd, 0x2a) & 0x1f) * 256 +
  1578  hdmi_read(sd, 0x2b)) / 2;
  1579  bt->vsync = ((hdmi_read(sd, 0x2e) & 0x1f) * 256 +
  1580  hdmi_read(sd, 0x2f)) / 2;
  1581  bt->vbackporch = ((hdmi_read(sd, 0x32) & 0x1f) * 256 +
  1582  hdmi_read(sd, 0x33)) / 2;
  1583  bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? 
V4L2_DV_VSYNC_POS_POL : 0) |
  1584  ((hdmi_read(sd, 0x05) & 0x20) ? 
V4L2_DV_HSYNC_POS_POL : 0);
  1585  if (bt->interlaced == V4L2_DV_INTERLACED) {
  1586  bt->height += (hdmi_read(sd, 0x0b) & 0x0f) * 
256 +
  1587  hdmi_read(sd, 0x0c);
  1588  bt->il_vfrontporch = ((hdmi_read(sd, 0x2c) & 
0x1f) * 256 +
  1589  hdmi_read(sd, 0x2d)) / 2;
  1590  bt->il_vsync = ((hdmi_read(sd, 0x30) & 0x1f) * 
256 +
  1591  hdmi_read(sd, 0x31)) / 2;
  1592  bt->il_vbackporch = ((hdmi_read(sd, 0x34) & 
0x1f) * 256 +
  1593  hdmi_read(sd, 0x35)) / 2;
  1594  } else {
  1595  bt->il_vfrontporch = 0;
  1596  bt->il_vsync = 0;
  1597  bt->il_vbackporch = 0;
  1598  }
  1599  adv7842_fill_optional_dv_timings_fields(sd, timings);
  1600  if ((timings->bt.flags & V4L2_DV_FL_CAN_REDUCE_FPS) &&
  1601  freq < bt->pixelclock) {
> 1602  u32 reduced_freq = (bt->pixelclock /

Re: [PATCHv2 5/5] adv7842: enable reduced fps detection

2018-08-16 Thread Hans Verkuil
On 15/08/18 15:40, Hans Verkuil wrote:
> From: Hans Verkuil 
> 
> The pixelclock detection of the adv7842 is precise enough to detect
> if the framerate is 60 Hz or 59.94 Hz (aka "reduced fps").
> 
> Implement this detection.
> 
> Signed-off-by: Hans Verkuil 
> ---
>  drivers/media/i2c/adv7842.c | 9 +
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
> index 4f8fbdd00e35..999d621f5667 100644
> --- a/drivers/media/i2c/adv7842.c
> +++ b/drivers/media/i2c/adv7842.c
> @@ -1525,6 +1525,7 @@ static void 
> adv7842_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
>   v4l2_find_dv_timings_cap(timings, adv7842_get_dv_timings_cap(sd),
>   is_digital_input(sd) ? 25 : 100,
>   adv7842_check_dv_timings, NULL);
> + timings->bt.flags |= V4L2_DV_FL_CAN_DETECT_REDUCED_FPS;
>  }
>  
>  static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
> @@ -1596,6 +1597,14 @@ static int adv7842_query_dv_timings(struct v4l2_subdev 
> *sd,
>   bt->il_vbackporch = 0;
>   }
>   adv7842_fill_optional_dv_timings_fields(sd, timings);
> + if ((timings->bt.flags & V4L2_DV_FL_CAN_REDUCE_FPS) &&
> + freq < bt->pixelclock) {
> + u32 reduced_freq = (bt->pixelclock / 1001) * 1000;

bt->pixelclock needs to be cast to u32 to avoid a 64 bit division.

> + u32 delta_freq = abs(freq - reduced_freq);
> +
> + if (delta_freq < (bt->pixelclock - reduced_freq) / 2)

Ditto.

(kbuild robot complained about this.)

Hans

> + timings->bt.flags |= V4L2_DV_FL_REDUCED_FPS;
> + }
>   } else {
>   /* find format
>* Since LCVS values are inaccurate [REF_03, p. 339-340],
>