// SPDX-License-Identifier: GPL-2.0
/*
* Omnivision OV2680 CMOS Image Sensor driver
*
* Copyright (C) 2018 Linaro Ltd
*
* Based on OV5640 Sensor Driver
* Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2014-2017 Mentor Graphics Inc.
*
*/
#include <asm/unaligned.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#define OV2680_XVCLK_VALUE 24000000
#define OV2680_CHIP_ID 0x2680
#define OV2680_REG_STREAM_CTRL 0x0100
#define OV2680_REG_SOFT_RESET 0x0103
#define OV2680_REG_CHIP_ID_HIGH 0x300a
#define OV2680_REG_CHIP_ID_LOW 0x300b
#define OV2680_REG_R_MANUAL 0x3503
#define OV2680_REG_GAIN_PK 0x350a
#define OV2680_REG_EXPOSURE_PK_HIGH 0x3500
#define OV2680_REG_TIMING_HTS 0x380c
#define OV2680_REG_TIMING_VTS 0x380e
#define OV2680_REG_FORMAT1 0x3820
#define OV2680_REG_FORMAT2 0x3821
#define OV2680_REG_ISP_CTRL00 0x5080
#define OV2680_FRAME_RATE 30
#define OV2680_REG_VALUE_8BIT 1
#define OV2680_REG_VALUE_16BIT 2
#define OV2680_REG_VALUE_24BIT 3
#define OV2680_WIDTH_MAX 1600
#define OV2680_HEIGHT_MAX 1200
enum ov2680_mode_id {
OV2680_MODE_QUXGA_800_600,
OV2680_MODE_720P_1280_720,
OV2680_MODE_UXGA_1600_1200,
OV2680_MODE_MAX,
};
struct reg_value {
u16 reg_addr;
u8 val;
};
static const char * const ov2680_supply_name[] = {
"DOVDD",
"DVDD",
"AVDD",
};
#define OV2680_NUM_SUPPLIES ARRAY_SIZE(ov2680_supply_name)
struct ov2680_mode_info {
const char *name;
enum ov2680_mode_id id;
u32 width;
u32 height;
const struct reg_value *reg_data;
u32 reg_data_size;
};
struct ov2680_ctrls {
struct v4l2_ctrl_handler handler;
struct {
struct v4l2_ctrl *auto_exp;
struct v4l2_ctrl *exposure;
};
struct {
struct v4l2_ctrl *auto_gain;
struct v4l2_ctrl *gain;
};
struct v4l2_ctrl *hflip;
struct v4l2_ctrl *vflip;
struct v4l2_ctrl *test_pattern;
};
struct ov2680_dev {
struct i2c_client *i2c_client;
struct v4l2_subdev sd;
struct media_pad pad;
struct clk *xvclk;
u32 xvclk_freq;
struct regulator_bulk_data supplies[OV2680_NUM_SUPPLIES];
struct gpio_desc *reset_gpio;
struct mutex lock; /* protect members */
bool mode_pending_changes;
bool is_enabled;
bool is_streaming;
struct ov2680_ctrls ctrls;
struct v4l2_mbus_framefmt fmt;
struct v4l2_fract frame_interval;
const struct ov2680_mode_info *current_mode;
};
static const char * const test_pattern_menu[] = {
"Disabled",
"Color Bars",
"Random Data",
"Square",
"Black Image",
};
static const int ov2680_hv_flip_bayer_order[] = {
MEDIA_BUS_FMT_SBGGR10_1X10,
MEDIA_BUS_FMT_SGRBG10_1X10,
MEDIA_BUS_FMT_SGBRG10_1X10,
MEDIA_BUS_FMT_SRGGB10_1X10,
};
static const struct reg_value ov2680_setting_30fps_QUXGA_800_600[] = {
{0x3086, 0x01}, {0x370a, 0x23}, {0x3808, 0x03}, {0x3809, 0x20},
{0x380a, 0x02}, {0x380b, 0x58}, {0x380c, 0x06}, {0x380d, 0xac},
{0x380e, 0x02}, {0x380f, 0x84}, {0x3811, 0x04}, {0x3813, 0x04},
{0x3814, 0x31}, {0x3815, 0x31}, {0x3820,