Re: [PATCH v4 32/36] media: imx: csi/fim: add support for frame intervals

2017-02-15 Thread Steve Longerbeam

Sorry, I forgot to change authorship on this patch. It should
be authored by Russell King .

Steve

On 02/15/2017 06:19 PM, Steve Longerbeam wrote:

Add support to CSI for negotiation of frame intervals, and use this
information to configure the frame interval monitor.

Signed-off-by: Russell King 
Signed-off-by: Steve Longerbeam 
---
  drivers/staging/media/imx/imx-media-csi.c | 36 ---
  drivers/staging/media/imx/imx-media-fim.c | 28 +---
  drivers/staging/media/imx/imx-media.h |  2 +-
  3 files changed, 44 insertions(+), 22 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index b0aac82..040cca6 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -56,6 +56,7 @@ struct csi_priv {
  
  	struct v4l2_mbus_framefmt format_mbus[CSI_NUM_PADS];

const struct imx_media_pixfmt *cc[CSI_NUM_PADS];
+   struct v4l2_fract frame_interval;
struct v4l2_rect crop;
  
  	/* the video device at IDMAC output pad */

@@ -565,7 +566,8 @@ static int csi_start(struct csi_priv *priv)
  
  	/* start the frame interval monitor */

if (priv->fim) {
-   ret = imx_media_fim_set_stream(priv->fim, priv->sensor, true);
+   ret = imx_media_fim_set_stream(priv->fim,
+  >frame_interval, true);
if (ret)
goto idmac_stop;
}
@@ -580,7 +582,8 @@ static int csi_start(struct csi_priv *priv)
  
  fim_off:

if (priv->fim)
-   imx_media_fim_set_stream(priv->fim, priv->sensor, false);
+   imx_media_fim_set_stream(priv->fim,
+>frame_interval, false);
  idmac_stop:
if (priv->dest == IPU_CSI_DEST_IDMAC)
csi_idmac_stop(priv);
@@ -594,11 +597,36 @@ static void csi_stop(struct csi_priv *priv)
  
  	/* stop the frame interval monitor */

if (priv->fim)
-   imx_media_fim_set_stream(priv->fim, priv->sensor, false);
+   imx_media_fim_set_stream(priv->fim,
+>frame_interval, false);
  
  	ipu_csi_disable(priv->csi);

  }
  
+static int csi_g_frame_interval(struct v4l2_subdev *sd,

+   struct v4l2_subdev_frame_interval *fi)
+{
+   struct csi_priv *priv = v4l2_get_subdevdata(sd);
+
+   fi->interval = priv->frame_interval;
+
+   return 0;
+}
+
+static int csi_s_frame_interval(struct v4l2_subdev *sd,
+   struct v4l2_subdev_frame_interval *fi)
+{
+   struct csi_priv *priv = v4l2_get_subdevdata(sd);
+
+   /* Output pads mirror active input pad, no limits on input pads */
+   if (fi->pad == CSI_SRC_PAD_IDMAC || fi->pad == CSI_SRC_PAD_DIRECT)
+   fi->interval = priv->frame_interval;
+
+   priv->frame_interval = fi->interval;
+
+   return 0;
+}
+
  static int csi_s_stream(struct v4l2_subdev *sd, int enable)
  {
struct csi_priv *priv = v4l2_get_subdevdata(sd);
@@ -1187,6 +1215,8 @@ static struct v4l2_subdev_core_ops csi_core_ops = {
  };
  
  static struct v4l2_subdev_video_ops csi_video_ops = {

+   .g_frame_interval = csi_g_frame_interval,
+   .s_frame_interval = csi_s_frame_interval,
.s_stream = csi_s_stream,
  };
  
diff --git a/drivers/staging/media/imx/imx-media-fim.c b/drivers/staging/media/imx/imx-media-fim.c

index acc7e39..a6ed57e 100644
--- a/drivers/staging/media/imx/imx-media-fim.c
+++ b/drivers/staging/media/imx/imx-media-fim.c
@@ -67,26 +67,18 @@ struct imx_media_fim {
  };
  
  static void update_fim_nominal(struct imx_media_fim *fim,

-  struct imx_media_subdev *sensor)
+  const struct v4l2_fract *fi)
  {
-   struct v4l2_streamparm parm;
-   struct v4l2_fract tpf;
-   int ret;
-
-   parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-   ret = v4l2_subdev_call(sensor->sd, video, g_parm, );
-   tpf = parm.parm.capture.timeperframe;
-
-   if (ret || tpf.denominator == 0) {
-   dev_dbg(fim->sd->dev, "no tpf from sensor, FIM disabled\n");
+   if (fi->denominator == 0) {
+   dev_dbg(fim->sd->dev, "no frame interval, FIM disabled\n");
fim->enabled = false;
return;
}
  
-	fim->nominal = DIV_ROUND_CLOSEST(1000 * 1000 * tpf.numerator,

-tpf.denominator);
+   fim->nominal = DIV_ROUND_CLOSEST_ULL(100ULL * (u64)fi->numerator,
+fi->denominator);
  
-	dev_dbg(fim->sd->dev, "sensor FI=%lu usec\n", fim->nominal);

+   dev_dbg(fim->sd->dev, "FI=%lu usec\n", fim->nominal);
  }
  
  static void reset_fim(struct imx_media_fim *fim, bool curval)

@@ -130,8 +122,8 @@ 

[PATCH v4 32/36] media: imx: csi/fim: add support for frame intervals

2017-02-15 Thread Steve Longerbeam
Add support to CSI for negotiation of frame intervals, and use this
information to configure the frame interval monitor.

Signed-off-by: Russell King 
Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c | 36 ---
 drivers/staging/media/imx/imx-media-fim.c | 28 +---
 drivers/staging/media/imx/imx-media.h |  2 +-
 3 files changed, 44 insertions(+), 22 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index b0aac82..040cca6 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -56,6 +56,7 @@ struct csi_priv {
 
struct v4l2_mbus_framefmt format_mbus[CSI_NUM_PADS];
const struct imx_media_pixfmt *cc[CSI_NUM_PADS];
+   struct v4l2_fract frame_interval;
struct v4l2_rect crop;
 
/* the video device at IDMAC output pad */
@@ -565,7 +566,8 @@ static int csi_start(struct csi_priv *priv)
 
/* start the frame interval monitor */
if (priv->fim) {
-   ret = imx_media_fim_set_stream(priv->fim, priv->sensor, true);
+   ret = imx_media_fim_set_stream(priv->fim,
+  >frame_interval, true);
if (ret)
goto idmac_stop;
}
@@ -580,7 +582,8 @@ static int csi_start(struct csi_priv *priv)
 
 fim_off:
if (priv->fim)
-   imx_media_fim_set_stream(priv->fim, priv->sensor, false);
+   imx_media_fim_set_stream(priv->fim,
+>frame_interval, false);
 idmac_stop:
if (priv->dest == IPU_CSI_DEST_IDMAC)
csi_idmac_stop(priv);
@@ -594,11 +597,36 @@ static void csi_stop(struct csi_priv *priv)
 
/* stop the frame interval monitor */
if (priv->fim)
-   imx_media_fim_set_stream(priv->fim, priv->sensor, false);
+   imx_media_fim_set_stream(priv->fim,
+>frame_interval, false);
 
ipu_csi_disable(priv->csi);
 }
 
+static int csi_g_frame_interval(struct v4l2_subdev *sd,
+   struct v4l2_subdev_frame_interval *fi)
+{
+   struct csi_priv *priv = v4l2_get_subdevdata(sd);
+
+   fi->interval = priv->frame_interval;
+
+   return 0;
+}
+
+static int csi_s_frame_interval(struct v4l2_subdev *sd,
+   struct v4l2_subdev_frame_interval *fi)
+{
+   struct csi_priv *priv = v4l2_get_subdevdata(sd);
+
+   /* Output pads mirror active input pad, no limits on input pads */
+   if (fi->pad == CSI_SRC_PAD_IDMAC || fi->pad == CSI_SRC_PAD_DIRECT)
+   fi->interval = priv->frame_interval;
+
+   priv->frame_interval = fi->interval;
+
+   return 0;
+}
+
 static int csi_s_stream(struct v4l2_subdev *sd, int enable)
 {
struct csi_priv *priv = v4l2_get_subdevdata(sd);
@@ -1187,6 +1215,8 @@ static struct v4l2_subdev_core_ops csi_core_ops = {
 };
 
 static struct v4l2_subdev_video_ops csi_video_ops = {
+   .g_frame_interval = csi_g_frame_interval,
+   .s_frame_interval = csi_s_frame_interval,
.s_stream = csi_s_stream,
 };
 
diff --git a/drivers/staging/media/imx/imx-media-fim.c 
b/drivers/staging/media/imx/imx-media-fim.c
index acc7e39..a6ed57e 100644
--- a/drivers/staging/media/imx/imx-media-fim.c
+++ b/drivers/staging/media/imx/imx-media-fim.c
@@ -67,26 +67,18 @@ struct imx_media_fim {
 };
 
 static void update_fim_nominal(struct imx_media_fim *fim,
-  struct imx_media_subdev *sensor)
+  const struct v4l2_fract *fi)
 {
-   struct v4l2_streamparm parm;
-   struct v4l2_fract tpf;
-   int ret;
-
-   parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-   ret = v4l2_subdev_call(sensor->sd, video, g_parm, );
-   tpf = parm.parm.capture.timeperframe;
-
-   if (ret || tpf.denominator == 0) {
-   dev_dbg(fim->sd->dev, "no tpf from sensor, FIM disabled\n");
+   if (fi->denominator == 0) {
+   dev_dbg(fim->sd->dev, "no frame interval, FIM disabled\n");
fim->enabled = false;
return;
}
 
-   fim->nominal = DIV_ROUND_CLOSEST(1000 * 1000 * tpf.numerator,
-tpf.denominator);
+   fim->nominal = DIV_ROUND_CLOSEST_ULL(100ULL * (u64)fi->numerator,
+fi->denominator);
 
-   dev_dbg(fim->sd->dev, "sensor FI=%lu usec\n", fim->nominal);
+   dev_dbg(fim->sd->dev, "FI=%lu usec\n", fim->nominal);
 }
 
 static void reset_fim(struct imx_media_fim *fim, bool curval)
@@ -130,8 +122,8 @@ static void send_fim_event(struct imx_media_fim *fim, 
unsigned long error)
 
 /*
  * Monitor an averaged frame interval. If the average deviates too much
- * from the sensor's