media: imx-mipi-csis: Use V4L2 subdev active state
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Thu, 26 Jan 2023 01:10:01 +0000 (02:10 +0100)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Wed, 8 Feb 2023 08:11:42 +0000 (09:11 +0100)
Use the V4L2 subdev active state API to store the active format. This
simplifies the driver not only by dropping the mipi_csis_device csis_fmt
and format_mbus fields, but it also allows dropping the device lock,
replaced with the state lock.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Tested-by: Adam Ford <aford173@gmail.com> #imx8mn-beacon
Acked-by: Rui Miguel Silva <rmfrfs@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/platform/nxp/imx-mipi-csis.c

index 38ed886..9e424cb 100644 (file)
@@ -327,10 +327,6 @@ struct mipi_csis_device {
        u32 hs_settle;
        u32 clk_settle;
 
-       struct mutex lock;      /* Protect csis_fmt and format_mbus */
-       const struct csis_pix_format *csis_fmt;
-       struct v4l2_mbus_framefmt format_mbus[CSIS_PADS_NUM];
-
        spinlock_t slock;       /* Protect events */
        struct mipi_csis_event events[MIPI_CSIS_NUM_EVENTS];
        struct dentry *debugfs_root;
@@ -559,7 +555,6 @@ static void mipi_csis_system_enable(struct mipi_csis_device *csis, int on)
        mipi_csis_write(csis, MIPI_CSIS_DPHY_CMN_CTRL, val);
 }
 
-/* Called with the csis.lock mutex held */
 static void __mipi_csis_set_format(struct mipi_csis_device *csis,
                                   const struct v4l2_mbus_framefmt *format,
                                   const struct csis_pix_format *csis_fmt)
@@ -941,79 +936,67 @@ static struct mipi_csis_device *sd_to_mipi_csis_device(struct v4l2_subdev *sdev)
 static int mipi_csis_s_stream(struct v4l2_subdev *sd, int enable)
 {
        struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
-       const struct v4l2_mbus_framefmt *format = &csis->format_mbus[CSIS_PAD_SINK];
-       const struct csis_pix_format *csis_fmt = csis->csis_fmt;
+       const struct v4l2_mbus_framefmt *format;
+       const struct csis_pix_format *csis_fmt;
+       struct v4l2_subdev_state *state;
        int ret;
 
        if (!enable) {
-               mutex_lock(&csis->lock);
-
                v4l2_subdev_call(csis->src_sd, video, s_stream, 0);
 
                mipi_csis_stop_stream(csis);
                if (csis->debug.enable)
                        mipi_csis_log_counters(csis, true);
 
-               mutex_unlock(&csis->lock);
-
                pm_runtime_put(csis->dev);
 
                return 0;
        }
 
+       state = v4l2_subdev_lock_and_get_active_state(sd);
+
+       format = v4l2_subdev_get_pad_format(sd, state, CSIS_PAD_SINK);
+       csis_fmt = find_csis_format(format->code);
+
        ret = mipi_csis_calculate_params(csis, csis_fmt);
        if (ret < 0)
-               return ret;
+               goto err_unlock;
 
        mipi_csis_clear_counters(csis);
 
        ret = pm_runtime_resume_and_get(csis->dev);
        if (ret < 0)
-               return ret;
-
-       mutex_lock(&csis->lock);
+               goto err_unlock;
 
        mipi_csis_start_stream(csis, format, csis_fmt);
+
        ret = v4l2_subdev_call(csis->src_sd, video, s_stream, 1);
        if (ret < 0)
-               goto error;
+               goto err_stop;
 
        mipi_csis_log_counters(csis, true);
 
-       mutex_unlock(&csis->lock);
+       v4l2_subdev_unlock_state(state);
 
        return 0;
 
-error:
+err_stop:
        mipi_csis_stop_stream(csis);
-       mutex_unlock(&csis->lock);
        pm_runtime_put(csis->dev);
+err_unlock:
+       v4l2_subdev_unlock_state(state);
 
        return ret;
 }
 
-static struct v4l2_mbus_framefmt *
-mipi_csis_get_format(struct mipi_csis_device *csis,
-                    struct v4l2_subdev_state *sd_state,
-                    enum v4l2_subdev_format_whence which,
-                    unsigned int pad)
-{
-       if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(&csis->sd, sd_state, pad);
-
-       return &csis->format_mbus[pad];
-}
-
 static int mipi_csis_init_cfg(struct v4l2_subdev *sd,
                              struct v4l2_subdev_state *sd_state)
 {
-       struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
        struct v4l2_mbus_framefmt *fmt_sink;
        struct v4l2_mbus_framefmt *fmt_source;
-       enum v4l2_subdev_format_whence which;
 
-       which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
-       fmt_sink = mipi_csis_get_format(csis, sd_state, which, CSIS_PAD_SINK);
+       fmt_sink = v4l2_subdev_get_pad_format(sd, sd_state, CSIS_PAD_SINK);
+       fmt_source = v4l2_subdev_get_pad_format(sd, sd_state, CSIS_PAD_SOURCE);
 
        fmt_sink->code = MEDIA_BUS_FMT_UYVY8_1X16;
        fmt_sink->width = MIPI_CSIS_DEF_PIX_WIDTH;
@@ -1027,36 +1010,15 @@ static int mipi_csis_init_cfg(struct v4l2_subdev *sd,
                V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
                                              fmt_sink->ycbcr_enc);
 
-       fmt_source = mipi_csis_get_format(csis, sd_state, which,
-                                         CSIS_PAD_SOURCE);
        *fmt_source = *fmt_sink;
 
        return 0;
 }
 
-static int mipi_csis_get_fmt(struct v4l2_subdev *sd,
-                            struct v4l2_subdev_state *sd_state,
-                            struct v4l2_subdev_format *sdformat)
-{
-       struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
-       struct v4l2_mbus_framefmt *fmt;
-
-       fmt = mipi_csis_get_format(csis, sd_state, sdformat->which,
-                                  sdformat->pad);
-
-       mutex_lock(&csis->lock);
-       sdformat->format = *fmt;
-       mutex_unlock(&csis->lock);
-
-       return 0;
-}
-
 static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd,
                                    struct v4l2_subdev_state *sd_state,
                                    struct v4l2_subdev_mbus_code_enum *code)
 {
-       struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
-
        /*
         * The CSIS can't transcode in any way, the source format is identical
         * to the sink format.
@@ -1067,8 +1029,7 @@ static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd,
                if (code->index > 0)
                        return -EINVAL;
 
-               fmt = mipi_csis_get_format(csis, sd_state, code->which,
-                                          code->pad);
+               fmt = v4l2_subdev_get_pad_format(sd, sd_state, code->pad);
                code->code = fmt->code;
                return 0;
        }
@@ -1088,7 +1049,6 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
                             struct v4l2_subdev_state *sd_state,
                             struct v4l2_subdev_format *sdformat)
 {
-       struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
        struct csis_pix_format const *csis_fmt;
        struct v4l2_mbus_framefmt *fmt;
        unsigned int align;
@@ -1098,7 +1058,7 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
         * modified.
         */
        if (sdformat->pad == CSIS_PAD_SOURCE)
-               return mipi_csis_get_fmt(sd, sd_state, sdformat);
+               return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
 
        if (sdformat->pad != CSIS_PAD_SINK)
                return -EINVAL;
@@ -1136,10 +1096,7 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
                              &sdformat->format.height, 1,
                              CSIS_MAX_PIX_HEIGHT, 0, 0);
 
-       fmt = mipi_csis_get_format(csis, sd_state, sdformat->which,
-                                  sdformat->pad);
-
-       mutex_lock(&csis->lock);
+       fmt = v4l2_subdev_get_pad_format(sd, sd_state, sdformat->pad);
 
        fmt->code = csis_fmt->code;
        fmt->width = sdformat->format.width;
@@ -1152,44 +1109,40 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
        sdformat->format = *fmt;
 
        /* Propagate the format from sink to source. */
-       fmt = mipi_csis_get_format(csis, sd_state, sdformat->which,
-                                  CSIS_PAD_SOURCE);
+       fmt = v4l2_subdev_get_pad_format(sd, sd_state, CSIS_PAD_SOURCE);
        *fmt = sdformat->format;
 
        /* The format on the source pad might change due to unpacking. */
        fmt->code = csis_fmt->output;
 
-       /* Store the CSIS format descriptor for active formats. */
-       if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
-               csis->csis_fmt = csis_fmt;
-
-       mutex_unlock(&csis->lock);
-
        return 0;
 }
 
 static int mipi_csis_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
                                    struct v4l2_mbus_frame_desc *fd)
 {
-       struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
        struct v4l2_mbus_frame_desc_entry *entry = &fd->entry[0];
+       const struct csis_pix_format *csis_fmt;
+       const struct v4l2_mbus_framefmt *fmt;
+       struct v4l2_subdev_state *state;
 
        if (pad != CSIS_PAD_SOURCE)
                return -EINVAL;
 
+       state = v4l2_subdev_lock_and_get_active_state(sd);
+       fmt = v4l2_subdev_get_pad_format(sd, state, CSIS_PAD_SOURCE);
+       csis_fmt = find_csis_format(fmt->code);
+       v4l2_subdev_unlock_state(state);
+
        fd->type = V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL;
        fd->num_entries = 1;
 
        memset(entry, 0, sizeof(*entry));
 
-       mutex_lock(&csis->lock);
-
        entry->flags = 0;
-       entry->pixelcode = csis->csis_fmt->code;
+       entry->pixelcode = csis_fmt->code;
        entry->bus.csi2.vc = 0;
-       entry->bus.csi2.dt = csis->csis_fmt->data_type;
-
-       mutex_unlock(&csis->lock);
+       entry->bus.csi2.dt = csis_fmt->data_type;
 
        return 0;
 }
@@ -1216,7 +1169,7 @@ static const struct v4l2_subdev_video_ops mipi_csis_video_ops = {
 static const struct v4l2_subdev_pad_ops mipi_csis_pad_ops = {
        .init_cfg               = mipi_csis_init_cfg,
        .enum_mbus_code         = mipi_csis_enum_mbus_code,
-       .get_fmt                = mipi_csis_get_fmt,
+       .get_fmt                = v4l2_subdev_get_fmt,
        .set_fmt                = mipi_csis_set_fmt,
        .get_frame_desc         = mipi_csis_get_frame_desc,
 };
@@ -1398,6 +1351,7 @@ static const struct dev_pm_ops mipi_csis_pm_ops = {
 static int mipi_csis_subdev_init(struct mipi_csis_device *csis)
 {
        struct v4l2_subdev *sd = &csis->sd;
+       int ret;
 
        v4l2_subdev_init(sd, &mipi_csis_subdev_ops);
        sd->owner = THIS_MODULE;
@@ -1419,15 +1373,21 @@ static int mipi_csis_subdev_init(struct mipi_csis_device *csis)
                return -ENOENT;
        }
 
-       csis->csis_fmt = &mipi_csis_formats[0];
-       mipi_csis_init_cfg(sd, NULL);
-
        csis->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK
                                         | MEDIA_PAD_FL_MUST_CONNECT;
        csis->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
                                           | MEDIA_PAD_FL_MUST_CONNECT;
-       return media_entity_pads_init(&sd->entity, CSIS_PADS_NUM,
-                                     csis->pads);
+       ret = media_entity_pads_init(&sd->entity, CSIS_PADS_NUM, csis->pads);
+       if (ret)
+               return ret;
+
+       ret = v4l2_subdev_init_finalize(sd);
+       if (ret) {
+               media_entity_cleanup(&sd->entity);
+               return ret;
+       }
+
+       return 0;
 }
 
 static int mipi_csis_parse_dt(struct mipi_csis_device *csis)
@@ -1452,7 +1412,6 @@ static int mipi_csis_probe(struct platform_device *pdev)
        if (!csis)
                return -ENOMEM;
 
-       mutex_init(&csis->lock);
        spin_lock_init(&csis->slock);
 
        csis->dev = dev;
@@ -1533,6 +1492,7 @@ static int mipi_csis_probe(struct platform_device *pdev)
 err_unregister_all:
        mipi_csis_debugfs_exit(csis);
 err_cleanup:
+       v4l2_subdev_cleanup(&csis->sd);
        media_entity_cleanup(&csis->sd.entity);
        v4l2_async_nf_unregister(&csis->notifier);
        v4l2_async_nf_cleanup(&csis->notifier);
@@ -1540,7 +1500,6 @@ err_cleanup:
 err_disable_clock:
        mipi_csis_clk_disable(csis);
        fwnode_handle_put(csis->sd.fwnode);
-       mutex_destroy(&csis->lock);
 
        return ret;
 }
@@ -1558,9 +1517,9 @@ static int mipi_csis_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
        mipi_csis_runtime_suspend(&pdev->dev);
        mipi_csis_clk_disable(csis);
+       v4l2_subdev_cleanup(&csis->sd);
        media_entity_cleanup(&csis->sd.entity);
        fwnode_handle_put(csis->sd.fwnode);
-       mutex_destroy(&csis->lock);
        pm_runtime_set_suspended(&pdev->dev);
 
        return 0;