Connect the CSI receiver subdevice between the sensors and the ISP. This includes: - Calling the subdevice via the v4l2 subdev API - Moving the async notifier for the sensor from the ISP to the CSI receiver - In the ISP, create a media link to the CSI receiver, and remove the media link creation to the sensor - In the CSI receiver, create a media link to the sensor Signed-off-by: Paul Elder <paul.elder@xxxxxxxxxxxxxxxx> Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> --- Changes since v1: - Clarify commit message - Update the media device topology - Fix white space --- .../platform/rockchip/rkisp1/rkisp1-csi.c | 34 ++++++++- .../platform/rockchip/rkisp1/rkisp1-csi.h | 6 +- .../platform/rockchip/rkisp1/rkisp1-dev.c | 70 ++++++++++--------- .../platform/rockchip/rkisp1/rkisp1-isp.c | 21 +----- 4 files changed, 75 insertions(+), 56 deletions(-) diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c index 173a0550af5c..6d904bbef424 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c @@ -44,6 +44,34 @@ rkisp1_csi_get_pad_fmt(struct rkisp1_csi *csi, return v4l2_subdev_get_try_format(&csi->sd, &state, pad); } +int rkisp1_csi_link_sensor(struct rkisp1_device *rkisp1, struct v4l2_subdev *sd, + struct rkisp1_sensor_async *s_asd, + unsigned int source_pad) +{ + struct rkisp1_csi *csi = &rkisp1->csi; + int ret; + + s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler, + V4L2_CID_PIXEL_RATE); + if (!s_asd->pixel_rate_ctrl) { + dev_err(rkisp1->dev, "No pixel rate control in subdev %s\n", + sd->name); + return -EINVAL; + } + + /* Create the link from the sensor to the CSI receiver. */ + ret = media_create_pad_link(&sd->entity, source_pad, + &csi->sd.entity, RKISP1_CSI_PAD_SINK, + !s_asd->index ? MEDIA_LNK_FL_ENABLED : 0); + if (ret) { + dev_err(csi->rkisp1->dev, "failed to link src pad of %s\n", + sd->name); + return ret; + } + + return 0; +} + static int rkisp1_csi_config(struct rkisp1_csi *csi, const struct rkisp1_sensor_async *sensor) { @@ -120,8 +148,8 @@ static void rkisp1_csi_disable(struct rkisp1_csi *csi) val & (~RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA)); } -int rkisp1_csi_start(struct rkisp1_csi *csi, - const struct rkisp1_sensor_async *sensor) +static int rkisp1_csi_start(struct rkisp1_csi *csi, + const struct rkisp1_sensor_async *sensor) { struct rkisp1_device *rkisp1 = csi->rkisp1; union phy_configure_opts opts; @@ -157,7 +185,7 @@ int rkisp1_csi_start(struct rkisp1_csi *csi, return 0; } -void rkisp1_csi_stop(struct rkisp1_csi *csi) +static void rkisp1_csi_stop(struct rkisp1_csi *csi) { rkisp1_csi_disable(csi); diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.h index ddf8e5e08f55..eadcd24f65fb 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.h +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-csi.h @@ -21,8 +21,8 @@ void rkisp1_csi_cleanup(struct rkisp1_device *rkisp1); int rkisp1_csi_register(struct rkisp1_device *rkisp1); void rkisp1_csi_unregister(struct rkisp1_device *rkisp1); -int rkisp1_csi_start(struct rkisp1_csi *csi, - const struct rkisp1_sensor_async *sensor); -void rkisp1_csi_stop(struct rkisp1_csi *csi); +int rkisp1_csi_link_sensor(struct rkisp1_device *rkisp1, struct v4l2_subdev *sd, + struct rkisp1_sensor_async *s_asd, + unsigned int source_pad); #endif /* _RKISP1_CSI_H */ diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c index 5428e19e818f..c3a7ab70bbef 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c @@ -17,6 +17,7 @@ #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include <media/v4l2-fwnode.h> +#include <media/v4l2-mc.h> #include "rkisp1-common.h" #include "rkisp1-csi.h" @@ -67,18 +68,28 @@ * * Media Topology * -------------- - * +----------+ +----------+ - * | Sensor 2 | | Sensor X | - * ------------ ... ------------ - * | 0 | | 0 | - * +----------+ +----------+ +-----------+ - * \ | | params | - * \ | | (output) | - * +----------+ \ | +-----------+ - * | Sensor 1 | v v | - * ------------ +------+------+ | - * | 0 |----->| 0 | 1 |<---------+ - * +----------+ |------+------| + * + * +----------+ +----------+ + * | Sensor 1 | | Sensor X | + * ------------ ... ------------ + * | 0 | | 0 | + * +----------+ +----------+ + * | | + * \----\ /----/ + * | | + * v v + * +-------------+ + * | 0 | + * --------------- + * | CSI-2 RX | + * --------------- +-----------+ + * | 1 | | params | + * +-------------+ | (output) | + * | +-----------+ + * v | + * +------+------+ | + * | 0 | 1 |<---------+ + * |------+------| * | ISP | * |------+------| * +-------------| 2 | 3 |----------+ @@ -119,17 +130,8 @@ static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier, container_of(asd, struct rkisp1_sensor_async, asd); int source_pad; - s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler, - V4L2_CID_PIXEL_RATE); - if (!s_asd->pixel_rate_ctrl) { - dev_err(rkisp1->dev, "No pixel rate control in subdev %s\n", - sd->name); - return -EINVAL; - } - s_asd->sd = sd; - /* Create the link to the sensor. */ source_pad = media_entity_get_fwnode_pad(&sd->entity, s_asd->source_ep, MEDIA_PAD_FL_SOURCE); if (source_pad < 0) { @@ -138,10 +140,7 @@ static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier, return source_pad; } - return media_create_pad_link(&sd->entity, source_pad, - &rkisp1->isp.sd.entity, - RKISP1_ISP_PAD_SINK_VIDEO, - !s_asd->index ? MEDIA_LNK_FL_ENABLED : 0); + return rkisp1_csi_link_sensor(rkisp1, sd, s_asd, source_pad); } static int rkisp1_subdev_notifier_complete(struct v4l2_async_notifier *notifier) @@ -283,6 +282,14 @@ static int rkisp1_create_links(struct rkisp1_device *rkisp1) unsigned int i; int ret; + /* Link the CSI receiver to the ISP. */ + ret = media_create_pad_link(&rkisp1->csi.sd.entity, RKISP1_CSI_PAD_SRC, + &rkisp1->isp.sd.entity, + RKISP1_ISP_PAD_SINK_VIDEO, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + /* create ISP->RSZ->CAP links */ for (i = 0; i < 2; i++) { struct media_entity *resizer = @@ -364,13 +371,6 @@ static int rkisp1_entities_register(struct rkisp1_device *rkisp1) if (ret) goto error; - ret = rkisp1_subdev_notifier_register(rkisp1); - if (ret) { - dev_err(rkisp1->dev, - "Failed to register subdev notifier(%d)\n", ret); - goto error; - } - return 0; error: @@ -534,10 +534,16 @@ static int rkisp1_probe(struct platform_device *pdev) if (ret) goto err_cleanup_csi; + ret = rkisp1_subdev_notifier_register(rkisp1); + if (ret) + goto err_unreg_entities; + rkisp1_debug_init(rkisp1); return 0; +err_unreg_entities: + rkisp1_entities_unregister(rkisp1); err_cleanup_csi: rkisp1_csi_cleanup(rkisp1); err_unreg_media_dev: diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c index d7e2802d11f5..ea0bbccb5aee 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c @@ -16,7 +16,6 @@ #include <media/v4l2-event.h> #include "rkisp1-common.h" -#include "rkisp1-csi.h" #define RKISP1_DEF_SINK_PAD_FMT MEDIA_BUS_FMT_SRGGB10_1X10 #define RKISP1_DEF_SRC_PAD_FMT MEDIA_BUS_FMT_YUYV8_2X8 @@ -728,17 +727,13 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable) { struct rkisp1_isp *isp = to_rkisp1_isp(sd); struct rkisp1_device *rkisp1 = isp->rkisp1; - const struct rkisp1_sensor_async *asd; struct media_pad *source_pad; struct media_pad *sink_pad; int ret; if (!enable) { v4l2_subdev_call(rkisp1->source, video, s_stream, false); - - rkisp1_csi_stop(&rkisp1->csi); rkisp1_isp_stop(isp); - return 0; } @@ -756,30 +751,20 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable) return -EPIPE; } - asd = container_of(rkisp1->source->asd, struct rkisp1_sensor_async, - asd); - - if (asd->mbus_type != V4L2_MBUS_CSI2_DPHY) - return -EINVAL; + if (rkisp1->source != &rkisp1->csi.sd) + return -EPIPE; isp->frame_sequence = -1; mutex_lock(&isp->ops_lock); - ret = rkisp1_config_cif(isp, asd->mbus_type, asd->mbus_flags); + ret = rkisp1_config_cif(isp, V4L2_MBUS_CSI2_DPHY, 0); if (ret) goto mutex_unlock; rkisp1_isp_start(isp); - ret = rkisp1_csi_start(&rkisp1->csi, asd); - if (ret) { - rkisp1_isp_stop(isp); - goto mutex_unlock; - } - ret = v4l2_subdev_call(rkisp1->source, video, s_stream, true); if (ret) { rkisp1_isp_stop(isp); - rkisp1_csi_stop(&rkisp1->csi); goto mutex_unlock; } -- Regards, Laurent Pinchart