@@ -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);
@@ -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;
+
media_pipeline_stop(&video_dev->entity);
error_state:
@@ -634,11 +638,14 @@ static int sun6i_csi_capture_start_streaming(struct vb2_queue *queue,
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;
+
media_pipeline_stop(&video_dev->entity);
sun6i_csi_capture_state_cleanup(csi_dev, true);
@@ -44,6 +44,7 @@ struct sun6i_csi_capture_state {
struct sun6i_csi_buffer *complete;
unsigned int sequence;
+ bool streaming;
};
struct sun6i_csi_capture {