diff options
Diffstat (limited to 'drivers/media/platform/renesas/rcar-isp.c')
-rw-r--r-- | drivers/media/platform/renesas/rcar-isp.c | 162 |
1 files changed, 105 insertions, 57 deletions
diff --git a/drivers/media/platform/renesas/rcar-isp.c b/drivers/media/platform/renesas/rcar-isp.c index c515278e3be5..4bc89d4757fa 100644 --- a/drivers/media/platform/renesas/rcar-isp.c +++ b/drivers/media/platform/renesas/rcar-isp.c @@ -76,6 +76,54 @@ static const struct rcar_isp_format rcar_isp_formats[] = { .code = MEDIA_BUS_FMT_YUYV10_2X10, .datatype = MIPI_CSI2_DT_YUV422_8B, .procmode = 0x0c, + }, { + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .datatype = MIPI_CSI2_DT_RAW8, + .procmode = 0x00, + }, { + .code = MEDIA_BUS_FMT_SGBRG8_1X8, + .datatype = MIPI_CSI2_DT_RAW8, + .procmode = 0x00, + }, { + .code = MEDIA_BUS_FMT_SGRBG8_1X8, + .datatype = MIPI_CSI2_DT_RAW8, + .procmode = 0x00, + }, { + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + .datatype = MIPI_CSI2_DT_RAW8, + .procmode = 0x00, + }, { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, + .datatype = MIPI_CSI2_DT_RAW10, + .procmode = 0x01, + }, { + .code = MEDIA_BUS_FMT_SGBRG10_1X10, + .datatype = MIPI_CSI2_DT_RAW10, + .procmode = 0x01, + }, { + .code = MEDIA_BUS_FMT_SGRBG10_1X10, + .datatype = MIPI_CSI2_DT_RAW10, + .procmode = 0x01, + }, { + .code = MEDIA_BUS_FMT_SRGGB10_1X10, + .datatype = MIPI_CSI2_DT_RAW10, + .procmode = 0x01, + }, { + .code = MEDIA_BUS_FMT_SBGGR12_1X12, + .datatype = MIPI_CSI2_DT_RAW12, + .procmode = 0x02, + }, { + .code = MEDIA_BUS_FMT_SGBRG12_1X12, + .datatype = MIPI_CSI2_DT_RAW12, + .procmode = 0x02, + }, { + .code = MEDIA_BUS_FMT_SGRBG12_1X12, + .datatype = MIPI_CSI2_DT_RAW12, + .procmode = 0x02, + }, { + .code = MEDIA_BUS_FMT_SRGGB12_1X12, + .datatype = MIPI_CSI2_DT_RAW12, + .procmode = 0x02, }, }; @@ -121,9 +169,8 @@ struct rcar_isp { struct v4l2_async_notifier notifier; struct v4l2_subdev *remote; + unsigned int remote_pad; - struct mutex lock; /* Protects mf and stream_count. */ - struct v4l2_mbus_framefmt mf; int stream_count; }; @@ -170,14 +217,19 @@ static void risp_power_off(struct rcar_isp *isp) pm_runtime_put(isp->dev); } -static int risp_start(struct rcar_isp *isp) +static int risp_start(struct rcar_isp *isp, struct v4l2_subdev_state *state) { + const struct v4l2_mbus_framefmt *fmt; const struct rcar_isp_format *format; unsigned int vc; u32 sel_csi = 0; int ret; - format = risp_code_to_fmt(isp->mf.code); + fmt = v4l2_subdev_state_get_format(state, RCAR_ISP_SINK); + if (!fmt) + return -EINVAL; + + format = risp_code_to_fmt(fmt->code); if (!format) { dev_err(isp->dev, "Unsupported bus format\n"); return -EINVAL; @@ -219,7 +271,8 @@ static int risp_start(struct rcar_isp *isp) /* Start ISP. */ risp_write(isp, ISPSTART_REG, ISPSTART_START); - ret = v4l2_subdev_call(isp->remote, video, s_stream, 1); + ret = v4l2_subdev_enable_streams(isp->remote, isp->remote_pad, + BIT_ULL(0)); if (ret) risp_power_off(isp); @@ -228,7 +281,7 @@ static int risp_start(struct rcar_isp *isp) static void risp_stop(struct rcar_isp *isp) { - v4l2_subdev_call(isp->remote, video, s_stream, 0); + v4l2_subdev_disable_streams(isp->remote, isp->remote_pad, BIT_ULL(0)); /* Stop ISP. */ risp_write(isp, ISPSTART_REG, ISPSTART_STOP); @@ -236,87 +289,79 @@ static void risp_stop(struct rcar_isp *isp) risp_power_off(isp); } -static int risp_s_stream(struct v4l2_subdev *sd, int enable) +static int risp_enable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, u32 source_pad, + u64 source_streams_mask) { struct rcar_isp *isp = sd_to_isp(sd); int ret = 0; - mutex_lock(&isp->lock); + if (source_streams_mask != 1) + return -EINVAL; - if (!isp->remote) { - ret = -ENODEV; - goto out; - } + if (!isp->remote) + return -ENODEV; - if (enable && isp->stream_count == 0) { - ret = risp_start(isp); + if (isp->stream_count == 0) { + ret = risp_start(isp, state); if (ret) - goto out; - } else if (!enable && isp->stream_count == 1) { - risp_stop(isp); + return ret; } - isp->stream_count += enable ? 1 : -1; -out: - mutex_unlock(&isp->lock); + isp->stream_count += 1; return ret; } -static const struct v4l2_subdev_video_ops risp_video_ops = { - .s_stream = risp_s_stream, -}; - -static int risp_set_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) +static int risp_disable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, u32 source_pad, + u64 source_streams_mask) { struct rcar_isp *isp = sd_to_isp(sd); - struct v4l2_mbus_framefmt *framefmt; - mutex_lock(&isp->lock); + if (source_streams_mask != 1) + return -EINVAL; - if (!risp_code_to_fmt(format->format.code)) - format->format.code = rcar_isp_formats[0].code; + if (!isp->remote) + return -ENODEV; - if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { - isp->mf = format->format; - } else { - framefmt = v4l2_subdev_state_get_format(sd_state, 0); - *framefmt = format->format; - } + if (isp->stream_count == 1) + risp_stop(isp); - mutex_unlock(&isp->lock); + isp->stream_count -= 1; return 0; } -static int risp_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, +static int risp_set_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *format) { - struct rcar_isp *isp = sd_to_isp(sd); + struct v4l2_mbus_framefmt *framefmt; - mutex_lock(&isp->lock); + if (format->pad > RCAR_ISP_SINK) + return v4l2_subdev_get_fmt(sd, state, format); - if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) - format->format = isp->mf; - else - format->format = *v4l2_subdev_state_get_format(sd_state, 0); + if (!risp_code_to_fmt(format->format.code)) + format->format.code = rcar_isp_formats[0].code; - mutex_unlock(&isp->lock); + for (unsigned int i = 0; i < RCAR_ISP_NUM_PADS; i++) { + framefmt = v4l2_subdev_state_get_format(state, i); + *framefmt = format->format; + } return 0; } static const struct v4l2_subdev_pad_ops risp_pad_ops = { + .enable_streams = risp_enable_streams, + .disable_streams = risp_disable_streams, .set_fmt = risp_set_pad_format, - .get_fmt = risp_get_pad_format, + .get_fmt = v4l2_subdev_get_fmt, .link_validate = v4l2_subdev_link_validate_default, }; static const struct v4l2_subdev_ops rcar_isp_subdev_ops = { - .video = &risp_video_ops, .pad = &risp_pad_ops, }; @@ -339,6 +384,7 @@ static int risp_notify_bound(struct v4l2_async_notifier *notifier, } isp->remote = subdev; + isp->remote_pad = pad; dev_dbg(isp->dev, "Bound %s pad: %d\n", subdev->name, pad); @@ -449,12 +495,10 @@ static int risp_probe(struct platform_device *pdev) isp->dev = &pdev->dev; - mutex_init(&isp->lock); - ret = risp_probe_resources(isp, pdev); if (ret) { dev_err(isp->dev, "Failed to get resources\n"); - goto error_mutex; + return ret; } platform_set_drvdata(pdev, isp); @@ -485,20 +529,25 @@ static int risp_probe(struct platform_device *pdev) if (ret) goto error_notifier; + ret = v4l2_subdev_init_finalize(&isp->subdev); + if (ret) + goto error_notifier; + ret = v4l2_async_register_subdev(&isp->subdev); if (ret < 0) - goto error_notifier; + goto error_subdev; dev_info(isp->dev, "Using CSI-2 input: %u\n", isp->csi_input); return 0; + +error_subdev: + v4l2_subdev_cleanup(&isp->subdev); error_notifier: v4l2_async_nf_unregister(&isp->notifier); v4l2_async_nf_cleanup(&isp->notifier); error_pm: pm_runtime_disable(&pdev->dev); -error_mutex: - mutex_destroy(&isp->lock); return ret; } @@ -511,10 +560,9 @@ static void risp_remove(struct platform_device *pdev) v4l2_async_nf_cleanup(&isp->notifier); v4l2_async_unregister_subdev(&isp->subdev); + v4l2_subdev_cleanup(&isp->subdev); pm_runtime_disable(&pdev->dev); - - mutex_destroy(&isp->lock); } static struct platform_driver rcar_isp_driver = { |