From ef6aee87d225b52fca665c57778351bb921e9285 Mon Sep 17 00:00:00 2001 From: Allon Huang Date: Thu, 25 Mar 2021 15:05:51 +0800 Subject: [PATCH] media: platform: rockchip: cif: optimize dts parameters config Signed-off-by: Allon Huang Change-Id: I2a8f471e52c2099f562f1bf765ea0c3e5d9e5845 --- drivers/media/platform/rockchip/cif/capture.c | 24 +++++-- drivers/media/platform/rockchip/cif/dev.c | 59 +++++++++++++++-- .../media/platform/rockchip/cif/mipi-csi2.c | 63 ++++++++++++++++--- .../media/platform/rockchip/cif/subdev-itf.c | 9 ++- drivers/media/platform/rockchip/cif/version.h | 1 + 5 files changed, 136 insertions(+), 20 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 1be1a5b01232..66cf3e19d0c5 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -434,20 +434,31 @@ static struct v4l2_subdev *get_remote_sensor(struct rkcif_stream *stream, u16 *i { struct media_pad *local, *remote; struct media_entity *sensor_me; + struct v4l2_subdev *sub = NULL; local = &stream->vnode.vdev.entity.pads[0]; - if (!local) + if (!local) { + v4l2_err(&stream->cifdev->v4l2_dev, + "%s: video pad[0] is null\n", __func__); return NULL; + } + remote = media_entity_remote_pad(local); - if (!remote) + if (!remote) { + v4l2_err(&stream->cifdev->v4l2_dev, + "%s: remote pad is null\n", __func__); return NULL; + } if (index) *index = remote->index; sensor_me = remote->entity; - return media_entity_to_v4l2_subdev(sensor_me); + sub = media_entity_to_v4l2_subdev(sensor_me); + + return sub; + } static void get_remote_terminal_sensor(struct rkcif_stream *stream, @@ -2325,8 +2336,12 @@ int rkcif_update_sensor_info(struct rkcif_stream *stream) int ret = 0; sensor_sd = get_remote_sensor(stream, NULL); - if (!sensor_sd) + if (!sensor_sd) { + v4l2_err(&stream->cifdev->v4l2_dev, + "%s: stream[%d] get remote sensor_sd failed!\n", + __func__, stream->id); return -ENODEV; + } sensor = sd_to_sensor(stream->cifdev, sensor_sd); if (!sensor) { @@ -2982,6 +2997,7 @@ static int rkcif_fh_open(struct file *filp) v4l2_err(vdev, "update sensor info failed %d\n", ret); + return ret; } diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index 3c826ff413d6..fd2feb651dad 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -457,7 +457,6 @@ static int rkcif_create_links(struct rkcif_device *dev) unsigned int s, pad, id, stream_num = 0; bool mipi_lvds_linked = false; - if (dev->chip_id < CHIP_RV1126_CIF) { if (dev->inf_id == RKCIF_MIPI_LVDS) stream_num = RKCIF_MAX_STREAM_MIPI; @@ -602,12 +601,52 @@ static int subdev_notifier_complete(struct v4l2_async_notifier *notifier) { struct rkcif_device *dev; struct rkcif_sensor_info *sensor; + struct v4l2_subdev *sd; + struct v4l2_device *v4l2_dev = NULL; int ret, index; dev = container_of(notifier, struct rkcif_device, notifier); + v4l2_dev = &dev->v4l2_dev; + for (index = 0; index < dev->num_sensors; index++) { sensor = &dev->sensors[index]; + + list_for_each_entry(sd, &v4l2_dev->subdevs, list) { + if (sd->ops) { + if (sd == sensor->sd) { + ret = v4l2_subdev_call(sd, + video, + g_mbus_config, + &sensor->mbus); + if (ret) + v4l2_err(v4l2_dev, + "get mbus config failed for linking\n"); + } + } + } + + if (sensor->mbus.type == V4L2_MBUS_CCP2 || + sensor->mbus.type == V4L2_MBUS_CSI2) { + + switch (sensor->mbus.flags & V4L2_MBUS_CSI2_LANES) { + case V4L2_MBUS_CSI2_1_LANE: + sensor->lanes = 1; + break; + case V4L2_MBUS_CSI2_2_LANE: + sensor->lanes = 2; + break; + case V4L2_MBUS_CSI2_3_LANE: + sensor->lanes = 3; + break; + case V4L2_MBUS_CSI2_4_LANE: + sensor->lanes = 4; + break; + default: + sensor->lanes = 1; + } + } + if (sensor->mbus.type == V4L2_MBUS_CCP2) { ret = rkcif_register_lvds_subdev(dev); if (ret < 0) { @@ -676,15 +715,19 @@ static int subdev_notifier_bound(struct v4l2_async_notifier *notifier, struct rkcif_async_subdev *s_asd = container_of(asd, struct rkcif_async_subdev, asd); - if (cif_dev->num_sensors == ARRAY_SIZE(cif_dev->sensors)) + if (cif_dev->num_sensors == ARRAY_SIZE(cif_dev->sensors)) { + v4l2_err(&cif_dev->v4l2_dev, + "%s: the num of subdev is beyond %d\n", + __func__, cif_dev->num_sensors); return -EBUSY; + } cif_dev->sensors[cif_dev->num_sensors].lanes = s_asd->lanes; cif_dev->sensors[cif_dev->num_sensors].mbus = s_asd->mbus; cif_dev->sensors[cif_dev->num_sensors].sd = subdev; ++cif_dev->num_sensors; - v4l2_dbg(1, rkcif_debug, subdev, "Async registered subdev\n"); + v4l2_err(subdev, "Async registered subdev\n"); return 0; } @@ -731,11 +774,17 @@ static int cif_subdev_notifier(struct rkcif_device *cif_dev) ret = v4l2_async_notifier_parse_fwnode_endpoints( dev, ntf, sizeof(struct rkcif_async_subdev), rkcif_fwnode_parse); - if (ret < 0) + if (ret < 0) { + v4l2_err(&cif_dev->v4l2_dev, + "%s: parse fwnode failed\n", __func__); return ret; + } - if (!ntf->num_subdevs) + if (!ntf->num_subdevs) { + v4l2_warn(&cif_dev->v4l2_dev, + "%s: no subdev be found!\n", __func__); return -ENODEV; /* no endpoint */ + } ntf->ops = &subdev_notifier_ops; diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.c b/drivers/media/platform/rockchip/cif/mipi-csi2.c index 176b46794b45..8a29bb3f68d5 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.c +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.c @@ -207,6 +207,40 @@ static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd) return media_entity_to_v4l2_subdev(sensor_me); } +static void csi2_update_sensor_info(struct csi2_dev *csi2) +{ + struct csi2_sensor *sensor = &csi2->sensors[0]; + struct v4l2_mbus_config mbus; + int ret = 0; + + ret = v4l2_subdev_call(sensor->sd, video, g_mbus_config, &mbus); + if (ret) { + v4l2_err(&csi2->sd, "update sensor info failed!\n"); + return; + } + + csi2->bus.flags = mbus.flags; + switch (csi2->bus.flags & V4L2_MBUS_CSI2_LANES) { + case V4L2_MBUS_CSI2_1_LANE: + csi2->bus.num_data_lanes = 1; + break; + case V4L2_MBUS_CSI2_2_LANE: + csi2->bus.num_data_lanes = 2; + break; + case V4L2_MBUS_CSI2_3_LANE: + csi2->bus.num_data_lanes = 3; + break; + case V4L2_MBUS_CSI2_4_LANE: + csi2->bus.num_data_lanes = 4; + break; + default: + v4l2_warn(&csi2->sd, "lane num is invalid\n"); + csi2->bus.num_data_lanes = 0; + break; + } + +} + static void csi2_disable(struct csi2_dev *csi2) { void __iomem *base = csi2->base; @@ -261,6 +295,8 @@ static int csi2_start(struct csi2_dev *csi2) } } + csi2_update_sensor_info(csi2); + if (csi2->format_mbus.code == MEDIA_BUS_FMT_RGB888_1X24) host_type = RK_DSI_RXHOST; else @@ -514,12 +550,16 @@ static int csi2_set_selection(struct v4l2_subdev *sd, static int csi2_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *mbus) { + struct csi2_dev *csi2 = sd_to_dev(sd); struct v4l2_subdev *sensor_sd = get_remote_sensor(sd); int ret; ret = v4l2_subdev_call(sensor_sd, video, g_mbus_config, mbus); - if (ret) - return ret; + if (ret) { + mbus->type = V4L2_MBUS_CSI2; + mbus->flags = csi2->bus.flags; + mbus->flags |= BIT(csi2->bus.num_data_lanes - 1); + } return 0; } @@ -596,10 +636,8 @@ static int csi2_parse_endpoint(struct device *dev, struct v4l2_subdev *sd = dev_get_drvdata(dev); struct csi2_dev *csi2 = sd_to_dev(sd); - if (vep->bus_type != V4L2_MBUS_CSI2) { - v4l2_err(&csi2->sd, - "invalid bus type: %d, must be MIPI CSI2\n", - vep->bus_type); + if (vep->base.port != 0) { + dev_err(dev, "The csi host node needs to parse port 0\n"); return -EINVAL; } @@ -621,9 +659,12 @@ csi2_notifier_bound(struct v4l2_async_notifier *notifier, struct media_link *link; unsigned int pad, ret; - if (csi2->num_sensors == ARRAY_SIZE(csi2->sensors)) + if (csi2->num_sensors == ARRAY_SIZE(csi2->sensors)) { + v4l2_err(&csi2->sd, + "%s: the num of sd is beyond:%d\n", + __func__, csi2->num_sensors); return -EBUSY; - + } sensor = &csi2->sensors[csi2->num_sensors++]; sensor->sd = sd; @@ -673,6 +714,7 @@ static void csi2_notifier_unbind(struct v4l2_async_notifier *notifier, struct csi2_sensor *sensor = sd_to_sensor(csi2, sd); sensor->sd = NULL; + } static const struct @@ -800,7 +842,10 @@ static int csi2_notifier(struct csi2_dev *csi2) v4l2_async_notifier_cleanup(&csi2->notifier); return ret; } - return v4l2_async_register_subdev(&csi2->sd); + + ret = v4l2_async_register_subdev(&csi2->sd); + + return ret; } static const struct csi2_match_data rk1808_csi2_match_data = { diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 05a3df69995d..770f8a32cfe1 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -75,7 +75,12 @@ static int sditf_get_set_fmt(struct v4l2_subdev *sd, rkcif_update_sensor_info(&cif_dev->stream[0]); if (cif_dev->terminal_sensor.sd) { - v4l2_subdev_call(cif_dev->terminal_sensor.sd, pad, get_fmt, NULL, fmt); + ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd, pad, get_fmt, NULL, fmt); + if (ret) { + v4l2_err(&priv->sd, + "%s: get sensor format failed\n", __func__); + return ret; + } input_sel.target = V4L2_SEL_TGT_CROP_BOUNDS; ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd, @@ -87,7 +92,7 @@ static int sditf_get_set_fmt(struct v4l2_subdev *sd, } } - return ret; + return 0; } static int sditf_get_selection(struct v4l2_subdev *sd, diff --git a/drivers/media/platform/rockchip/cif/version.h b/drivers/media/platform/rockchip/cif/version.h index b7d7bdf263e0..d806f3d8d5c7 100644 --- a/drivers/media/platform/rockchip/cif/version.h +++ b/drivers/media/platform/rockchip/cif/version.h @@ -60,6 +60,7 @@ *v0.1.10 *1. rv1126/rk356x support bt656/bt1120 multi channels function *2. add dynamic cropping function + *3. optimize dts config of cif's pipeline */ #define RKCIF_DRIVER_VERSION RKCIF_API_VERSION