lkml.org 
[lkml]   [2017]   [Mar]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v6 30/39] media: imx: csi/fim: add support for frame intervals
    Date
    From: Russell King <rmk+kernel@armlinux.org.uk>

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

    Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
    Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
    ---
    drivers/staging/media/imx/imx-media-csi.c | 46 +++++++++++++++++++++++++++++--
    drivers/staging/media/imx/imx-media-fim.c | 28 +++++++------------
    drivers/staging/media/imx/imx-media.h | 2 +-
    3 files changed, 54 insertions(+), 22 deletions(-)

    diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
    index f4c6a33..59d80ba 100644
    --- a/drivers/staging/media/imx/imx-media-csi.c
    +++ b/drivers/staging/media/imx/imx-media-csi.c
    @@ -63,6 +63,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;

    /* active vb2 buffers to send to video dev sink */
    @@ -589,7 +590,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,
    + &priv->frame_interval, true);
    if (ret)
    goto idmac_stop;
    }
    @@ -604,7 +606,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,
    + &priv->frame_interval, false);
    idmac_stop:
    if (priv->dest == IPU_CSI_DEST_IDMAC)
    csi_idmac_stop(priv);
    @@ -618,7 +621,8 @@ 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,
    + &priv->frame_interval, false);

    ipu_csi_disable(priv->csi);
    }
    @@ -627,6 +631,36 @@ static void csi_stop(struct csi_priv *priv)
    * V4L2 subdev operations.
    */

    +static int csi_g_frame_interval(struct v4l2_subdev *sd,
    + struct v4l2_subdev_frame_interval *fi)
    +{
    + struct csi_priv *priv = v4l2_get_subdevdata(sd);
    +
    + mutex_lock(&priv->lock);
    + fi->interval = priv->frame_interval;
    + mutex_unlock(&priv->lock);
    +
    + 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);
    +
    + mutex_lock(&priv->lock);
    +
    + /* 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;
    +
    + mutex_unlock(&priv->lock);
    +
    + return 0;
    +}
    +
    static int csi_s_stream(struct v4l2_subdev *sd, int enable)
    {
    struct csi_priv *priv = v4l2_get_subdevdata(sd);
    @@ -1216,6 +1250,10 @@ static int csi_registered(struct v4l2_subdev *sd)
    goto put_csi;
    }

    + /* init default frame interval */
    + priv->frame_interval.numerator = 1;
    + priv->frame_interval.denominator = 30;
    +
    priv->fim = imx_media_fim_init(&priv->sd);
    if (IS_ERR(priv->fim)) {
    ret = PTR_ERR(priv->fim);
    @@ -1266,6 +1304,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 0623bc5..e9525cd 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, &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(1000000ULL * (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 nominal frame rate, send the frame interval error
    - * event. The frame intervals are averaged in order to quiet noise from
    + * from the nominal frame rate, send the frame interval error event. The
    + * frame intervals are averaged in order to quiet noise from
    * (presumably random) interrupt latency.
    */
    static void frame_interval_monitor(struct imx_media_fim *fim,
    @@ -422,12 +414,12 @@ EXPORT_SYMBOL_GPL(imx_media_fim_set_power);

    /* Called by the subdev in its s_stream callback */
    int imx_media_fim_set_stream(struct imx_media_fim *fim,
    - struct imx_media_subdev *sensor,
    + const struct v4l2_fract *fi,
    bool on)
    {
    if (on) {
    reset_fim(fim, true);
    - update_fim_nominal(fim, sensor);
    + update_fim_nominal(fim, fi);

    if (fim->icap_channel >= 0)
    fim_acquire_first_ts(fim);
    diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h
    index b991081..b6a0e41 100644
    --- a/drivers/staging/media/imx/imx-media.h
    +++ b/drivers/staging/media/imx/imx-media.h
    @@ -256,7 +256,7 @@ struct imx_media_fim;
    void imx_media_fim_eof_monitor(struct imx_media_fim *fim, struct timespec *ts);
    int imx_media_fim_set_power(struct imx_media_fim *fim, bool on);
    int imx_media_fim_set_stream(struct imx_media_fim *fim,
    - struct imx_media_subdev *sensor,
    + const struct v4l2_fract *frame_interval,
    bool on);
    struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd);
    void imx_media_fim_free(struct imx_media_fim *fim);
    --
    2.7.4
    \
     
     \ /
      Last update: 2017-03-28 02:47    [W:4.076 / U:0.396 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site