media: ccs: Add support for alternate analogue global gain
authorSakari Ailus <sakari.ailus@linux.intel.com>
Wed, 23 Sep 2020 22:55:00 +0000 (00:55 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Tue, 12 Jan 2021 16:29:01 +0000 (17:29 +0100)
The CCS spec defines an alternative implementation for global analogue
gain. Add support for that in the driver.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/i2c/ccs/ccs-core.c

index c511973..7591a52 100644 (file)
@@ -673,6 +673,17 @@ static int ccs_set_ctrl(struct v4l2_ctrl *ctrl)
 
                break;
 
+       case V4L2_CID_CCS_ANALOGUE_LINEAR_GAIN:
+               rval = ccs_write(sensor, ANALOG_LINEAR_GAIN_GLOBAL, ctrl->val);
+
+               break;
+
+       case V4L2_CID_CCS_ANALOGUE_EXPONENTIAL_GAIN:
+               rval = ccs_write(sensor, ANALOG_EXPONENTIAL_GAIN_GLOBAL,
+                                ctrl->val);
+
+               break;
+
        case V4L2_CID_DIGITAL_GAIN:
                if (CCS_LIM(sensor, DIGITAL_GAIN_CAPABILITY) ==
                    CCS_DIGITAL_GAIN_CAPABILITY_GLOBAL) {
@@ -820,6 +831,50 @@ static int ccs_init_controls(struct ccs_sensor *sensor)
                                      1U),
                                  CCS_LIM(sensor, ANALOG_GAIN_CODE_MIN));
        }
+               break;
+
+       case CCS_ANALOG_GAIN_CAPABILITY_ALTERNATE_GLOBAL: {
+               struct {
+                       const char *name;
+                       u32 id;
+                       u16 min, max, step;
+               } const gain_ctrls[] = {
+                       {
+                               "Analogue Linear Gain",
+                               V4L2_CID_CCS_ANALOGUE_LINEAR_GAIN,
+                               CCS_LIM(sensor, ANALOG_LINEAR_GAIN_MIN),
+                               CCS_LIM(sensor, ANALOG_LINEAR_GAIN_MAX),
+                               max(CCS_LIM(sensor,
+                                           ANALOG_LINEAR_GAIN_STEP_SIZE),
+                                   1U),
+                       },
+                       {
+                               "Analogue Exponential Gain",
+                               V4L2_CID_CCS_ANALOGUE_EXPONENTIAL_GAIN,
+                               CCS_LIM(sensor, ANALOG_EXPONENTIAL_GAIN_MIN),
+                               CCS_LIM(sensor, ANALOG_EXPONENTIAL_GAIN_MAX),
+                               max(CCS_LIM(sensor,
+                                           ANALOG_EXPONENTIAL_GAIN_STEP_SIZE),
+                                   1U),
+                       },
+               };
+               struct v4l2_ctrl_config ctrl_cfg = {
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .ops = &ccs_ctrl_ops,
+               };
+               unsigned int i;
+
+               for (i = 0; i < ARRAY_SIZE(gain_ctrls); i++) {
+                       ctrl_cfg.name = gain_ctrls[i].name;
+                       ctrl_cfg.min = ctrl_cfg.def = gain_ctrls[i].min;
+                       ctrl_cfg.max = gain_ctrls[i].max;
+                       ctrl_cfg.step = gain_ctrls[i].step;
+                       ctrl_cfg.id = gain_ctrls[i].id;
+
+                       v4l2_ctrl_new_custom(&sensor->pixel_array->ctrl_handler,
+                                            &ctrl_cfg, NULL);
+               }
+       }
        }
 
        if (CCS_LIM(sensor, DIGITAL_GAIN_CAPABILITY) ==