media: imx: imx7_mipi_csis: Calculate Ths_settle from source lane rate
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Mon, 1 Mar 2021 16:40:19 +0000 (17:40 +0100)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Thu, 11 Mar 2021 10:59:53 +0000 (11:59 +0100)
The Ths_settle timing parameter depends solely on the lane data rate of
the source. Calculate it at runtime instead of requiring it to be
specified in the device tree.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/staging/media/imx/imx7-mipi-csis.c

index 333ab3966b5b9a6c74b49c5f755f5949563c40ad..e1728240b4943f17402ec8644702820d496fbfed 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/reset.h>
 #include <linux/spinlock.h>
 
+#include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fwnode.h>
 #include <media/v4l2-mc.h>
@@ -482,6 +483,39 @@ static void __mipi_csis_set_format(struct csi_state *state)
        mipi_csis_write(state, MIPI_CSIS_ISPRESOL_CH0, val);
 }
 
+static int mipi_csis_calculate_params(struct csi_state *state)
+{
+       s64 link_freq;
+       u32 lane_rate;
+
+       /* Calculate the line rate from the pixel rate. */
+       link_freq = v4l2_get_link_freq(state->src_sd->ctrl_handler,
+                                      state->csis_fmt->width,
+                                      state->bus.num_data_lanes * 2);
+       if (link_freq < 0) {
+               dev_err(state->dev, "Unable to obtain link frequency: %d\n",
+                       (int)link_freq);
+               return link_freq;
+       }
+
+       lane_rate = link_freq * 2;
+
+       if (lane_rate < 80000000 || lane_rate > 1500000000) {
+               dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate);
+               return -EINVAL;
+       }
+
+       /*
+        * The HSSETTLE counter value is document in a table, but can also
+        * easily be calculated.
+        */
+       state->hs_settle = (lane_rate - 5000000) / 45000000;
+       dev_dbg(state->dev, "lane rate %u, Ths_settle %u\n",
+               lane_rate, state->hs_settle);
+
+       return 0;
+}
+
 static void mipi_csis_set_params(struct csi_state *state)
 {
        int lanes = state->bus.num_data_lanes;
@@ -608,9 +642,13 @@ static void mipi_csis_log_counters(struct csi_state *state, bool non_errors)
 static int mipi_csis_s_stream(struct v4l2_subdev *mipi_sd, int enable)
 {
        struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
-       int ret = 0;
+       int ret;
 
        if (enable) {
+               ret = mipi_csis_calculate_params(state);
+               if (ret < 0)
+                       return ret;
+
                mipi_csis_clear_counters(state);
                ret = pm_runtime_get_sync(&state->pdev->dev);
                if (ret < 0) {
@@ -943,9 +981,6 @@ static int mipi_csis_parse_dt(struct platform_device *pdev,
        if (IS_ERR(state->mrst))
                return PTR_ERR(state->mrst);
 
-       /* Get MIPI CSI-2 bus configuration from the endpoint node. */
-       of_property_read_u32(node, "fsl,csis-hs-settle", &state->hs_settle);
-
        return 0;
 }
 
@@ -1143,9 +1178,8 @@ static int mipi_csis_probe(struct platform_device *pdev)
                        goto unregister_all;
        }
 
-       dev_info(&pdev->dev, "lanes: %d, hs_settle: %d, freq: %u\n",
-                state->bus.num_data_lanes, state->hs_settle,
-                state->clk_frequency);
+       dev_info(&pdev->dev, "lanes: %d, freq: %u\n",
+                state->bus.num_data_lanes, state->clk_frequency);
 
        return 0;