media: sun6i-csi: Only configure capture when streaming
authorPaul Kocialkowski <paul.kocialkowski@bootlin.com>
Thu, 3 Nov 2022 16:31:10 +0000 (16:31 +0000)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Fri, 25 Nov 2022 07:17:30 +0000 (07:17 +0000)
Add a streaming element to the capture state structure to know if the
capture device is used or not. Only configure things related to output
when streaming, including the output format, irq, state (dma buffer)
and window configuration registers.

After this change, it becomes possible to use the bridge without the
capture device, which will be the case in the isp media flow.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.h

index 69c1fa7151d915ca77f8875edb4a3b43b220a3ae..492f93b0db28ae4a5b4062d963f08bc4f0a2cbab 100644 (file)
@@ -338,6 +338,7 @@ sun6i_csi_bridge_configure_mipi_csi2(struct sun6i_csi_device *csi_dev)
 static void sun6i_csi_bridge_configure_format(struct sun6i_csi_device *csi_dev)
 {
        struct regmap *regmap = csi_dev->regmap;
+       bool capture_streaming = csi_dev->capture.state.streaming;
        const struct sun6i_csi_bridge_format *bridge_format;
        const struct sun6i_csi_capture_format *capture_format;
        u32 mbus_code, field, pixelformat;
@@ -353,26 +354,29 @@ static void sun6i_csi_bridge_configure_format(struct sun6i_csi_device *csi_dev)
        input_format = bridge_format->input_format;
        input_yuv_seq = bridge_format->input_yuv_seq;
 
-       sun6i_csi_capture_format(csi_dev, &pixelformat, NULL);
+       if (capture_streaming) {
+               sun6i_csi_capture_format(csi_dev, &pixelformat, NULL);
 
-       capture_format = sun6i_csi_capture_format_find(pixelformat);
-       if (WARN_ON(!capture_format))
-               return;
+               capture_format = sun6i_csi_capture_format_find(pixelformat);
+               if (WARN_ON(!capture_format))
+                       return;
 
-       if (capture_format->input_format_raw)
-               input_format = SUN6I_CSI_INPUT_FMT_RAW;
+               if (capture_format->input_format_raw)
+                       input_format = SUN6I_CSI_INPUT_FMT_RAW;
 
-       if (capture_format->input_yuv_seq_invert)
-               input_yuv_seq = bridge_format->input_yuv_seq_invert;
+               if (capture_format->input_yuv_seq_invert)
+                       input_yuv_seq = bridge_format->input_yuv_seq_invert;
 
-       if (field == V4L2_FIELD_INTERLACED ||
-           field == V4L2_FIELD_INTERLACED_TB ||
-           field == V4L2_FIELD_INTERLACED_BT)
-               output_format = capture_format->output_format_field;
-       else
-               output_format = capture_format->output_format_frame;
+               if (field == V4L2_FIELD_INTERLACED ||
+                   field == V4L2_FIELD_INTERLACED_TB ||
+                   field == V4L2_FIELD_INTERLACED_BT)
+                       output_format = capture_format->output_format_field;
+               else
+                       output_format = capture_format->output_format_frame;
+
+               value |= SUN6I_CSI_CH_CFG_OUTPUT_FMT(output_format);
+       }
 
-       value |= SUN6I_CSI_CH_CFG_OUTPUT_FMT(output_format);
        value |= SUN6I_CSI_CH_CFG_INPUT_FMT(input_format);
        value |= SUN6I_CSI_CH_CFG_INPUT_YUV_SEQ(input_yuv_seq);
 
@@ -406,6 +410,7 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
        struct sun6i_csi_device *csi_dev = v4l2_get_subdevdata(subdev);
        struct sun6i_csi_bridge *bridge = &csi_dev->bridge;
        struct media_pad *local_pad = &bridge->pads[SUN6I_CSI_BRIDGE_PAD_SINK];
+       bool capture_streaming = csi_dev->capture.state.streaming;
        struct device *dev = csi_dev->dev;
        struct sun6i_csi_bridge_source *source;
        struct v4l2_subdev *source_subdev;
@@ -447,15 +452,20 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
        /* Configure */
 
        sun6i_csi_bridge_configure(csi_dev, source);
-       sun6i_csi_capture_configure(csi_dev);
+
+       if (capture_streaming)
+               sun6i_csi_capture_configure(csi_dev);
 
        /* State Update */
 
-       sun6i_csi_capture_state_update(csi_dev);
+       if (capture_streaming)
+               sun6i_csi_capture_state_update(csi_dev);
 
        /* Enable */
 
-       sun6i_csi_bridge_irq_enable(csi_dev);
+       if (capture_streaming)
+               sun6i_csi_bridge_irq_enable(csi_dev);
+
        sun6i_csi_bridge_enable(csi_dev);
 
        ret = v4l2_subdev_call(source_subdev, video, s_stream, 1);
@@ -465,7 +475,9 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
        return 0;
 
 disable:
-       sun6i_csi_bridge_irq_disable(csi_dev);
+       if (capture_streaming)
+               sun6i_csi_bridge_irq_disable(csi_dev);
+
        sun6i_csi_bridge_disable(csi_dev);
 
        pm_runtime_put(dev);
index 645ef01f32c5ae6250f962df7efa02e7795b88b9..708338c50b8baaaf3ab521ef4ac91426d67a9135 100644 (file)
@@ -616,13 +616,17 @@ static int sun6i_csi_capture_start_streaming(struct vb2_queue *queue,
        if (ret < 0)
                goto error_state;
 
+       state->streaming = true;
+
        ret = v4l2_subdev_call(subdev, video, s_stream, 1);
        if (ret && ret != -ENOIOCTLCMD)
-               goto error_media_pipeline;
+               goto error_streaming;
 
        return 0;
 
-error_media_pipeline:
+error_streaming:
+       state->streaming = false;
+
        video_device_pipeline_stop(video_dev);
 
 error_state:
@@ -634,11 +638,14 @@ error_state:
 static void sun6i_csi_capture_stop_streaming(struct vb2_queue *queue)
 {
        struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue);
+       struct sun6i_csi_capture_state *state = &csi_dev->capture.state;
        struct video_device *video_dev = &csi_dev->capture.video_dev;
        struct v4l2_subdev *subdev = &csi_dev->bridge.subdev;
 
        v4l2_subdev_call(subdev, video, s_stream, 0);
 
+       state->streaming = false;
+
        video_device_pipeline_stop(video_dev);
 
        sun6i_csi_capture_state_cleanup(csi_dev, true);
index ceceb030aef6de62854ad4004da51a03098bb0f5..29893cf96f6b470fdaff6cab79e2b6e807621ccd 100644 (file)
@@ -44,6 +44,7 @@ struct sun6i_csi_capture_state {
        struct sun6i_csi_buffer         *complete;
 
        unsigned int                    sequence;
+       bool                            streaming;
 };
 
 struct sun6i_csi_capture {