diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-01-12 14:29:48 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-01-12 14:29:48 -0800 |
commit | 61da593f4458f25c59f65cfd9ba1bda570db5db7 (patch) | |
tree | 42196179375dfda07901577e080f979b2897d308 /drivers/media/i2c/ccs/ccs-core.c | |
parent | a3cc31e75185f9b1ad8dc45eac77f8de788dc410 (diff) | |
parent | 60a031b64984ad4a219a13b0fe912746b586bb9b (diff) |
Merge tag 'media/v6.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- v4l core: subdev frame interval now supports which field
- v4l kapi: moves and renames the init_cfg pad op to init_state as an
internal op.
- new sensor drivers: gc0308, gc2145, Avnet Alvium, ov64a40, tw9900
- new camera driver: STM32 DCMIPP
- s5p-mfc has gained MFC v12 support
- new ISP driver added to staging: Starfive
- new stateful encoder/decoded: Wave5 codec It is found on the J721S2
SoC, JH7100 SoC, ssd202d SoC. Etc.
- fwnode gained support for MIPI "DisCo for Imaging"
(https://www.mipi.org/specifications/mipi-disco-imaging)
- as usual, lots of cleanups, fixups and driver improvements.
* tag 'media/v6.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (309 commits)
media: i2c: thp7312: select CONFIG_FW_LOADER
media: i2c: mt9m114: use fsleep() in place of udelay()
media: videobuf2: core: Rename min_buffers_needed field in vb2_queue
media: i2c: thp7312: Store frame interval in subdev state
media: docs: uAPI: Fix documentation of 'which' field for routing ioctls
media: docs: uAPI: Expand error documentation for invalid 'which' value
media: docs: uAPI: Clarify error documentation for invalid 'which' value
media: v4l2-subdev: Store frame interval in subdev state
media: v4l2-subdev: Add which field to struct v4l2_subdev_frame_interval
media: v4l2-subdev: Turn .[gs]_frame_interval into pad operations
media: v4l: subdev: Move out subdev state lock macros outside CONFIG_MEDIA_CONTROLLER
media: s5p-mfc: DPB Count Independent of VIDIOC_REQBUF
media: s5p-mfc: Load firmware for each run in MFCv12.
media: s5p-mfc: Set context for valid case before calling try_run
media: s5p-mfc: Add support for DMABUF for encoder
media: s5p-mfc: Add support for UHD encoding.
media: s5p-mfc: Add support for rate controls in MFCv12
media: s5p-mfc: Add YV12 and I420 multiplanar format support
media: s5p-mfc: Add initial support for MFCv12
media: s5p-mfc: Rename IS_MFCV10 macro
...
Diffstat (limited to 'drivers/media/i2c/ccs/ccs-core.c')
-rw-r--r-- | drivers/media/i2c/ccs/ccs-core.c | 134 |
1 files changed, 73 insertions, 61 deletions
diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 12e6f0a26fc8..e21287d50c15 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -25,8 +25,9 @@ #include <linux/slab.h> #include <linux/smiapp.h> #include <linux/v4l2-mediabus.h> -#include <media/v4l2-fwnode.h> +#include <media/v4l2-cci.h> #include <media/v4l2-device.h> +#include <media/v4l2-fwnode.h> #include <uapi/linux/ccs.h> #include "ccs.h" @@ -98,7 +99,7 @@ static int ccs_limit_ptr(struct ccs_sensor *sensor, unsigned int limit, linfo = &ccs_limits[ccs_limit_offsets[limit].info]; if (WARN_ON(!sensor->ccs_limits) || - WARN_ON(offset + ccs_reg_width(linfo->reg) > + WARN_ON(offset + CCI_REG_WIDTH_BYTES(linfo->reg) > ccs_limit_offsets[limit + 1].lim)) return -EINVAL; @@ -124,7 +125,7 @@ void ccs_replace_limit(struct ccs_sensor *sensor, dev_dbg(&client->dev, "quirk: 0x%8.8x \"%s\" %u = %u, 0x%x\n", linfo->reg, linfo->name, offset, val, val); - ccs_assign_limit(ptr, ccs_reg_width(linfo->reg), val); + ccs_assign_limit(ptr, CCI_REG_WIDTH_BYTES(linfo->reg), val); } u32 ccs_get_limit(struct ccs_sensor *sensor, unsigned int limit, @@ -138,7 +139,7 @@ u32 ccs_get_limit(struct ccs_sensor *sensor, unsigned int limit, if (ret) return 0; - switch (ccs_reg_width(ccs_limits[ccs_limit_offsets[limit].info].reg)) { + switch (CCI_REG_WIDTH_BYTES(ccs_limits[ccs_limit_offsets[limit].info].reg)) { case sizeof(u8): val = *(u8 *)ptr; break; @@ -172,9 +173,11 @@ static int ccs_read_all_limits(struct ccs_sensor *sensor) end = alloc + ccs_limit_offsets[CCS_L_LAST].lim; + sensor->ccs_limits = alloc; + for (i = 0, l = 0, ptr = alloc; ccs_limits[i].size; i++) { u32 reg = ccs_limits[i].reg; - unsigned int width = ccs_reg_width(reg); + unsigned int width = CCI_REG_WIDTH_BYTES(reg); unsigned int j; if (l == CCS_L_LAST) { @@ -186,6 +189,7 @@ static int ccs_read_all_limits(struct ccs_sensor *sensor) for (j = 0; j < ccs_limits[i].size / width; j++, reg += width, ptr += width) { + char str[16] = ""; u32 val; ret = ccs_read_addr_noconv(sensor, reg, &val); @@ -204,8 +208,15 @@ static int ccs_read_all_limits(struct ccs_sensor *sensor) ccs_assign_limit(ptr, width, val); - dev_dbg(&client->dev, "0x%8.8x \"%s\" = %u, 0x%x\n", - reg, ccs_limits[i].name, val, val); +#ifdef CONFIG_DYNAMIC_DEBUG + if (reg & (CCS_FL_FLOAT_IREAL | CCS_FL_IREAL)) + snprintf(str, sizeof(str), ", %u", + ccs_reg_conv(sensor, reg, val)); +#endif + + dev_dbg(&client->dev, + "0x%8.8x \"%s\" = %u, 0x%x%s\n", + reg, ccs_limits[i].name, val, val, str); } if (ccs_limits[i].flags & CCS_L_FL_SAME_REG) @@ -222,14 +233,13 @@ static int ccs_read_all_limits(struct ccs_sensor *sensor) goto out_err; } - sensor->ccs_limits = alloc; - if (CCS_LIM(sensor, SCALER_N_MIN) < 16) ccs_replace_limit(sensor, CCS_L_SCALER_N_MIN, 0, 16); return 0; out_err: + sensor->ccs_limits = NULL; kfree(alloc); return ret; @@ -1878,9 +1888,11 @@ static int ccs_pm_get_init(struct ccs_sensor *sensor) goto error; /* Device was already active, so don't set controls */ - if (rval == 1) + if (rval == 1 && !sensor->handler_setup_needed) return 0; + sensor->handler_setup_needed = false; + /* Restore V4L2 controls to the previously suspended device */ rval = v4l2_ctrl_handler_setup(&sensor->pixel_array->ctrl_handler); if (rval) @@ -2030,7 +2042,7 @@ static int __ccs_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *fmt) { - fmt->format = *v4l2_subdev_get_pad_format(subdev, sd_state, fmt->pad); + fmt->format = *v4l2_subdev_state_get_format(sd_state, fmt->pad); fmt->format.code = __ccs_get_mbus_code(subdev, fmt->pad); return 0; @@ -2061,10 +2073,10 @@ static void ccs_get_crop_compose(struct v4l2_subdev *subdev, if (crops) for (i = 0; i < subdev->entity.num_pads; i++) crops[i] = - v4l2_subdev_get_pad_crop(subdev, sd_state, i); + v4l2_subdev_state_get_crop(sd_state, i); if (comps) - *comps = v4l2_subdev_get_pad_compose(subdev, sd_state, - ssd->sink_pad); + *comps = v4l2_subdev_state_get_compose(sd_state, + ssd->sink_pad); } /* Changes require propagation only on sink pad. */ @@ -2097,7 +2109,7 @@ static void ccs_propagate(struct v4l2_subdev *subdev, fallthrough; case V4L2_SEL_TGT_COMPOSE: *crops[CCS_PAD_SRC] = *comp; - fmt = v4l2_subdev_get_pad_format(subdev, sd_state, CCS_PAD_SRC); + fmt = v4l2_subdev_state_get_format(sd_state, CCS_PAD_SRC); fmt->width = comp->width; fmt->height = comp->height; if (which == V4L2_SUBDEV_FORMAT_ACTIVE && ssd == sensor->src) @@ -2507,7 +2519,7 @@ static int ccs_set_crop(struct v4l2_subdev *subdev, if (sel->pad == ssd->sink_pad) { struct v4l2_mbus_framefmt *mfmt = - v4l2_subdev_get_pad_format(subdev, sd_state, sel->pad); + v4l2_subdev_state_get_format(sd_state, sel->pad); src_size.width = mfmt->width; src_size.height = mfmt->height; @@ -2567,8 +2579,8 @@ static int ccs_get_selection(struct v4l2_subdev *subdev, ccs_get_native_size(ssd, &sel->r); } else if (sel->pad == ssd->sink_pad) { struct v4l2_mbus_framefmt *sink_fmt = - v4l2_subdev_get_pad_format(subdev, sd_state, - ssd->sink_pad); + v4l2_subdev_state_get_format(sd_state, + ssd->sink_pad); sel->r.top = sel->r.left = 0; sel->r.width = sink_fmt->width; sel->r.height = sink_fmt->height; @@ -2714,66 +2726,54 @@ static int ccs_identify_module(struct ccs_sensor *sensor) rval = ccs_read(sensor, MODULE_MANUFACTURER_ID, &minfo->mipi_manufacturer_id); if (!rval && !minfo->mipi_manufacturer_id) - rval = ccs_read_addr_8only(sensor, - SMIAPP_REG_U8_MANUFACTURER_ID, - &minfo->smia_manufacturer_id); + rval = ccs_read_addr(sensor, SMIAPP_REG_U8_MANUFACTURER_ID, + &minfo->smia_manufacturer_id); if (!rval) - rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_MODEL_ID, - &minfo->model_id); + rval = ccs_read(sensor, MODULE_MODEL_ID, &minfo->model_id); if (!rval) - rval = ccs_read_addr_8only(sensor, - CCS_R_MODULE_REVISION_NUMBER_MAJOR, - &rev); + rval = ccs_read(sensor, MODULE_REVISION_NUMBER_MAJOR, &rev); if (!rval) { - rval = ccs_read_addr_8only(sensor, - CCS_R_MODULE_REVISION_NUMBER_MINOR, - &minfo->revision_number); + rval = ccs_read(sensor, MODULE_REVISION_NUMBER_MINOR, + &minfo->revision_number); minfo->revision_number |= rev << 8; } if (!rval) - rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_YEAR, - &minfo->module_year); + rval = ccs_read(sensor, MODULE_DATE_YEAR, &minfo->module_year); if (!rval) - rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_MONTH, - &minfo->module_month); + rval = ccs_read(sensor, MODULE_DATE_MONTH, + &minfo->module_month); if (!rval) - rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_DAY, - &minfo->module_day); + rval = ccs_read(sensor, MODULE_DATE_DAY, &minfo->module_day); /* Sensor info */ if (!rval) rval = ccs_read(sensor, SENSOR_MANUFACTURER_ID, &minfo->sensor_mipi_manufacturer_id); if (!rval && !minfo->sensor_mipi_manufacturer_id) - rval = ccs_read_addr_8only(sensor, - CCS_R_SENSOR_MANUFACTURER_ID, - &minfo->sensor_smia_manufacturer_id); + rval = ccs_read(sensor, SENSOR_MANUFACTURER_ID, + &minfo->sensor_smia_manufacturer_id); if (!rval) - rval = ccs_read_addr_8only(sensor, - CCS_R_SENSOR_MODEL_ID, - &minfo->sensor_model_id); + rval = ccs_read(sensor, SENSOR_MODEL_ID, + &minfo->sensor_model_id); if (!rval) - rval = ccs_read_addr_8only(sensor, - CCS_R_SENSOR_REVISION_NUMBER, - &minfo->sensor_revision_number); + rval = ccs_read(sensor, 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); + rval = ccs_read(sensor, SENSOR_REVISION_NUMBER_16, + &minfo->sensor_revision_number); if (!rval) - rval = ccs_read_addr_8only(sensor, - CCS_R_SENSOR_FIRMWARE_VERSION, - &minfo->sensor_firmware_version); + rval = ccs_read(sensor, SENSOR_FIRMWARE_VERSION, + &minfo->sensor_firmware_version); /* SMIA */ if (!rval) rval = ccs_read(sensor, MIPI_CCS_VERSION, &minfo->ccs_version); if (!rval && !minfo->ccs_version) - rval = ccs_read_addr_8only(sensor, SMIAPP_REG_U8_SMIA_VERSION, - &minfo->smia_version); + rval = ccs_read_addr(sensor, SMIAPP_REG_U8_SMIA_VERSION, + &minfo->smia_version); if (!rval && !minfo->ccs_version) - rval = ccs_read_addr_8only(sensor, SMIAPP_REG_U8_SMIAPP_VERSION, - &minfo->smiapp_version); + rval = ccs_read_addr(sensor, SMIAPP_REG_U8_SMIAPP_VERSION, + &minfo->smiapp_version); if (rval) { dev_err(&client->dev, "sensor detection failed\n"); @@ -3004,17 +3004,17 @@ static int ccs_init_subdev(struct ccs_sensor *sensor, return 0; } -static int ccs_init_cfg(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state) +static int ccs_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state) { struct ccs_subdev *ssd = to_ccs_subdev(sd); struct ccs_sensor *sensor = ssd->sensor; unsigned int pad = ssd == sensor->pixel_array ? CCS_PA_PAD_SRC : CCS_PAD_SINK; struct v4l2_mbus_framefmt *fmt = - v4l2_subdev_get_pad_format(sd, sd_state, pad); + v4l2_subdev_state_get_format(sd_state, pad); struct v4l2_rect *crop = - v4l2_subdev_get_pad_crop(sd, sd_state, pad); + v4l2_subdev_state_get_crop(sd_state, pad); bool is_active = !sd->active_state || sd->active_state == sd_state; mutex_lock(&sensor->mutex); @@ -3034,7 +3034,7 @@ static int ccs_init_cfg(struct v4l2_subdev *sd, return 0; } - fmt = v4l2_subdev_get_pad_format(sd, sd_state, CCS_PAD_SRC); + fmt = v4l2_subdev_state_get_format(sd_state, CCS_PAD_SRC); fmt->code = ssd == sensor->src ? sensor->csi_format->code : sensor->internal_csi_format->code; fmt->field = V4L2_FIELD_NONE; @@ -3053,7 +3053,6 @@ static const struct v4l2_subdev_video_ops ccs_video_ops = { }; static const struct v4l2_subdev_pad_ops ccs_pad_ops = { - .init_cfg = ccs_init_cfg, .enum_mbus_code = ccs_enum_mbus_code, .get_fmt = ccs_get_format, .set_fmt = ccs_set_format, @@ -3077,6 +3076,7 @@ static const struct media_entity_operations ccs_entity_ops = { }; static const struct v4l2_subdev_internal_ops ccs_internal_src_ops = { + .init_state = ccs_init_state, .registered = ccs_registered, .unregistered = ccs_unregistered, }; @@ -3307,6 +3307,13 @@ static int ccs_probe(struct i2c_client *client) if (IS_ERR(sensor->xshutdown)) return PTR_ERR(sensor->xshutdown); + sensor->regmap = devm_cci_regmap_init_i2c(client, 16); + if (IS_ERR(sensor->regmap)) { + dev_err(&client->dev, "can't initialise CCI (%ld)\n", + PTR_ERR(sensor->regmap)); + return PTR_ERR(sensor->regmap); + } + rval = ccs_power_on(&client->dev); if (rval < 0) return rval; @@ -3532,6 +3539,7 @@ static int ccs_probe(struct i2c_client *client) sensor->streaming = false; sensor->dev_init_done = true; + sensor->handler_setup_needed = true; rval = ccs_write_msr_regs(sensor); if (rval) @@ -3636,12 +3644,16 @@ static int ccs_module_init(void) { unsigned int i, l; + CCS_BUILD_BUG; + for (i = 0, l = 0; ccs_limits[i].size && l < CCS_L_LAST; i++) { if (!(ccs_limits[i].flags & CCS_L_FL_SAME_REG)) { ccs_limit_offsets[l + 1].lim = ALIGN(ccs_limit_offsets[l].lim + ccs_limits[i].size, - ccs_reg_width(ccs_limits[i + 1].reg)); + ccs_limits[i + 1].reg ? + CCI_REG_WIDTH_BYTES(ccs_limits[i + 1].reg) : + 1U); ccs_limit_offsets[l].info = i; l++; } else { |