aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0803-media-rcar-csi2-Negotiate-data-lanes-number.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0803-media-rcar-csi2-Negotiate-data-lanes-number.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.4/950-0803-media-rcar-csi2-Negotiate-data-lanes-number.patch159
1 files changed, 159 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0803-media-rcar-csi2-Negotiate-data-lanes-number.patch b/target/linux/bcm27xx/patches-5.4/950-0803-media-rcar-csi2-Negotiate-data-lanes-number.patch
new file mode 100644
index 0000000000..f54b33e59c
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.4/950-0803-media-rcar-csi2-Negotiate-data-lanes-number.patch
@@ -0,0 +1,159 @@
+From 15221304a23fd99c84a6da4b68dc0e887150d1ee Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo+renesas@jmondi.org>
+Date: Tue, 16 Jun 2020 16:12:44 +0200
+Subject: [PATCH] media: rcar-csi2: Negotiate data lanes number
+
+Upstream https://patchwork.linuxtv.org/patch/64675/
+
+Use the newly introduced get_mbus_config() subdevice pad operation to
+retrieve the remote subdevice MIPI CSI-2 bus configuration and configure
+the number of active data lanes accordingly.
+
+In order to be able to call the remote subdevice operation cache the
+index of the remote pad connected to the single CSI-2 input port.
+
+Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
+---
+ drivers/media/platform/rcar-vin/rcar-csi2.c | 74 +++++++++++++++++++--
+ 1 file changed, 67 insertions(+), 7 deletions(-)
+
+--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
++++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
+@@ -362,6 +362,7 @@ struct rcar_csi2 {
+
+ struct v4l2_async_notifier notifier;
+ struct v4l2_subdev *remote;
++ unsigned int remote_pad;
+
+ struct v4l2_mbus_framefmt mf;
+
+@@ -407,13 +408,14 @@ static void rcsi2_exit_standby(struct rc
+ reset_control_deassert(priv->rstc);
+ }
+
+-static int rcsi2_wait_phy_start(struct rcar_csi2 *priv)
++static int rcsi2_wait_phy_start(struct rcar_csi2 *priv,
++ unsigned int active_lanes)
+ {
+ unsigned int timeout;
+
+ /* Wait for the clock and data lanes to enter LP-11 state. */
+ for (timeout = 0; timeout <= 20; timeout++) {
+- const u32 lane_mask = (1 << priv->lanes) - 1;
++ const u32 lane_mask = (1 << active_lanes) - 1;
+
+ if ((rcsi2_read(priv, PHCLM_REG) & PHCLM_STOPSTATECKL) &&
+ (rcsi2_read(priv, PHDLM_REG) & lane_mask) == lane_mask)
+@@ -445,7 +447,8 @@ static int rcsi2_set_phypll(struct rcar_
+ return 0;
+ }
+
+-static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp)
++static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp,
++ unsigned int active_lanes)
+ {
+ struct v4l2_subdev *source;
+ struct v4l2_ctrl *ctrl;
+@@ -470,15 +473,63 @@ static int rcsi2_calc_mbps(struct rcar_c
+ * bps = link_freq * 2
+ */
+ mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp;
+- do_div(mbps, priv->lanes * 1000000);
++ do_div(mbps, active_lanes * 1000000);
+
+ return mbps;
+ }
+
++static int rcsi2_config_active_lanes(struct rcar_csi2 *priv,
++ unsigned int *active_lanes)
++{
++ struct v4l2_mbus_config mbus_config = { 0 };
++ unsigned int num_lanes = (-1U);
++ int ret;
++
++ *active_lanes = priv->lanes;
++ ret = v4l2_subdev_call(priv->remote, pad, get_mbus_config,
++ priv->remote_pad, &mbus_config);
++ if (ret == -ENOIOCTLCMD) {
++ dev_dbg(priv->dev, "No remote mbus configuration available\n");
++ return 0;
++ }
++
++ if (ret) {
++ dev_err(priv->dev, "Failed to get remote mbus configuration\n");
++ return ret;
++ }
++
++ if (mbus_config.type != V4L2_MBUS_CSI2_DPHY) {
++ dev_err(priv->dev, "Unsupported media bus type %u\n",
++ mbus_config.type);
++ return -EINVAL;
++ }
++
++ if (mbus_config.flags & V4L2_MBUS_CSI2_1_LANE)
++ num_lanes = 1;
++ else if (mbus_config.flags & V4L2_MBUS_CSI2_2_LANE)
++ num_lanes = 2;
++ else if (mbus_config.flags & V4L2_MBUS_CSI2_3_LANE)
++ num_lanes = 3;
++ else if (mbus_config.flags & V4L2_MBUS_CSI2_4_LANE)
++ num_lanes = 4;
++
++ if (num_lanes > priv->lanes) {
++ dev_err(priv->dev,
++ "Unsupported mbus config: too many data lanes %u\n",
++ num_lanes);
++ return -EINVAL;
++ }
++
++ *active_lanes = num_lanes;
++
++ return 0;
++}
++
+ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
+ {
+ const struct rcar_csi2_format *format;
+ u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0;
++ unsigned int active_lanes;
+ unsigned int i;
+ int mbps, ret;
+
+@@ -520,10 +571,18 @@ static int rcsi2_start_receiver(struct r
+ fld |= FLD_FLD_NUM(1);
+ }
+
++ /*
++ * Get the number of active data lanes inspecting the remote mbus
++ * configuration.
++ */
++ ret = rcsi2_config_active_lanes(priv, &active_lanes);
++ if (ret)
++ return ret;
++
+ phycnt = PHYCNT_ENABLECLK;
+- phycnt |= (1 << priv->lanes) - 1;
++ phycnt |= (1 << active_lanes) - 1;
+
+- mbps = rcsi2_calc_mbps(priv, format->bpp);
++ mbps = rcsi2_calc_mbps(priv, format->bpp, active_lanes);
+ if (mbps < 0)
+ return mbps;
+
+@@ -570,7 +629,7 @@ static int rcsi2_start_receiver(struct r
+ rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ);
+ rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ | PHYCNT_RSTZ);
+
+- ret = rcsi2_wait_phy_start(priv);
++ ret = rcsi2_wait_phy_start(priv, active_lanes);
+ if (ret)
+ return ret;
+
+@@ -747,6 +806,7 @@ static int rcsi2_notify_bound(struct v4l
+ }
+
+ priv->remote = subdev;
++ priv->remote_pad = pad;
+
+ dev_dbg(priv->dev, "Bound %s pad: %d\n", subdev->name, pad);
+