Message ID | 20220415152811.636419-41-paul.kocialkowski@bootlin.com |
---|---|
State | Superseded |
Headers | show |
Series | Allwinner A31/A83T MIPI CSI-2 and A31 ISP / CSI Rework | expand |
Dne petek, 15. april 2022 ob 17:28:06 CEST je Paul Kocialkowski napisal(a): > 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> Best regards, Jernej > --- > .../sunxi/sun6i-csi/sun6i_csi_bridge.c | 50 ++++++++++++------- > .../sunxi/sun6i-csi/sun6i_csi_capture.c | 11 +++- > .../sunxi/sun6i-csi/sun6i_csi_capture.h | 1 + > 3 files changed, 41 insertions(+), 21 deletions(-) > > diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c > b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c index > 27289d904d5c..8e9eded0df28 100644 > --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c > +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c > @@ -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_entity *bridge_entity = &bridge->subdev.entity; > + 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; > @@ -448,15 +453,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); > @@ -466,7 +476,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); > diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c > b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c index > f1581b877819..17145ce53395 100644 > --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c > +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c > @@ -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); > diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.h > b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.h index > ceceb030aef6..29893cf96f6b 100644 > --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.h > +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.h > @@ -44,6 +44,7 @@ struct sun6i_csi_capture_state { > struct sun6i_csi_buffer *complete; > > unsigned int sequence; > + bool streaming; > }; > > struct sun6i_csi_capture {
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c index 27289d904d5c..8e9eded0df28 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c @@ -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_entity *bridge_entity = &bridge->subdev.entity; + 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; @@ -448,15 +453,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); @@ -466,7 +476,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); diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c index f1581b877819..17145ce53395 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c @@ -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); diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.h index ceceb030aef6..29893cf96f6b 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.h +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.h @@ -44,6 +44,7 @@ struct sun6i_csi_capture_state { struct sun6i_csi_buffer *complete; unsigned int sequence; + bool streaming; }; struct sun6i_csi_capture {
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> --- .../sunxi/sun6i-csi/sun6i_csi_bridge.c | 50 ++++++++++++------- .../sunxi/sun6i-csi/sun6i_csi_capture.c | 11 +++- .../sunxi/sun6i-csi/sun6i_csi_capture.h | 1 + 3 files changed, 41 insertions(+), 21 deletions(-)