linux/drivers/media/i2c/imx283.c

// SPDX-License-Identifier: GPL-2.0
/*
 * V4L2 Support for the IMX283
 *
 * Diagonal 15.86 mm (Type 1) CMOS Image Sensor with Square Pixel for Color
 * Cameras.
 *
 * Copyright (C) 2024 Ideas on Board Oy.
 *
 * Based on Sony IMX283 driver prepared by Will Whang
 *
 * Based on Sony imx477 camera driver
 * Copyright (C) 2019-2020 Raspberry Pi (Trading) Ltd
 */

#include <linux/array_size.h>
#include <linux/bitops.h>
#include <linux/container_of.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/types.h>
#include <linux/units.h>
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h>

/* Chip ID */
#define IMX283_REG_CHIP_ID
#define IMX283_CHIP_ID

#define IMX283_REG_STANDBY
#define IMX283_ACTIVE
#define IMX283_STANDBY
#define IMX283_STBLOGIC
#define IMX283_STBMIPI
#define IMX283_STBDV
#define IMX283_SLEEP

#define IMX283_REG_CLAMP
#define IMX283_CLPSQRST

#define IMX283_REG_PLSTMG08
#define IMX283_PLSTMG08_VAL

#define IMX283_REG_MDSEL1
#define IMX283_REG_MDSEL2
#define IMX283_REG_MDSEL3
#define IMX283_MDSEL3_VCROP_EN
#define IMX283_REG_MDSEL4
#define IMX283_MDSEL4_VCROP_EN

#define IMX283_REG_SVR

#define IMX283_REG_HTRIMMING
#define IMX283_MDVREV
#define IMX283_HTRIMMING_EN

#define IMX283_REG_VWINPOS
#define IMX283_REG_VWIDCUT

#define IMX283_REG_MDSEL7

/* CSI Clock Configuration */
#define IMX283_REG_TCLKPOST
#define IMX283_REG_THSPREPARE
#define IMX283_REG_THSZERO
#define IMX283_REG_THSTRAIL
#define IMX283_REG_TCLKTRAIL
#define IMX283_REG_TCLKPREPARE
#define IMX283_REG_TCLKZERO
#define IMX283_REG_TLPX
#define IMX283_REG_THSEXIT
#define IMX283_REG_TCLKPRE
#define IMX283_REG_SYSMODE

#define IMX283_REG_Y_OUT_SIZE
#define IMX283_REG_WRITE_VSIZE
#define IMX283_REG_OB_SIZE_V

/* HMAX internal HBLANK */
#define IMX283_REG_HMAX
#define IMX283_HMAX_MAX

/* VMAX internal VBLANK */
#define IMX283_REG_VMAX
#define IMX283_VMAX_MAX

/* SHR internal */
#define IMX283_REG_SHR
#define IMX283_SHR_MIN

/*
 * Analog gain control
 *  Gain [dB] = -20log{(2048 - value [10:0]) /2048}
 *  Range: 0dB to approximately +27dB
 */
#define IMX283_REG_ANALOG_GAIN
#define IMX283_ANA_GAIN_MIN
#define IMX283_ANA_GAIN_MAX
#define IMX283_ANA_GAIN_STEP
#define IMX283_ANA_GAIN_DEFAULT

/*
 * Digital gain control
 *  Gain [dB] = value * 6
 *  Range: 0dB to +18db
 */
#define IMX283_REG_DIGITAL_GAIN
#define IMX283_DGTL_GAIN_MIN
#define IMX283_DGTL_GAIN_MAX
#define IMX283_DGTL_GAIN_DEFAULT
#define IMX283_DGTL_GAIN_STEP

#define IMX283_REG_HTRIMMING_START
#define IMX283_REG_HTRIMMING_END

#define IMX283_REG_MDSEL18

/* Master Mode Operation Control */
#define IMX283_REG_XMSTA
#define IMX283_XMSTA

#define IMX283_REG_SYNCDRV
#define IMX283_SYNCDRV_XHS_XVS
#define IMX283_SYNCDRV_HIZ

/* PLL Standby */
#define IMX283_REG_STBPL
#define IMX283_STBPL_NORMAL
#define IMX283_STBPL_STANDBY

/* Input Frequency Setting */
#define IMX283_REG_PLRD1
#define IMX283_REG_PLRD2
#define IMX283_REG_PLRD3
#define IMX283_REG_PLRD4

#define IMX283_REG_PLSTMG02
#define IMX283_PLSTMG02_VAL

#define IMX283_REG_EBD_X_OUT_SIZE

/* Test pattern generator */
#define IMX283_REG_TPG_CTRL
#define IMX283_TPG_CTRL_CLKEN
#define IMX283_TPG_CTRL_PATEN

#define IMX283_REG_TPG_PAT
#define IMX283_TPG_PAT_ALL_000
#define IMX283_TPG_PAT_ALL_FFF
#define IMX283_TPG_PAT_ALL_555
#define IMX283_TPG_PAT_ALL_AAA
#define IMX283_TPG_PAT_H_COLOR_BARS
#define IMX283_TPG_PAT_V_COLOR_BARS

/* Exposure control */
#define IMX283_EXPOSURE_MIN
#define IMX283_EXPOSURE_STEP
#define IMX283_EXPOSURE_DEFAULT
#define IMX283_EXPOSURE_MAX

#define IMAGE_PAD

#define IMX283_XCLR_MIN_DELAY_US
#define IMX283_XCLR_DELAY_RANGE_US

/* IMX283 native and active pixel array size. */
static const struct v4l2_rect imx283_native_area =;

static const struct v4l2_rect imx283_active_area =;

struct imx283_reg_list {};

/* Mode : resolution and related config values */
struct imx283_mode {};

struct imx283_input_frequency {};

static const struct imx283_input_frequency imx283_frequencies[] =;

enum imx283_modes {};

struct imx283_readout_mode {};

static const struct imx283_readout_mode imx283_readout_modes[] =;

static const struct cci_reg_sequence mipi_data_rate_1440Mbps[] =;

static const struct cci_reg_sequence mipi_data_rate_720Mbps[] =;

static const s64 link_frequencies[] =;

static const struct imx283_reg_list link_freq_reglist[] =;

/* Mode configs */
static const struct imx283_mode supported_modes_12bit[] =;

static const struct imx283_mode supported_modes_10bit[] =;

static const u32 imx283_mbus_codes[] =;

/* regulator supplies */
static const char *const imx283_supply_name[] =;

struct imx283 {};

static inline struct imx283 *to_imx283(struct v4l2_subdev *sd)
{}

static inline void get_mode_table(unsigned int code,
				  const struct imx283_mode **mode_list,
				  unsigned int *num_modes)
{}

/* Calculate the Pixel Rate based on the current mode */
static u64 imx283_pixel_rate(struct imx283 *imx283,
			     const struct imx283_mode *mode)
{}

/* Convert from a variable pixel_rate to 72 MHz clock cycles */
static u64 imx283_internal_clock(unsigned int pixel_rate, unsigned int pixels)
{}

/* Internal clock (72MHz) to Pixel Rate clock (Variable) */
static u64 imx283_iclk_to_pix(unsigned int pixel_rate, unsigned int cycles)
{}

/* Determine the exposure based on current hmax, vmax and a given SHR */
static u32 imx283_exposure(struct imx283 *imx283,
			   const struct imx283_mode *mode, u64 shr)
{}

static void imx283_exposure_limits(struct imx283 *imx283,
				   const struct imx283_mode *mode,
				   s64 *min_exposure, s64 *max_exposure)
{}

/*
 * Integration Time [s] = [ {VMAX x (SVR + 1) – (SHR)} x HMAX + offset ]
 *                      / [ 72 x 10^6 ]
 */
static u32 imx283_shr(struct imx283 *imx283, const struct imx283_mode *mode,
		      u32 exposure)
{}

static const char * const imx283_tpg_menu[] =;

static const int imx283_tpg_val[] =;

static int imx283_update_test_pattern(struct imx283 *imx283, u32 pattern_index)
{}

static int imx283_set_ctrl(struct v4l2_ctrl *ctrl)
{}

static const struct v4l2_ctrl_ops imx283_ctrl_ops =;

static int imx283_enum_mbus_code(struct v4l2_subdev *sd,
				 struct v4l2_subdev_state *sd_state,
				 struct v4l2_subdev_mbus_code_enum *code)
{}

static int imx283_enum_frame_size(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *sd_state,
				  struct v4l2_subdev_frame_size_enum *fse)
{}

static void imx283_update_image_pad_format(struct imx283 *imx283,
					   const struct imx283_mode *mode,
					   struct v4l2_mbus_framefmt *format)
{}

static int imx283_init_state(struct v4l2_subdev *sd,
			     struct v4l2_subdev_state *state)
{}

static void imx283_set_framing_limits(struct imx283 *imx283,
				      const struct imx283_mode *mode)
{}

static int imx283_set_pad_format(struct v4l2_subdev *sd,
				 struct v4l2_subdev_state *sd_state,
				 struct v4l2_subdev_format *fmt)
{}

static int imx283_standby_cancel(struct imx283 *imx283)
{}

/* Start streaming */
static int imx283_start_streaming(struct imx283 *imx283,
				  struct v4l2_subdev_state *state)
{}

static int imx283_enable_streams(struct v4l2_subdev *sd,
				 struct v4l2_subdev_state *state, u32 pad,
				 u64 streams_mask)
{}

static int imx283_disable_streams(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *state, u32 pad,
				  u64 streams_mask)
{}

/* Power/clock management functions */
static int imx283_power_on(struct imx283 *imx283)
{}

static int imx283_power_off(struct imx283 *imx283)
{}

static int imx283_runtime_resume(struct device *dev)
{}

static int imx283_runtime_suspend(struct device *dev)
{}

static int imx283_get_regulators(struct imx283 *imx283)
{}

/* Verify chip ID */
static int imx283_identify_module(struct imx283 *imx283)
{}

static int imx283_get_selection(struct v4l2_subdev *sd,
				struct v4l2_subdev_state *sd_state,
				struct v4l2_subdev_selection *sel)
{}

static const struct v4l2_subdev_core_ops imx283_core_ops =;

static const struct v4l2_subdev_video_ops imx283_video_ops =;

static const struct v4l2_subdev_pad_ops imx283_pad_ops =;

static const struct v4l2_subdev_internal_ops imx283_internal_ops =;

static const struct v4l2_subdev_ops imx283_subdev_ops =;

/* Initialize control handlers */
static int imx283_init_controls(struct imx283 *imx283)
{}

static int imx283_parse_endpoint(struct imx283 *imx283)
{
	struct fwnode_handle *fwnode;
	struct v4l2_fwnode_endpoint bus_cfg = {
		.bus_type = V4L2_MBUS_CSI2_DPHY
	};
	struct fwnode_handle *ep;
	int ret;

	fwnode = dev_fwnode(imx283->dev);
	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;
};

static int imx283_probe(struct i2c_client *client)
{}

static void imx283_remove(struct i2c_client *client)
{}

static DEFINE_RUNTIME_DEV_PM_OPS(imx283_pm_ops, imx283_runtime_suspend,
				 imx283_runtime_resume, NULL);

static const struct of_device_id imx283_dt_ids[] =;
MODULE_DEVICE_TABLE(of, imx283_dt_ids);

static struct i2c_driver imx283_i2c_driver =;
module_i2c_driver();

MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();