linux/drivers/media/i2c/imx219.c

// SPDX-License-Identifier: GPL-2.0
/*
 * A V4L2 driver for Sony IMX219 cameras.
 * Copyright (C) 2019, Raspberry Pi (Trading) Ltd
 *
 * Based on Sony imx258 camera driver
 * Copyright (C) 2018 Intel Corporation
 *
 * DT / fwnode changes, and regulator / GPIO control taken from imx214 driver
 * Copyright 2018 Qtechnology A/S
 *
 * Flip handling taken from the Sony IMX319 driver.
 * Copyright (C) 2018 Intel Corporation
 *
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.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 IMX219_REG_CHIP_ID
#define IMX219_CHIP_ID

#define IMX219_REG_MODE_SELECT
#define IMX219_MODE_STANDBY
#define IMX219_MODE_STREAMING

#define IMX219_REG_CSI_LANE_MODE
#define IMX219_CSI_2_LANE_MODE
#define IMX219_CSI_4_LANE_MODE

#define IMX219_REG_DPHY_CTRL
#define IMX219_DPHY_CTRL_TIMING_AUTO
#define IMX219_DPHY_CTRL_TIMING_MANUAL

#define IMX219_REG_EXCK_FREQ
#define IMX219_EXCK_FREQ(n)

/* Analog gain control */
#define IMX219_REG_ANALOG_GAIN
#define IMX219_ANA_GAIN_MIN
#define IMX219_ANA_GAIN_MAX
#define IMX219_ANA_GAIN_STEP
#define IMX219_ANA_GAIN_DEFAULT

/* Digital gain control */
#define IMX219_REG_DIGITAL_GAIN
#define IMX219_DGTL_GAIN_MIN
#define IMX219_DGTL_GAIN_MAX
#define IMX219_DGTL_GAIN_DEFAULT
#define IMX219_DGTL_GAIN_STEP

/* Exposure control */
#define IMX219_REG_EXPOSURE
#define IMX219_EXPOSURE_MIN
#define IMX219_EXPOSURE_STEP
#define IMX219_EXPOSURE_DEFAULT
#define IMX219_EXPOSURE_MAX

/* V_TIMING internal */
#define IMX219_REG_VTS
#define IMX219_VTS_MAX

#define IMX219_VBLANK_MIN

/* HBLANK control - read only */
#define IMX219_PPL_DEFAULT

#define IMX219_REG_LINE_LENGTH_A
#define IMX219_REG_X_ADD_STA_A
#define IMX219_REG_X_ADD_END_A
#define IMX219_REG_Y_ADD_STA_A
#define IMX219_REG_Y_ADD_END_A
#define IMX219_REG_X_OUTPUT_SIZE
#define IMX219_REG_Y_OUTPUT_SIZE
#define IMX219_REG_X_ODD_INC_A
#define IMX219_REG_Y_ODD_INC_A
#define IMX219_REG_ORIENTATION

/* Binning  Mode */
#define IMX219_REG_BINNING_MODE_H
#define IMX219_REG_BINNING_MODE_V
#define IMX219_BINNING_NONE
#define IMX219_BINNING_X2
#define IMX219_BINNING_X2_ANALOG

#define IMX219_REG_CSI_DATA_FORMAT_A

/* PLL Settings */
#define IMX219_REG_VTPXCK_DIV
#define IMX219_REG_VTSYCK_DIV
#define IMX219_REG_PREPLLCK_VT_DIV
#define IMX219_REG_PREPLLCK_OP_DIV
#define IMX219_REG_PLL_VT_MPY
#define IMX219_REG_OPPXCK_DIV
#define IMX219_REG_OPSYCK_DIV
#define IMX219_REG_PLL_OP_MPY

/* Test Pattern Control */
#define IMX219_REG_TEST_PATTERN
#define IMX219_TEST_PATTERN_DISABLE
#define IMX219_TEST_PATTERN_SOLID_COLOR
#define IMX219_TEST_PATTERN_COLOR_BARS
#define IMX219_TEST_PATTERN_GREY_COLOR
#define IMX219_TEST_PATTERN_PN9

/* Test pattern colour components */
#define IMX219_REG_TESTP_RED
#define IMX219_REG_TESTP_GREENR
#define IMX219_REG_TESTP_BLUE
#define IMX219_REG_TESTP_GREENB
#define IMX219_TESTP_COLOUR_MIN
#define IMX219_TESTP_COLOUR_MAX
#define IMX219_TESTP_COLOUR_STEP

#define IMX219_REG_TP_WINDOW_WIDTH
#define IMX219_REG_TP_WINDOW_HEIGHT

/* External clock frequency is 24.0M */
#define IMX219_XCLK_FREQ

/* Pixel rate is fixed for all the modes */
#define IMX219_PIXEL_RATE
#define IMX219_PIXEL_RATE_4LANE

#define IMX219_DEFAULT_LINK_FREQ
#define IMX219_DEFAULT_LINK_FREQ_4LANE

/* IMX219 native and active pixel array size. */
#define IMX219_NATIVE_WIDTH
#define IMX219_NATIVE_HEIGHT
#define IMX219_PIXEL_ARRAY_LEFT
#define IMX219_PIXEL_ARRAY_TOP
#define IMX219_PIXEL_ARRAY_WIDTH
#define IMX219_PIXEL_ARRAY_HEIGHT

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

static const struct cci_reg_sequence imx219_common_regs[] =;

static const s64 imx219_link_freq_menu[] =;

static const s64 imx219_link_freq_4lane_menu[] =;

static const char * const imx219_test_pattern_menu[] =;

static const int imx219_test_pattern_val[] =;

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

#define IMX219_NUM_SUPPLIES

/*
 * The supported formats.
 * This table MUST contain 4 entries per format, to cover the various flip
 * combinations in the order
 * - no flip
 * - h flip
 * - v flip
 * - h&v flips
 */
static const u32 imx219_mbus_formats[] =;

/*
 * Initialisation delay between XCLR low->high and the moment when the sensor
 * can start capture (i.e. can leave software stanby) must be not less than:
 *   t4 + max(t5, t6 + <time to initialize the sensor register over I2C>)
 * where
 *   t4 is fixed, and is max 200uS,
 *   t5 is fixed, and is 6000uS,
 *   t6 depends on the sensor external clock, and is max 32000 clock periods.
 * As per sensor datasheet, the external clock must be from 6MHz to 27MHz.
 * So for any acceptable external clock t6 is always within the range of
 * 1185 to 5333 uS, and is always less than t5.
 * For this reason this is always safe to wait (t4 + t5) = 6200 uS, then
 * initialize the sensor over I2C, and then exit the software standby.
 *
 * This start-up time can be optimized a bit more, if we start the writes
 * over I2C after (t4+t6), but before (t4+t5) expires. But then sensor
 * initialization over I2C may complete before (t4+t5) expires, and we must
 * ensure that capture is not started before (t4+t5).
 *
 * This delay doesn't account for the power supply startup time. If needed,
 * this should be taken care of via the regulator framework. E.g. in the
 * case of DT for regulator-fixed one should define the startup-delay-us
 * property.
 */
#define IMX219_XCLR_MIN_DELAY_US
#define IMX219_XCLR_DELAY_RANGE_US

/* Mode configs */
static const struct imx219_mode supported_modes[] =;

struct imx219 {};

static inline struct imx219 *to_imx219(struct v4l2_subdev *_sd)
{}

/* Get bayer order based on flip setting. */
static u32 imx219_get_format_code(struct imx219 *imx219, u32 code)
{}

/* -----------------------------------------------------------------------------
 * Controls
 */

static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
{}

static const struct v4l2_ctrl_ops imx219_ctrl_ops =;

static unsigned long imx219_get_pixel_rate(struct imx219 *imx219)
{}

/* Initialize control handlers */
static int imx219_init_controls(struct imx219 *imx219)
{}

static void imx219_free_controls(struct imx219 *imx219)
{}

/* -----------------------------------------------------------------------------
 * Subdev operations
 */

static int imx219_set_framefmt(struct imx219 *imx219,
			       struct v4l2_subdev_state *state)
{}

static int imx219_configure_lanes(struct imx219 *imx219)
{
	return cci_write(imx219->regmap, IMX219_REG_CSI_LANE_MODE,
			 imx219->lanes == 2 ? IMX219_CSI_2_LANE_MODE :
			 IMX219_CSI_4_LANE_MODE, NULL);
};

static int imx219_start_streaming(struct imx219 *imx219,
				  struct v4l2_subdev_state *state)
{}

static void imx219_stop_streaming(struct imx219 *imx219)
{}

static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
{}

static void imx219_update_pad_format(struct imx219 *imx219,
				     const struct imx219_mode *mode,
				     struct v4l2_mbus_framefmt *fmt, u32 code)
{}

static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
				 struct v4l2_subdev_state *state,
				 struct v4l2_subdev_mbus_code_enum *code)
{}

static int imx219_enum_frame_size(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *state,
				  struct v4l2_subdev_frame_size_enum *fse)
{}

static int imx219_set_pad_format(struct v4l2_subdev *sd,
				 struct v4l2_subdev_state *state,
				 struct v4l2_subdev_format *fmt)
{}

static int imx219_get_selection(struct v4l2_subdev *sd,
				struct v4l2_subdev_state *state,
				struct v4l2_subdev_selection *sel)
{}

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

static const struct v4l2_subdev_core_ops imx219_core_ops =;

static const struct v4l2_subdev_video_ops imx219_video_ops =;

static const struct v4l2_subdev_pad_ops imx219_pad_ops =;

static const struct v4l2_subdev_ops imx219_subdev_ops =;

static const struct v4l2_subdev_internal_ops imx219_internal_ops =;

/* -----------------------------------------------------------------------------
 * Power management
 */

static int imx219_power_on(struct device *dev)
{}

static int imx219_power_off(struct device *dev)
{}

/* -----------------------------------------------------------------------------
 * Probe & remove
 */

static int imx219_get_regulators(struct imx219 *imx219)
{}

/* Verify chip ID */
static int imx219_identify_module(struct imx219 *imx219)
{}

static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219)
{}

static int imx219_probe(struct i2c_client *client)
{}

static void imx219_remove(struct i2c_client *client)
{}

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

static const struct dev_pm_ops imx219_pm_ops =;

static struct i2c_driver imx219_i2c_driver =;

module_i2c_driver();

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