]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: ccs: Compute binning configuration from sub-device state
authorSakari Ailus <sakari.ailus@linux.intel.com>
Tue, 10 Oct 2023 19:53:04 +0000 (22:53 +0300)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Fri, 16 Jan 2026 13:08:53 +0000 (14:08 +0100)
Calculate binning configuration from sub-device state so the state related
configuration can be removed from the driver's device context struct.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
drivers/media/i2c/ccs/ccs-core.c
drivers/media/i2c/ccs/ccs.h

index 81f81cb2c35413c357ba0a61fa413737fc9faaa2..6d2b5eb506599a6a86a5f39cf37947a2a3fa0f34 100644 (file)
@@ -511,13 +511,36 @@ static int ccs_pll_try(struct ccs_sensor *sensor, struct ccs_pll *pll)
        return ccs_pll_calculate(&client->dev, &lim, pll);
 }
 
+static void
+ccs_get_binning(struct ccs_sensor *sensor, u8 *binning_mode, u8 *binh, u8 *binv)
+{
+       struct v4l2_subdev_state *state =
+               v4l2_subdev_get_locked_active_state(&sensor->binner->sd);
+       const struct v4l2_rect *sink_crop =
+               v4l2_subdev_state_get_crop(state, CCS_PAD_SINK,
+                                          CCS_STREAM_PIXEL);
+       const struct v4l2_rect *sink_comp =
+               v4l2_subdev_state_get_compose(state, CCS_PAD_SINK,
+                                             CCS_STREAM_PIXEL);
+
+       if (binning_mode)
+               *binning_mode = sink_crop->width == sink_comp->width &&
+                               sink_crop->height == sink_comp->height ? 0 : 1;
+
+       *binh = sink_crop->width / sink_comp->width;
+       *binv = sink_crop->height / sink_comp->height;
+}
+
 static int ccs_pll_update(struct ccs_sensor *sensor)
 {
        struct ccs_pll *pll = &sensor->pll;
+       u8 binh, binv;
        int rval;
 
-       pll->binning_horizontal = sensor->binning_horizontal;
-       pll->binning_vertical = sensor->binning_vertical;
+       ccs_get_binning(sensor, NULL, &binh, &binv);
+
+       pll->binning_horizontal = binh;
+       pll->binning_vertical = binv;
        pll->link_freq =
                sensor->link_freq->qmenu_int[sensor->link_freq->val];
        pll->scale_m = sensor->scale_m;
@@ -1239,8 +1262,11 @@ static void ccs_update_blanking(struct ccs_sensor *sensor,
        struct v4l2_ctrl *hblank = sensor->hblank;
        u16 min_fll, max_fll, min_llp, max_llp, min_lbp;
        int min, max;
+       u8 binh, binv;
+
+       ccs_get_binning(sensor, NULL, &binh, &binv);
 
-       if (sensor->binning_vertical > 1 || sensor->binning_horizontal > 1) {
+       if (binv > 1 || binh > 1) {
                min_fll = CCS_LIM(sensor, MIN_FRAME_LENGTH_LINES_BIN);
                max_fll = CCS_LIM(sensor, MAX_FRAME_LENGTH_LINES_BIN);
                min_llp = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK_BIN);
@@ -1808,7 +1834,7 @@ static int ccs_enable_streams(struct v4l2_subdev *subdev,
                v4l2_subdev_state_get_crop(src_state, CCS_PAD_SRC,
                                           CCS_STREAM_PIXEL);
        struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
-       unsigned int binning_mode;
+       u8 binning_mode, binh, binv;
        int rval;
 
        if (pad != CCS_PAD_SRC)
@@ -1830,19 +1856,12 @@ static int ccs_enable_streams(struct v4l2_subdev *subdev,
                goto err_pm_put;
 
        /* Binning configuration */
-       if (sensor->binning_horizontal == 1 &&
-           sensor->binning_vertical == 1) {
-               binning_mode = 0;
-       } else {
-               u8 binning_type =
-                       (sensor->binning_horizontal << 4)
-                       | sensor->binning_vertical;
+       ccs_get_binning(sensor, &binning_mode, &binh, &binv);
 
-               rval = ccs_write(sensor, BINNING_TYPE, binning_type);
+       if (binning_mode) {
+               rval = ccs_write(sensor, BINNING_TYPE, (binh << 4) | binv);
                if (rval < 0)
                        goto err_pm_put;
-
-               binning_mode = 1;
        }
        rval = ccs_write(sensor, BINNING_MODE, binning_mode);
        if (rval < 0)
@@ -2122,9 +2141,6 @@ static void ccs_propagate(struct v4l2_subdev *subdev,
                                sensor->scale_m = CCS_LIM(sensor, SCALER_N_MIN);
                                sensor->scaling_mode =
                                        CCS_SCALING_MODE_NO_SCALING;
-                       } else if (ssd == sensor->binner) {
-                               sensor->binning_horizontal = 1;
-                               sensor->binning_vertical = 1;
                        }
                }
                fallthrough;
@@ -2310,10 +2326,6 @@ static void ccs_set_compose_binner(struct v4l2_subdev *subdev,
                        best = this;
                }
        }
-       if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
-               sensor->binning_vertical = binv;
-               sensor->binning_horizontal = binh;
-       }
 
        sel->r.width = (sink_crop->width / binh) & ~1;
        sel->r.height = (sink_crop->height / binv) & ~1;
@@ -3400,8 +3412,6 @@ static int ccs_probe(struct i2c_client *client)
                                sensor->binning_subtypes[i].vertical);
                }
        }
-       sensor->binning_horizontal = 1;
-       sensor->binning_vertical = 1;
 
        if (device_create_file(&client->dev, &dev_attr_ident) != 0) {
                dev_err(&client->dev, "sysfs ident entry creation failed\n");
index e885063c89f0cb11c5b23af693d96467e1b8492b..62a4900686f86c1def608f6106a02beeecdf164d 100644 (file)
@@ -229,9 +229,6 @@ struct ccs_sensor {
        int default_pixel_order;
        struct ccs_data_container sdata, mdata;
 
-       u8 binning_horizontal;
-       u8 binning_vertical;
-
        u8 scale_m;
        u8 scaling_mode;