// SPDX-License-Identifier: GPL-2.0
/*
* ov5695 driver
*
* Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
*/
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/sysfs.h>
#include <media/media-entity.h>
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#ifndef V4L2_CID_DIGITAL_GAIN
#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
#endif
/* 45Mhz * 4 Binning */
#define OV5695_PIXEL_RATE (45 * 1000 * 1000 * 4)
#define OV5695_XVCLK_FREQ 24000000
#define CHIP_ID 0x005695
#define OV5695_REG_CHIP_ID 0x300a
#define OV5695_REG_CTRL_MODE 0x0100
#define OV5695_MODE_SW_STANDBY 0x0
#define OV5695_MODE_STREAMING BIT(0)
#define OV5695_REG_EXPOSURE 0x3500
#define OV5695_EXPOSURE_MIN 4
#define OV5695_EXPOSURE_STEP 1
#define OV5695_VTS_MAX 0x7fff
#define OV5695_REG_ANALOG_GAIN 0x3509
#define ANALOG_GAIN_MIN 0x10
#define ANALOG_GAIN_MAX 0xf8
#define ANALOG_GAIN_STEP 1
#define ANALOG_GAIN_DEFAULT 0xf8
#define OV5695_REG_DIGI_GAIN_H 0x350a
#define OV5695_REG_DIGI_GAIN_L 0x350b
#define OV5695_DIGI_GAIN_L_MASK 0x3f
#define OV5695_DIGI_GAIN_H_SHIFT 6
#define OV5695_DIGI_GAIN_MIN 0
#define OV5695_DIGI_GAIN_MAX (0x4000 - 1)
#define OV5695_DIGI_GAIN_STEP 1
#define OV5695_DIGI_GAIN_DEFAULT 1024
#define OV5695_REG_TEST_PATTERN 0x4503
#define OV5695_TEST_PATTERN_ENABLE 0x80
#define OV5695_TEST_PATTERN_DISABLE 0x0
#define OV5695_REG_VTS 0x380e
#define REG_NULL 0xFFFF
#define OV5695_REG_VALUE_08BIT 1
#define OV5695_REG_VALUE_16BIT 2
#define OV5695_REG_VALUE_24BIT 3
#define OV5695_LANES 2
#define OV5695_BITS_PER_SAMPLE 10
static const char * const ov5695_supply_names[] = {
"avdd", /* Analog power */
"dovdd", /* Digital I/O power */
"dvdd", /* Digital core power */
};
#define OV5695_NUM_SUPPLIES ARRAY_SIZE(ov5695_supply_names)
struct regval {
u16 addr;
u8 val;
};
struct ov5695_mode {
u32 width;
u32 height;
u32 max_fps;
u32 hts_def;
u32 vts_def;
u32 exp_def;
const struct regval *reg_list;
};
struct ov5695 {
struct i2c_client *client;
struct clk *xvclk;
struct gpio_desc *reset_gpio;
struct regulator_bulk_data supplies[OV5695_NUM_SUPPLIES];
struct v4l2_subdev subdev;
struct media_pad pad;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl *exposure;
struct v4l2_ctrl *anal_gain;
struct v4l2_ctrl *digi_gain;
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *vblank;
struct v4l2_ctrl *test_pattern;
struct mutex mutex;
const struct ov5695_mode *cur_mode;
};
#define to_ov5695(sd) container_of(sd, struct ov5695, subdev)
/*
* Xclk 24Mhz
* Pclk 45Mhz
* linelength 672(0x2a0)
* framelength 2232(0x8b8)
* grabwindow_width 1296
* grabwindow_height 972
* max_framerate 30fps
* mipi_datarate per lane 840Mbps
*/
static const struct regval ov5695_global_regs[] = {
{0x0103, 0x01},
{0x0100, 0x00},
{0x0300, 0x04},
{0x0301, 0x00