On Thu, Mar 7, 2024 at 11:41 PM Umang Jain <umang.jain@xxxxxxxxxxxxxxxx> wrote: > > From: Kieran Bingham <kieran.bingham@xxxxxxxxxxxxxxxx> > > Add a v4l2 subdevice driver for the Sony IMX283 image sensor. > > The IMX283 is a 20MP Diagonal 15.86 mm (Type 1) CMOS Image Sensor with > Square Pixel for Color Cameras. > > The following features are supported: > - Manual exposure an gain control support > - vblank/hblank/link freq control support > - Test pattern support control > - Arbitrary horizontal and vertical cropping > - Supported resolution: > - 5472x3648 @ 20fps (SRGGB12) > - 5472x3648 @ 25fps (SRGGB10) > - 2736x1824 @ 50fps (SRGGB12) ... + array_size.h + bitops.h + container_of.h > +#include <linux/clk.h> > +#include <linux/delay.h> + errno.h > +#include <linux/gpio/consumer.h> > +#include <linux/i2c.h> > +#include <linux/module.h> + mutex.h > +#include <linux/of.h> How is this being used, please? > +#include <linux/pm_runtime.h> + property.h > +#include <linux/regulator/consumer.h> + types.h > +#include <linux/units.h> ... > +#define IMX283_HMAX_MAX 0xffff I would rather use the form of (BIT(16) - 1) to imply that this is limited by bit field in the HW. ... > +#define IMX283_VMAX_MAX 0xfffff Ditto. ... > +#define IMX283_XCLR_MIN_DELAY_US 1000 > +#define IMX283_XCLR_DELAY_RANGE_US 1000 Perhaps (1 * USEC_PER_MSEC) ? ... > + /* Veritcal 2/9 subsampling, horizontal 3 binning cropping */ Vertical ... > +static const s64 link_frequencies[] = { > + 720 * MEGA, /* 1440 Mbps lane data rate */ > + 360 * MEGA, /* 720 Mbps data lane rate */ HZ_PER_MHZ > +}; ... > +/* regulator supplies */ > +static const char *const imx283_supply_name[] = { > + "vadd", /* Analog (2.9V) supply */ > + "vdd1", /* Supply Voltage 2 (1.8V) supply */ > + "vdd2", /* Supply Voltage 3 (1.2V) supply */ > +}; > + > + One blank line is enough. ... > + default: > + *mode_list = NULL; > + *num_modes = 0; break; ... > + u64 link_frequency = link_frequencies[__ffs(imx283->link_freq_bitmap)]; > + > + return link_frequency * ddr * lanes / bpp; No overflow on 32-bit? ... > +static u64 imx283_internal_clock(unsigned int pixel_rate, unsigned int pixels) > +{ > + /* > + * Determine the following operation without overflow: > + * pixels = 72 * MEGA / pixel_rate Use proper units in the comments, I believe you want MHz here. > + * The internal clock at 72MHz and Pixel Rate (between 240 and 576MHz) > + * can easily overflow this calculation, so pre-divide to simplify. > + */ > + const u32 iclk_pre = 72 * MEGA / 1000000; HZ_PER_MHZ MEGA (But why? wouldn't simply 72 be enough here?) > + const u32 pclk_pre = pixel_rate / 1000000; MEGA > + return pixels * iclk_pre / pclk_pre; > +} ... > +static u64 imx283_iclk_to_pix(unsigned int pixel_rate, unsigned int cycles) Same comments as per above function. ... > + do_div(numerator, hmax); > + numerator = clamp_t(u32, numerator, 0, 0xFFFFFFFF); Please, avoid _t variant, better to use proper types. Also the last should be U32_MAX, no? > + return numerator; return clamp(...); ... > + max_shr = min_t(u64, max_shr, 0xFFFF); No min_t() please. You probably wanted clamp() here. ... > +/* > + * Integration Time [s] = [{VMAX x (SVR + 1) – (SHR)} x HMAX + offset] > + * / (72 x 10^6) Indent better, so we can read easily. > + */ ... > + shr = (u32)(vmax * (svr + 1) - temp); > + > + return shr; Unneeded casting, simply return vmas * ...; ... > + current_exposure = clamp_t(u32, current_exposure, min_exposure, > + max_exposure); Can it be clamp()? ... > + case V4L2_CID_VBLANK: > + imx283->vmax = mode->height + ctrl->val; > + dev_dbg(imx283->dev, "V4L2_CID_VBLANK : %d VMAX : %d\n", > + ctrl->val, imx283->vmax); %d or %u? Check ALL specifiers to have proper signedness. > + ret = cci_write(imx283->cci, IMX283_REG_VMAX, imx283->vmax, NULL); > + break; ... > + usleep_range(1000, 2000); /* 1st Stabilisation period of 1 ms or more */ fsleep() ... > + /* Apply customized values from controls (HMAX/VMAX/SHR) */ > + ret = __v4l2_ctrl_handler_setup(imx283->sd.ctrl_handler); > + > + return ret; return __v4l2_ctrl_handler_setup(...); ... > + ret = cci_write(imx283->cci, IMX283_REG_STANDBY, IMX283_STBLOGIC, NULL); > + if (ret) > + dev_err(imx283->dev, "%s failed to set stream\n", __func__); Why __func__? ... > + ret = regulator_bulk_enable(ARRAY_SIZE(imx283_supply_name), > + imx283->supplies); > + if (ret) { > + dev_err(imx283->dev, "%s: failed to enable regulators\n", > + __func__); > + return ret; Ditto. > + } > + > + ret = clk_prepare_enable(imx283->xclk); > + if (ret) { > + dev_err(imx283->dev, "%s: failed to enable clock\n", > + __func__); Ditto. > + goto reg_off; > + } This Q applies to all error messages. ... > +static int __maybe_unused imx283_power_off(struct device *dev) No __maybe_unused in a new code. ... > + switch (sel->target) { > + case V4L2_SEL_TGT_CROP: { > + sel->r = *v4l2_subdev_state_get_crop(sd_state, 0); > + return 0; > + } > + > + case V4L2_SEL_TGT_NATIVE_SIZE: > + sel->r = imx283_native_area; > + return 0; > + > + case V4L2_SEL_TGT_CROP_DEFAULT: > + case V4L2_SEL_TGT_CROP_BOUNDS: > + sel->r = imx283_active_area; > + return 0; > + } > + > + return -EINVAL; Instead use default: case. ... > + mutex_lock(imx283->ctrl_handler.lock); > + mutex_unlock(imx283->ctrl_handler.lock); Can you use cleanup.h? ... > +static int imx283_parse_endpoint(struct imx283 *imx283) > +{ > + struct fwnode_handle *fwnode = dev_fwnode(imx283->dev); Split this assignment that it will be easier to understand at the first use where it came from. > + struct v4l2_fwnode_endpoint bus_cfg = { > + .bus_type = V4L2_MBUS_CSI2_DPHY > + }; > + struct fwnode_handle *ep; > + int ret; fwnode = ... > + if (!fwnode) > + return -ENXIO; > + > + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); > + if (!ep) { > + dev_err(imx283->dev, "Failed to get next endpoint\n"); > + return -ENXIO; > + } > + > + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); > + fwnode_handle_put(ep); > + if (ret) > + return ret; > + > + if (bus_cfg.bus.mipi_csi2.num_data_lanes != 4) { > + dev_err(imx283->dev, > + "number of CSI2 data lanes %d is not supported\n", > + bus_cfg.bus.mipi_csi2.num_data_lanes); > + ret = -EINVAL; > + goto done_endpoint_free; > + } > + > + ret = v4l2_link_freq_to_bitmap(imx283->dev, bus_cfg.link_frequencies, > + bus_cfg.nr_of_link_frequencies, > + link_frequencies, ARRAY_SIZE(link_frequencies), > + &imx283->link_freq_bitmap); > + > +done_endpoint_free: > + v4l2_fwnode_endpoint_free(&bus_cfg); > + > + return ret; > +}; ... > + imx283->cci = devm_cci_regmap_init_i2c(client, 16); > + if (IS_ERR(imx283->cci)) { > + ret = PTR_ERR(imx283->cci); > + dev_err(imx283->dev, "failed to initialize CCI: %d\n", ret); > + return ret; What's wrong with return dev_err_probe(...); ? > + } ... > + if (!imx283->freq) { > + dev_err(imx283->dev, "xclk frequency unsupported: %d Hz\n", xclk_freq); > + return -EINVAL; return dev_err_probe(...); > + } ... > + ret = imx283_parse_endpoint(imx283); > + if (ret) { > + dev_err(imx283->dev, "failed to parse endpoint configuration\n"); > + return ret; Ditto. Make all messages in ->probe() stage to use the same pattern. > + } ... > + /* Request optional enable pin */ > + imx283->reset_gpio = devm_gpiod_get_optional(imx283->dev, "reset", > + GPIOD_OUT_LOW); No error check?! Why? ... > + ret = media_entity_pads_init(&imx283->sd.entity, 1, &imx283->pad); > + if (ret) { > + dev_err(imx283->dev, "failed to init entity pads: %d\n", ret); dev_err_probe(...); > + goto error_handler_free; > + } > + > + imx283->sd.state_lock = imx283->ctrl_handler.lock; > + ret = v4l2_subdev_init_finalize(&imx283->sd); > + if (ret < 0) { > + dev_err(imx283->dev, "subdev init error: %d\n", ret); Ditto. > + goto error_media_entity; > + } > + > + ret = v4l2_async_register_subdev_sensor(&imx283->sd); > + if (ret < 0) { > + dev_err(imx283->dev, "failed to register sensor sub-device: %d\n", ret); Ditto. > + goto error_subdev_cleanup; > + } ... > +static const struct dev_pm_ops imx283_pm_ops = { > + SET_RUNTIME_PM_OPS(imx283_power_off, imx283_power_on, NULL) > +}; Use the respective DEFINE_* PM macro. ... > +static const struct of_device_id imx283_dt_ids[] = { > + { .compatible = "sony,imx283", }, Inner comma is not needed. > + { /* sentinel */ } > +}; > +MODULE_DEVICE_TABLE(of, imx283_dt_ids); > + > +static struct i2c_driver imx283_i2c_driver = { > + .driver = { > + .name = "imx283", > + .of_match_table = imx283_dt_ids, > + .pm = &imx283_pm_ops, Missing respective PM macro. > + }, > + .probe = imx283_probe, > + .remove = imx283_remove, > +}; > + Unneeded blank line. > +module_i2c_driver(imx283_i2c_driver); -- With Best Regards, Andy Shevchenko