From 6b3980e045bb99a8c54091eb4eca07d2ea484468 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 28 Mar 2023 14:34:42 +0300 Subject: media: ccs: Align flipping behaviour with other drivers No longer mirror flipping controls if the sensor is mounted upside down. This way the behaviour of the flipping controls and rotation of the sensor are aligned with the rest of the drivers. Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/ccs/ccs-core.c | 40 ---------------------------------------- 1 file changed, 40 deletions(-) (limited to 'drivers/media/i2c/ccs/ccs-core.c') diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 4a14d7e5d9f25..d15d492738925 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -569,8 +569,6 @@ static u32 ccs_pixel_order(struct ccs_sensor *sensor) flip |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP; } - flip ^= sensor->hvflip_inv_mask; - dev_dbg(&client->dev, "flip %u\n", flip); return sensor->default_pixel_order ^ flip; } @@ -632,8 +630,6 @@ static int ccs_set_ctrl(struct v4l2_ctrl *ctrl) if (sensor->vflip->val) orient |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP; - orient ^= sensor->hvflip_inv_mask; - ccs_update_mbus_formats(sensor); break; @@ -3185,7 +3181,6 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev) struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_UNKNOWN }; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); - u32 rotation; unsigned int i; int rval; @@ -3224,22 +3219,6 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev) goto out_err; } - rval = fwnode_property_read_u32(fwnode, "rotation", &rotation); - if (!rval) { - switch (rotation) { - case 180: - hwcfg->module_board_orient = - CCS_MODULE_BOARD_ORIENT_180; - fallthrough; - case 0: - break; - default: - dev_err(dev, "invalid rotation %u\n", rotation); - rval = -EINVAL; - goto out_err; - } - } - rval = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", &hwcfg->ext_clk); if (rval) @@ -3437,25 +3416,6 @@ static int ccs_probe(struct i2c_client *client) if (rval < 0) goto out_free_ccs_limits; - /* - * Handle Sensor Module orientation on the board. - * - * The application of H-FLIP and V-FLIP on the sensor is modified by - * the sensor orientation on the board. - * - * For CCS_BOARD_SENSOR_ORIENT_180 the default behaviour is to set - * both H-FLIP and V-FLIP for normal operation which also implies - * that a set/unset operation for user space HFLIP and VFLIP v4l2 - * controls will need to be internally inverted. - * - * Rotation also changes the bayer pattern. - */ - if (sensor->hwcfg.module_board_orient == - CCS_MODULE_BOARD_ORIENT_180) - sensor->hvflip_inv_mask = - CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR | - CCS_IMAGE_ORIENTATION_VERTICAL_FLIP; - rval = ccs_call_quirk(sensor, limits); if (rval) { dev_err(&client->dev, "limits quirks failed\n"); -- cgit v1.2.3 From c2fc1693ab3051382f62738f3289910470f3bf39 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 28 Mar 2023 14:39:26 +0300 Subject: media: ccs: Add V4L2 controls from properties Add V4L2 controls (currently CAMERA_SENSOR_ROTATION and CAMERA_SENSOR_ORIENTATION) from properties. Signed-off-by: Sakari Ailus Reviewed-by: Jacopo Mondi Signed-off-by: Hans Verkuil --- drivers/media/i2c/ccs/ccs-core.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/media/i2c/ccs/ccs-core.c') diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index d15d492738925..daee36c1f545b 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -796,14 +796,24 @@ static const struct v4l2_ctrl_ops ccs_ctrl_ops = { static int ccs_init_controls(struct ccs_sensor *sensor) { struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + struct v4l2_fwnode_device_properties props; int rval; - rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 17); + rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 19); if (rval) return rval; sensor->pixel_array->ctrl_handler.lock = &sensor->mutex; + rval = v4l2_fwnode_device_parse(&client->dev, &props); + if (rval) + return rval; + + rval = v4l2_ctrl_new_fwnode_properties(&sensor->pixel_array->ctrl_handler, + &ccs_ctrl_ops, &props); + if (rval) + return rval; + switch (CCS_LIM(sensor, ANALOG_GAIN_CAPABILITY)) { case CCS_ANALOG_GAIN_CAPABILITY_GLOBAL: { struct { -- cgit v1.2.3 From 2bef63370bbad0b356d346aad19981e08d2b7776 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 28 Mar 2023 14:11:00 +0300 Subject: media: ccs: Support 16-bit sensor revision number register Read 16-bit sensor revision number if the 8-bit register has value 0. Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/ccs/ccs-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/i2c/ccs/ccs-core.c') diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index daee36c1f545b..4adb2da340661 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -2834,6 +2834,10 @@ static int ccs_identify_module(struct ccs_sensor *sensor) rval = ccs_read_addr_8only(sensor, CCS_R_SENSOR_REVISION_NUMBER, &minfo->sensor_revision_number); + if (!rval && !minfo->sensor_revision_number) + rval = ccs_read_addr_8only(sensor, + CCS_R_SENSOR_REVISION_NUMBER_16, + &minfo->sensor_revision_number); if (!rval) rval = ccs_read_addr_8only(sensor, CCS_R_SENSOR_FIRMWARE_VERSION, @@ -2876,7 +2880,7 @@ static int ccs_identify_module(struct ccs_sensor *sensor) minfo->sensor_model_id); dev_dbg(&client->dev, - "sensor revision 0x%2.2x firmware version 0x%2.2x\n", + "sensor revision 0x%4.4x firmware version 0x%2.2x\n", minfo->sensor_revision_number, minfo->sensor_firmware_version); if (minfo->ccs_version) { -- cgit v1.2.3 From c31d11e3878e1437a33dae18f31b0ed0dca6a477 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 6 Apr 2023 19:41:03 +0300 Subject: media: ccs: Apply module manufacturer hack on non-CCS devices only Some modules don't have any model identification information in the register address space. The driver as a SMIA++ driver attempted to use sensor information in this case. This workaround is definitely not for CCS devices. Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/ccs/ccs-core.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/media/i2c/ccs/ccs-core.c') diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 4adb2da340661..20c3974f5ac76 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -2894,19 +2894,18 @@ static int ccs_identify_module(struct ccs_sensor *sensor) "smia version %2.2d smiapp version %2.2d\n", minfo->smia_version, minfo->smiapp_version); minfo->name = SMIAPP_NAME; - } - - /* - * Some modules have bad data in the lvalues below. Hope the - * rvalues have better stuff. The lvalues are module - * parameters whereas the rvalues are sensor parameters. - */ - if (minfo->sensor_smia_manufacturer_id && - !minfo->smia_manufacturer_id && !minfo->model_id) { - minfo->smia_manufacturer_id = - minfo->sensor_smia_manufacturer_id; - minfo->model_id = minfo->sensor_model_id; - minfo->revision_number = minfo->sensor_revision_number; + /* + * Some modules have bad data in the lvalues below. Hope the + * rvalues have better stuff. The lvalues are module + * parameters whereas the rvalues are sensor parameters. + */ + if (minfo->sensor_smia_manufacturer_id && + !minfo->smia_manufacturer_id && !minfo->model_id) { + minfo->smia_manufacturer_id = + minfo->sensor_smia_manufacturer_id; + minfo->model_id = minfo->sensor_model_id; + minfo->revision_number = minfo->sensor_revision_number; + } } for (i = 0; i < ARRAY_SIZE(ccs_module_idents); i++) { -- cgit v1.2.3 From 86190c53c900cbadbb45b3cd6ab92268627f9992 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 13 May 2022 16:12:54 +0300 Subject: media: ccs: Differentiate SMIA and MIPI vendors in static data MIPI CCS uses a 16-bit MIPI manufacturer identifier for firmware filenames compared to older 8-bit identifier used by SMIA. The requested firmware files used the MIPI manufacturer ID even for SMIA compliant devices, effectively making the manufacturer ID 0. While CCS static data is a feature of CCS 1.1, it has no hardware dependencies. Making this feature available for SMIA devices helps adding support for them and avoids requesting ill-generated CCS static data file names. The files are named as: ccs/smiapp-module-vv-mmmm-rrrr.fw, ccs/smiapp-sensor-vv-mmmm-rr.fw and ccs/smia-sensor-vv-mmmm-rr.fw where vv is the manufacturer ID, mmmm is the model ID and rr or rrrr is the revision number. Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/ccs/ccs-core.c | 74 +++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 19 deletions(-) (limited to 'drivers/media/i2c/ccs/ccs-core.c') diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 20c3974f5ac76..559a415fd827f 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3271,8 +3271,47 @@ out_err: return rval; } +static int ccs_firmware_name(struct i2c_client *client, + struct ccs_sensor *sensor, char *filename, + size_t filename_size, bool is_module) +{ + const struct ccs_device *ccsdev = device_get_match_data(&client->dev); + bool is_ccs = !(ccsdev->flags & CCS_DEVICE_FLAG_IS_SMIA); + bool is_smiapp = sensor->minfo.smiapp_version; + u16 manufacturer_id; + u16 model_id; + u16 revision_number; + + /* + * Old SMIA is module-agnostic. Its sensor identification is based on + * what now are those of the module. + */ + if (is_module || (!is_ccs && !is_smiapp)) { + manufacturer_id = is_ccs ? + sensor->minfo.mipi_manufacturer_id : + sensor->minfo.smia_manufacturer_id; + model_id = sensor->minfo.model_id; + revision_number = sensor->minfo.revision_number; + } else { + manufacturer_id = is_ccs ? + sensor->minfo.sensor_mipi_manufacturer_id : + sensor->minfo.sensor_smia_manufacturer_id; + model_id = sensor->minfo.sensor_model_id; + revision_number = sensor->minfo.sensor_revision_number; + } + + return snprintf(filename, filename_size, + "ccs/%s-%s-%0*x-%4.4x-%0*x.fw", + is_ccs ? "ccs" : is_smiapp ? "smiapp" : "smia", + is_module || (!is_ccs && !is_smiapp) ? + "module" : "sensor", + is_ccs ? 4 : 2, manufacturer_id, model_id, + !is_ccs && !is_module ? 2 : 4, revision_number); +} + static int ccs_probe(struct i2c_client *client) { + const struct ccs_device *ccsdev = device_get_match_data(&client->dev); struct ccs_sensor *sensor; const struct firmware *fw; char filename[40]; @@ -3381,11 +3420,8 @@ static int ccs_probe(struct i2c_client *client) goto out_power_off; } - rval = snprintf(filename, sizeof(filename), - "ccs/ccs-sensor-%4.4x-%4.4x-%4.4x.fw", - sensor->minfo.sensor_mipi_manufacturer_id, - sensor->minfo.sensor_model_id, - sensor->minfo.sensor_revision_number); + rval = ccs_firmware_name(client, sensor, filename, sizeof(filename), + false); if (rval >= sizeof(filename)) { rval = -ENOMEM; goto out_power_off; @@ -3398,21 +3434,21 @@ static int ccs_probe(struct i2c_client *client) release_firmware(fw); } - rval = snprintf(filename, sizeof(filename), - "ccs/ccs-module-%4.4x-%4.4x-%4.4x.fw", - sensor->minfo.mipi_manufacturer_id, - sensor->minfo.model_id, - sensor->minfo.revision_number); - if (rval >= sizeof(filename)) { - rval = -ENOMEM; - goto out_release_sdata; - } + if (!(ccsdev->flags & CCS_DEVICE_FLAG_IS_SMIA) || + sensor->minfo.smiapp_version) { + rval = ccs_firmware_name(client, sensor, filename, + sizeof(filename), true); + if (rval >= sizeof(filename)) { + rval = -ENOMEM; + goto out_release_sdata; + } - rval = request_firmware(&fw, filename, &client->dev); - if (!rval) { - ccs_data_parse(&sensor->mdata, fw->data, fw->size, &client->dev, - true); - release_firmware(fw); + rval = request_firmware(&fw, filename, &client->dev); + if (!rval) { + ccs_data_parse(&sensor->mdata, fw->data, fw->size, + &client->dev, true); + release_firmware(fw); + } } rval = ccs_read_all_limits(sensor); -- cgit v1.2.3