On Tue Sep 8 09:33:12 2026 +0300, Tomi Valkeinen wrote:
> Call get_frame_desc to find out VC & DT, instead of hardcoding the VC
> routing and deducing the DT based on the mbus format.
> 
> Reviewed-by: Niklas Söderlund <[email protected]>
> Tested-by: Niklas Söderlund <[email protected]>
> Signed-off-by: Tomi Valkeinen <[email protected]>
> Signed-off-by: Sakari Ailus <[email protected]>

Patch committed.

Thanks,
Sakari Ailus

 drivers/media/platform/renesas/rcar-isp/csisp.c | 110 ++++++++++++++++--------
 1 file changed, 74 insertions(+), 36 deletions(-)

---

diff --git a/drivers/media/platform/renesas/rcar-isp/csisp.c 
b/drivers/media/platform/renesas/rcar-isp/csisp.c
index 97465467d047..6480f6a2a435 100644
--- a/drivers/media/platform/renesas/rcar-isp/csisp.c
+++ b/drivers/media/platform/renesas/rcar-isp/csisp.c
@@ -41,6 +41,9 @@
 #define ISPCS_DT_CODE03_EN0                            BIT(7)
 #define ISPCS_DT_CODE03_DT0(dt)                                ((dt) & 0x3f)
 
+/* ISP has 12 channels, of which channels 4 to 11 are connected to VINs */
+#define ISPCS_NUM_CHANNELS     12
+
 struct rcar_isp_format {
        u32 code;
        unsigned int datatype;
@@ -225,31 +228,82 @@ static void risp_power_off(struct rcar_isp *isp)
        pm_runtime_put(isp->dev);
 }
 
-static int risp_start(struct rcar_isp *isp, struct v4l2_subdev_state *state)
+static int risp_configure_routing(struct rcar_isp *isp,
+                                 struct v4l2_subdev_state *state)
 {
-       const struct v4l2_subdev_route *route;
-       const struct v4l2_mbus_framefmt *fmt;
-       const struct rcar_isp_format *format;
-       unsigned int vc;
-       u32 sel_csi = 0;
+       struct v4l2_mbus_frame_desc source_fd;
+       struct v4l2_subdev_route *route;
        int ret;
 
-       if (state->routing.num_routes != 1)
-               return -EINVAL;
+       ret = v4l2_subdev_call(isp->remote, pad, get_frame_desc,
+                              isp->remote_pad, &source_fd);
+       if (ret)
+               return ret;
 
-       route = &state->routing.routes[0];
+       /* Clear the channel registers */
+       for (unsigned int ch = 0; ch < ISPCS_NUM_CHANNELS; ++ch) {
+               risp_write_cs(isp, ISPCS_FILTER_ID_CH_REG(ch), 0);
+               risp_write_cs(isp, ISPCS_DT_CODE03_CH_REG(ch), 0);
+       }
 
-       fmt = v4l2_subdev_state_get_format(state, route->sink_pad,
-                                          route->sink_stream);
-       if (!fmt)
-               return -EINVAL;
+       for_each_active_route(&state->routing, route) {
+               struct v4l2_mbus_frame_desc_entry *source_entry = NULL;
+               const struct rcar_isp_format *format;
+               const struct v4l2_mbus_framefmt *fmt;
+               unsigned int i;
+               u8 vc, dt, ch;
+               u32 v;
+
+               for (i = 0; i < source_fd.num_entries; i++) {
+                       if (source_fd.entry[i].stream == route->sink_stream) {
+                               source_entry = &source_fd.entry[i];
+                               break;
+                       }
+               }
+
+               if (!source_entry) {
+                       dev_err(isp->dev,
+                               "Failed to find source frame desc entry for 
stream\n");
+                       return -EPIPE;
+               }
+
+               vc = source_entry->bus.csi2.vc;
+               dt = source_entry->bus.csi2.dt;
+               /* Channels 4 - 11 go to VIN */
+               ch = route->source_pad - 1 + 4;
+
+               fmt = v4l2_subdev_state_get_format(state, route->sink_pad,
+                                                  route->sink_stream);
+               if (!fmt)
+                       return -EINVAL;
+
+               format = risp_code_to_fmt(fmt->code);
+               if (!format) {
+                       dev_err(isp->dev, "Unsupported bus format\n");
+                       return -EINVAL;
+               }
+
+               /* VC Filtering */
+               risp_write_cs(isp, ISPCS_FILTER_ID_CH_REG(ch), BIT(vc));
 
-       format = risp_code_to_fmt(fmt->code);
-       if (!format) {
-               dev_err(isp->dev, "Unsupported bus format\n");
-               return -EINVAL;
+               /* DT Filtering */
+               risp_write_cs(isp, ISPCS_DT_CODE03_CH_REG(ch),
+                             ISPCS_DT_CODE03_EN0 | ISPCS_DT_CODE03_DT0(dt));
+
+               /* Proc mode */
+               v = risp_read_cs(isp, ISPPROCMODE_DT_REG(dt));
+               v |= ISPPROCMODE_DT_PROC_MODE_VCn(vc, format->procmode);
+               risp_write_cs(isp, ISPPROCMODE_DT_REG(dt), v);
        }
 
+       return 0;
+}
+
+static int risp_start(struct rcar_isp *isp, struct v4l2_subdev_state *state)
+{
+       u32 sel_csi = 0;
+       int ret;
+
        ret = risp_power_on(isp);
        if (ret) {
                dev_err(isp->dev, "Failed to power on ISP\n");
@@ -263,25 +317,9 @@ static int risp_start(struct rcar_isp *isp, struct 
v4l2_subdev_state *state)
        risp_write_cs(isp, ISPINPUTSEL0_REG,
                      risp_read_cs(isp, ISPINPUTSEL0_REG) | sel_csi);
 
-       /* Configure Channel Selector. */
-       for (vc = 0; vc < 4; vc++) {
-               u8 ch = vc + 4;
-               u8 dt = format->datatype;
-
-               risp_write_cs(isp, ISPCS_FILTER_ID_CH_REG(ch), BIT(vc));
-               risp_write_cs(isp, ISPCS_DT_CODE03_CH_REG(ch),
-                             ISPCS_DT_CODE03_EN3 | ISPCS_DT_CODE03_DT3(dt) |
-                             ISPCS_DT_CODE03_EN2 | ISPCS_DT_CODE03_DT2(dt) |
-                             ISPCS_DT_CODE03_EN1 | ISPCS_DT_CODE03_DT1(dt) |
-                             ISPCS_DT_CODE03_EN0 | ISPCS_DT_CODE03_DT0(dt));
-       }
-
-       /* Setup processing method. */
-       risp_write_cs(isp, ISPPROCMODE_DT_REG(format->datatype),
-                     ISPPROCMODE_DT_PROC_MODE_VCn(3, format->procmode) |
-                     ISPPROCMODE_DT_PROC_MODE_VCn(2, format->procmode) |
-                     ISPPROCMODE_DT_PROC_MODE_VCn(1, format->procmode) |
-                     ISPPROCMODE_DT_PROC_MODE_VCn(0, format->procmode));
+       ret = risp_configure_routing(isp, state);
+       if (ret)
+               return ret;
 
        /* Start ISP. */
        risp_write_cs(isp, ISPSTART_REG, ISPSTART_START);
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to