linux/drivers/media/i2c/ov5640.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright (C) 2014-2017 Mentor Graphics Inc.
 */

#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>

/* min/typical/max system clock (xclk) frequencies */
#define OV5640_XCLK_MIN
#define OV5640_XCLK_MAX

#define OV5640_NATIVE_WIDTH
#define OV5640_NATIVE_HEIGHT
#define OV5640_PIXEL_ARRAY_TOP
#define OV5640_PIXEL_ARRAY_LEFT
#define OV5640_PIXEL_ARRAY_WIDTH
#define OV5640_PIXEL_ARRAY_HEIGHT

/* FIXME: not documented. */
#define OV5640_MIN_VBLANK
#define OV5640_MAX_VTS

#define OV5640_DEFAULT_SLAVE_ID

#define OV5640_LINK_RATE_MAX

#define OV5640_REG_SYS_RESET02
#define OV5640_REG_SYS_CLOCK_ENABLE02
#define OV5640_REG_SYS_CTRL0
#define OV5640_REG_SYS_CTRL0_SW_PWDN
#define OV5640_REG_SYS_CTRL0_SW_PWUP
#define OV5640_REG_SYS_CTRL0_SW_RST
#define OV5640_REG_CHIP_ID
#define OV5640_REG_IO_MIPI_CTRL00
#define OV5640_REG_PAD_OUTPUT_ENABLE01
#define OV5640_REG_PAD_OUTPUT_ENABLE02
#define OV5640_REG_PAD_OUTPUT00
#define OV5640_REG_SYSTEM_CONTROL1
#define OV5640_REG_SC_PLL_CTRL0
#define OV5640_REG_SC_PLL_CTRL1
#define OV5640_REG_SC_PLL_CTRL2
#define OV5640_REG_SC_PLL_CTRL3
#define OV5640_REG_SLAVE_ID
#define OV5640_REG_SCCB_SYS_CTRL1
#define OV5640_REG_SYS_ROOT_DIVIDER
#define OV5640_REG_AWB_R_GAIN
#define OV5640_REG_AWB_G_GAIN
#define OV5640_REG_AWB_B_GAIN
#define OV5640_REG_AWB_MANUAL_CTRL
#define OV5640_REG_AEC_PK_EXPOSURE_HI
#define OV5640_REG_AEC_PK_EXPOSURE_MED
#define OV5640_REG_AEC_PK_EXPOSURE_LO
#define OV5640_REG_AEC_PK_MANUAL
#define OV5640_REG_AEC_PK_REAL_GAIN
#define OV5640_REG_AEC_PK_VTS
#define OV5640_REG_TIMING_HS
#define OV5640_REG_TIMING_VS
#define OV5640_REG_TIMING_HW
#define OV5640_REG_TIMING_VH
#define OV5640_REG_TIMING_DVPHO
#define OV5640_REG_TIMING_DVPVO
#define OV5640_REG_TIMING_HTS
#define OV5640_REG_TIMING_VTS
#define OV5640_REG_TIMING_HOFFS
#define OV5640_REG_TIMING_VOFFS
#define OV5640_REG_TIMING_TC_REG20
#define OV5640_REG_TIMING_TC_REG21
#define OV5640_REG_AEC_CTRL00
#define OV5640_REG_AEC_B50_STEP
#define OV5640_REG_AEC_B60_STEP
#define OV5640_REG_AEC_CTRL0D
#define OV5640_REG_AEC_CTRL0E
#define OV5640_REG_AEC_CTRL0F
#define OV5640_REG_AEC_CTRL10
#define OV5640_REG_AEC_CTRL11
#define OV5640_REG_AEC_CTRL1B
#define OV5640_REG_AEC_CTRL1E
#define OV5640_REG_AEC_CTRL1F
#define OV5640_REG_HZ5060_CTRL00
#define OV5640_REG_HZ5060_CTRL01
#define OV5640_REG_SIGMADELTA_CTRL0C
#define OV5640_REG_FRAME_CTRL01
#define OV5640_REG_FORMAT_CONTROL00
#define OV5640_REG_VFIFO_HSIZE
#define OV5640_REG_VFIFO_VSIZE
#define OV5640_REG_JPG_MODE_SELECT
#define OV5640_REG_CCIR656_CTRL00
#define OV5640_REG_POLARITY_CTRL00
#define OV5640_REG_MIPI_CTRL00
#define OV5640_REG_DEBUG_MODE
#define OV5640_REG_PCLK_PERIOD
#define OV5640_REG_ISP_FORMAT_MUX_CTRL
#define OV5640_REG_PRE_ISP_TEST_SET1
#define OV5640_REG_SDE_CTRL0
#define OV5640_REG_SDE_CTRL1
#define OV5640_REG_SDE_CTRL3
#define OV5640_REG_SDE_CTRL4
#define OV5640_REG_SDE_CTRL5
#define OV5640_REG_AVG_READOUT

enum ov5640_mode_id {};

enum ov5640_frame_rate {};

enum ov5640_pixel_rate_id {};

/*
 * The chip manual suggests 24/48/96/192 MHz pixel clocks.
 *
 * 192MHz exceeds the sysclk limits; use 168MHz as maximum pixel rate for
 * full resolution mode @15 FPS.
 */
static const u32 ov5640_pixel_rates[] =;

/*
 * MIPI CSI-2 link frequencies.
 *
 * Derived from the above defined pixel rate for bpp = (8, 16, 24) and
 * data_lanes = (1, 2)
 *
 * link_freq = (pixel_rate * bpp) / (2 * data_lanes)
 */
static const s64 ov5640_csi2_link_freqs[] =;

/* Link freq for default mode: UYVY 16 bpp, 2 data lanes. */
#define OV5640_DEFAULT_LINK_FREQ

enum ov5640_format_mux {};

struct ov5640_pixfmt {};

static const struct ov5640_pixfmt ov5640_dvp_formats[] =;

static const struct ov5640_pixfmt ov5640_csi2_formats[] =;

/*
 * FIXME: remove this when a subdev API becomes available
 * to set the MIPI CSI-2 virtual channel.
 */
static unsigned int virtual_channel;
module_param(virtual_channel, uint, 0444);
MODULE_PARM_DESC();

static const int ov5640_framerates[] =;

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

#define OV5640_NUM_SUPPLIES

/*
 * Image size under 1280 * 960 are SUBSAMPLING
 * Image size upper 1280 * 960 are SCALING
 */
enum ov5640_downsize_mode {};

struct reg_value {};

struct ov5640_timings {};

struct ov5640_mode_info {};

struct ov5640_ctrls {};

struct ov5640_dev {};

static inline struct ov5640_dev *to_ov5640_dev(struct v4l2_subdev *sd)
{}

static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
{}

static inline bool ov5640_is_csi2(const struct ov5640_dev *sensor)
{}

static inline const struct ov5640_pixfmt *
ov5640_formats(struct ov5640_dev *sensor)
{}

static const struct ov5640_pixfmt *
ov5640_code_to_pixfmt(struct ov5640_dev *sensor, u32 code)
{}

static u32 ov5640_code_to_bpp(struct ov5640_dev *sensor, u32 code)
{}

/*
 * FIXME: all of these register tables are likely filled with
 * entries that set the register to their power-on default values,
 * and which are otherwise not touched by this driver. Those entries
 * should be identified and removed to speed register load time
 * over i2c.
 */
/* YUV422 UYVY VGA@30fps */

static const struct v4l2_mbus_framefmt ov5640_csi2_default_fmt =;

static const struct v4l2_mbus_framefmt ov5640_dvp_default_fmt =;

static const struct reg_value ov5640_init_setting[] =;

static const struct reg_value ov5640_setting_low_res[] =;

static const struct reg_value ov5640_setting_720P_1280_720[] =;

static const struct reg_value ov5640_setting_1080P_1920_1080[] =;

static const struct reg_value ov5640_setting_QSXGA_2592_1944[] =;

static const struct ov5640_mode_info ov5640_mode_data[OV5640_NUM_MODES] =;

static const struct ov5640_timings *
ov5640_timings(const struct ov5640_dev *sensor,
	       const struct ov5640_mode_info *mode)
{}

static int ov5640_init_slave_id(struct ov5640_dev *sensor)
{}

static int ov5640_write_reg(struct ov5640_dev *sensor, u16 reg, u8 val)
{}

static int ov5640_read_reg(struct ov5640_dev *sensor, u16 reg, u8 *val)
{}

static int ov5640_read_reg16(struct ov5640_dev *sensor, u16 reg, u16 *val)
{}

static int ov5640_write_reg16(struct ov5640_dev *sensor, u16 reg, u16 val)
{}

static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
			  u8 mask, u8 val)
{}

/*
 * After trying the various combinations, reading various
 * documentations spread around the net, and from the various
 * feedback, the clock tree is probably as follows:
 *
 *   +--------------+
 *   |  Ext. Clock  |
 *   +-+------------+
 *     |  +----------+
 *     +->|   PLL1   | - reg 0x3036, for the multiplier
 *        +-+--------+ - reg 0x3037, bits 0-3 for the pre-divider
 *          |  +--------------+
 *          +->| System Clock |  - reg 0x3035, bits 4-7
 *             +-+------------+
 *               |  +--------------+
 *               +->| MIPI Divider | - reg 0x3035, bits 0-3
 *               |  +-+------------+
 *               |    +----------------> MIPI SCLK
 *               |    +  +-----+
 *               |    +->| / 2 |-------> MIPI BIT CLK
 *               |       +-----+
 *               |  +--------------+
 *               +->| PLL Root Div | - reg 0x3037, bit 4
 *                  +-+------------+
 *                    |  +---------+
 *                    +->| Bit Div | - reg 0x3034, bits 0-3
 *                       +-+-------+
 *                         |  +-------------+
 *                         +->| SCLK Div    | - reg 0x3108, bits 0-1
 *                         |  +-+-----------+
 *                         |    +---------------> SCLK
 *                         |  +-------------+
 *                         +->| SCLK 2X Div | - reg 0x3108, bits 2-3
 *                         |  +-+-----------+
 *                         |    +---------------> SCLK 2X
 *                         |  +-------------+
 *                         +->| PCLK Div    | - reg 0x3108, bits 4-5
 *                            ++------------+
 *                             +  +-----------+
 *                             +->|   P_DIV   | - reg 0x3035, bits 0-3
 *                                +-----+-----+
 *                                       +------------> PCLK
 *
 * There seems to be also constraints:
 *  - the PLL pre-divider output rate should be in the 4-27MHz range
 *  - the PLL multiplier output rate should be in the 500-1000MHz range
 *  - PCLK >= SCLK * 2 in YUV, >= SCLK in Raw or JPEG
 */

/*
 * This is supposed to be ranging from 1 to 8, but the value is always
 * set to 3 in the vendor kernels.
 */
#define OV5640_PLL_PREDIV

#define OV5640_PLL_MULT_MIN
#define OV5640_PLL_MULT_MAX

/*
 * This is supposed to be ranging from 1 to 16, but the value is
 * always set to either 1 or 2 in the vendor kernels.
 */
#define OV5640_SYSDIV_MIN
#define OV5640_SYSDIV_MAX

/*
 * This is supposed to be ranging from 1 to 2, but the value is always
 * set to 2 in the vendor kernels.
 */
#define OV5640_PLL_ROOT_DIV
#define OV5640_PLL_CTRL3_PLL_ROOT_DIV_2

/*
 * We only supports 8-bit formats at the moment
 */
#define OV5640_BIT_DIV
#define OV5640_PLL_CTRL0_MIPI_MODE_8BIT

/*
 * This is supposed to be ranging from 1 to 8, but the value is always
 * set to 2 in the vendor kernels.
 */
#define OV5640_SCLK_ROOT_DIV

/*
 * This is hardcoded so that the consistency is maintained between SCLK and
 * SCLK 2x.
 */
#define OV5640_SCLK2X_ROOT_DIV

/*
 * This is supposed to be ranging from 1 to 8, but the value is always
 * set to 1 in the vendor kernels.
 */
#define OV5640_PCLK_ROOT_DIV
#define OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS

static unsigned long ov5640_compute_sys_clk(struct ov5640_dev *sensor,
					    u8 pll_prediv, u8 pll_mult,
					    u8 sysdiv)
{}

static unsigned long ov5640_calc_sys_clk(struct ov5640_dev *sensor,
					 unsigned long rate,
					 u8 *pll_prediv, u8 *pll_mult,
					 u8 *sysdiv)
{}

/*
 * ov5640_set_mipi_pclk() - Calculate the clock tree configuration values
 *			    for the MIPI CSI-2 output.
 */
static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor)
{}

static u32 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
{}

static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
				      unsigned long rate,
				      u8 *pll_prediv, u8 *pll_mult, u8 *sysdiv,
				      u8 *pll_rdiv, u8 *bit_div, u8 *pclk_div)
{}

static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor)
{}

/* set JPEG framing sizes */
static int ov5640_set_jpeg_timings(struct ov5640_dev *sensor,
				   const struct ov5640_mode_info *mode)
{}

/* download ov5640 settings to sensor through i2c */
static int ov5640_set_timings(struct ov5640_dev *sensor,
			      const struct ov5640_mode_info *mode)
{}

static void ov5640_load_regs(struct ov5640_dev *sensor,
			     const struct reg_value *regs, unsigned int regnum)
{}

static int ov5640_set_autoexposure(struct ov5640_dev *sensor, bool on)
{}

/* read exposure, in number of line periods */
static int ov5640_get_exposure(struct ov5640_dev *sensor)
{}

/* write exposure, given number of line periods */
static int ov5640_set_exposure(struct ov5640_dev *sensor, u32 exposure)
{}

static int ov5640_get_gain(struct ov5640_dev *sensor)
{}

static int ov5640_set_gain(struct ov5640_dev *sensor, int gain)
{}

static int ov5640_set_autogain(struct ov5640_dev *sensor, bool on)
{}

static int ov5640_set_stream_dvp(struct ov5640_dev *sensor, bool on)
{}

static int ov5640_set_stream_mipi(struct ov5640_dev *sensor, bool on)
{}

static int ov5640_get_sysclk(struct ov5640_dev *sensor)
{}

static int ov5640_set_night_mode(struct ov5640_dev *sensor)
{}

static int ov5640_get_hts(struct ov5640_dev *sensor)
{}

static int ov5640_get_vts(struct ov5640_dev *sensor)
{}

static int ov5640_set_vts(struct ov5640_dev *sensor, int vts)
{}

static int ov5640_get_light_freq(struct ov5640_dev *sensor)
{}

static int ov5640_set_bandingfilter(struct ov5640_dev *sensor)
{}

static int ov5640_set_ae_target(struct ov5640_dev *sensor, int target)
{}

static int ov5640_get_binning(struct ov5640_dev *sensor)
{}

static int ov5640_set_binning(struct ov5640_dev *sensor, bool enable)
{}

static int ov5640_set_virtual_channel(struct ov5640_dev *sensor)
{}

static const struct ov5640_mode_info *
ov5640_find_mode(struct ov5640_dev *sensor, int width, int height, bool nearest)
{}

/*
 * sensor changes between scaling and subsampling, go through
 * exposure calculation
 */
static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor,
					 const struct ov5640_mode_info *mode)
{}

/*
 * if sensor changes inside scaling or subsampling
 * change mode directly
 */
static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
				  const struct ov5640_mode_info *mode)
{}

static int ov5640_set_mode(struct ov5640_dev *sensor)
{}

static int ov5640_set_framefmt(struct ov5640_dev *sensor,
			       struct v4l2_mbus_framefmt *format);

/* restore the last set video mode after chip power-on */
static int ov5640_restore_mode(struct ov5640_dev *sensor)
{}

static void ov5640_power(struct ov5640_dev *sensor, bool enable)
{}

/*
 * From section 2.7 power up sequence:
 * t0 + t1 + t2 >= 5ms	Delay from DOVDD stable to PWDN pull down
 * t3 >= 1ms		Delay from PWDN pull down to RESETB pull up
 * t4 >= 20ms		Delay from RESETB pull up to SCCB (i2c) stable
 *
 * Some modules don't expose RESETB/PWDN pins directly, instead providing a
 * "PWUP" GPIO which is wired through appropriate delays and inverters to the
 * pins.
 *
 * In such cases, this gpio should be mapped to pwdn_gpio in the driver, and we
 * should still toggle the pwdn_gpio below with the appropriate delays, while
 * the calls to reset_gpio will be ignored.
 */
static void ov5640_powerup_sequence(struct ov5640_dev *sensor)
{}

static int ov5640_set_power_on(struct ov5640_dev *sensor)
{}

static void ov5640_set_power_off(struct ov5640_dev *sensor)
{}

static int ov5640_set_power_mipi(struct ov5640_dev *sensor, bool on)
{}

static int ov5640_set_power_dvp(struct ov5640_dev *sensor, bool on)
{}

static int ov5640_set_power(struct ov5640_dev *sensor, bool on)
{}

static int ov5640_sensor_suspend(struct device *dev)
{}

static int ov5640_sensor_resume(struct device *dev)
{}

/* --------------- Subdev Operations --------------- */

static int ov5640_try_frame_interval(struct ov5640_dev *sensor,
				     struct v4l2_fract *fi,
				     const struct ov5640_mode_info *mode_info)
{}

static int ov5640_get_fmt(struct v4l2_subdev *sd,
			  struct v4l2_subdev_state *sd_state,
			  struct v4l2_subdev_format *format)
{}

static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
				   struct v4l2_mbus_framefmt *fmt,
				   const struct ov5640_mode_info **new_mode)
{}

static void __v4l2_ctrl_vblank_update(struct ov5640_dev *sensor, u32 vblank)
{}

static int ov5640_update_pixel_rate(struct ov5640_dev *sensor)
{}

static int ov5640_set_fmt(struct v4l2_subdev *sd,
			  struct v4l2_subdev_state *sd_state,
			  struct v4l2_subdev_format *format)
{}

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

static int ov5640_set_framefmt(struct ov5640_dev *sensor,
			       struct v4l2_mbus_framefmt *format)
{}

/*
 * Sensor Controls.
 */

static int ov5640_set_ctrl_hue(struct ov5640_dev *sensor, int value)
{}

static int ov5640_set_ctrl_contrast(struct ov5640_dev *sensor, int value)
{}

static int ov5640_set_ctrl_saturation(struct ov5640_dev *sensor, int value)
{}

static int ov5640_set_ctrl_white_balance(struct ov5640_dev *sensor, int awb)
{}

static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor,
				    enum v4l2_exposure_auto_type auto_exposure)
{}

static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, bool auto_gain)
{}

static const char * const test_pattern_menu[] =;

#define OV5640_TEST_ENABLE
#define OV5640_TEST_ROLLING
#define OV5640_TEST_TRANSPARENT
#define OV5640_TEST_SQUARE_BW
#define OV5640_TEST_BAR_STANDARD
#define OV5640_TEST_BAR_VERT_CHANGE_1
#define OV5640_TEST_BAR_HOR_CHANGE
#define OV5640_TEST_BAR_VERT_CHANGE_2
#define OV5640_TEST_BAR
#define OV5640_TEST_RANDOM
#define OV5640_TEST_SQUARE
#define OV5640_TEST_BLACK

static const u8 test_pattern_val[] =;

static int ov5640_set_ctrl_test_pattern(struct ov5640_dev *sensor, int value)
{}

static int ov5640_set_ctrl_light_freq(struct ov5640_dev *sensor, int value)
{}

static int ov5640_set_ctrl_hflip(struct ov5640_dev *sensor, int value)
{}

static int ov5640_set_ctrl_vflip(struct ov5640_dev *sensor, int value)
{}

static int ov5640_set_ctrl_vblank(struct ov5640_dev *sensor, int value)
{}

static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{}

static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
{}

static const struct v4l2_ctrl_ops ov5640_ctrl_ops =;

static int ov5640_init_controls(struct ov5640_dev *sensor)
{}

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

static int ov5640_enum_frame_interval(
	struct v4l2_subdev *sd,
	struct v4l2_subdev_state *sd_state,
	struct v4l2_subdev_frame_interval_enum *fie)
{}

static int ov5640_get_frame_interval(struct v4l2_subdev *sd,
				     struct v4l2_subdev_state *sd_state,
				     struct v4l2_subdev_frame_interval *fi)
{}

static int ov5640_set_frame_interval(struct v4l2_subdev *sd,
				     struct v4l2_subdev_state *sd_state,
				     struct v4l2_subdev_frame_interval *fi)
{}

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

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

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

static const struct v4l2_subdev_core_ops ov5640_core_ops =;

static const struct v4l2_subdev_video_ops ov5640_video_ops =;

static const struct v4l2_subdev_pad_ops ov5640_pad_ops =;

static const struct v4l2_subdev_ops ov5640_subdev_ops =;

static const struct v4l2_subdev_internal_ops ov5640_internal_ops =;

static int ov5640_get_regulators(struct ov5640_dev *sensor)
{}

static int ov5640_check_chip_id(struct ov5640_dev *sensor)
{}

static int ov5640_probe(struct i2c_client *client)
{}

static void ov5640_remove(struct i2c_client *client)
{}

static const struct dev_pm_ops ov5640_pm_ops =;

static const struct i2c_device_id ov5640_id[] =;
MODULE_DEVICE_TABLE(i2c, ov5640_id);

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

static struct i2c_driver ov5640_i2c_driver =;

module_i2c_driver();

MODULE_DESCRIPTION();
MODULE_LICENSE();