// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2020 Intel Corporation.
#include <asm/unaligned.h>
#include <linux/acpi.h>
#include <linux/clk.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/nvmem-provider.h>
#include <linux/regmap.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#define OV2740_LINK_FREQ_360MHZ 360000000ULL
#define OV2740_SCLK 72000000LL
#define OV2740_MCLK 19200000
#define OV2740_DATA_LANES 2
#define OV2740_RGB_DEPTH 10
#define OV2740_REG_CHIP_ID 0x300a
#define OV2740_CHIP_ID 0x2740
#define OV2740_REG_MODE_SELECT 0x0100
#define OV2740_MODE_STANDBY 0x00
#define OV2740_MODE_STREAMING 0x01
/* vertical-timings from sensor */
#define OV2740_REG_VTS 0x380e
#define OV2740_VTS_DEF 0x088a
#define OV2740_VTS_MIN 0x0460
#define OV2740_VTS_MAX 0x7fff
/* horizontal-timings from sensor */
#define OV2740_REG_HTS 0x380c
/* Exposure controls from sensor */
#define OV2740_REG_EXPOSURE 0x3500
#define OV2740_EXPOSURE_MIN 4
#define OV2740_EXPOSURE_MAX_MARGIN 8
#define OV2740_EXPOSURE_STEP 1
/* Analog gain controls from sensor */
#define OV2740_REG_ANALOG_GAIN 0x3508
#define OV2740_ANAL_GAIN_MIN 128
#define OV2740_ANAL_GAIN_MAX 1983
#define OV2740_ANAL_GAIN_STEP 1
/* Digital gain controls from sensor */
#define OV2740_REG_MWB_R_GAIN 0x500a
#define OV2740_REG_MWB_G_GAIN 0x500c
#define OV2740_REG_MWB_B_GAIN 0x500e
#define OV2740_DGTL_GAIN_MIN 1024
#define OV2740_DGTL_GAIN_MAX 4095
#define OV2740_DGTL_GAIN_STEP 1
#define OV2740_DGTL_GAIN_DEFAULT 1024
/* Test Pattern Control */
#define OV2740_REG_TEST_PATTERN 0x5040
#define OV2740_TEST_PATTERN_ENABLE BIT(7)
#define OV2740_TEST_PATTERN_BAR_SHIFT 2
/* Group Access */
#define OV2740_REG_GROUP_ACCESS 0x3208
#define OV2740_GROUP_HOLD_START 0x0
#define OV2740_GROUP_HOLD_END 0x10
#define OV2740_GROUP_HOLD_LAUNCH 0xa0
/* ISP CTRL00 */
#define OV2740_REG_ISP_CTRL00 0x5000
/* ISP CTRL01 */
#define OV2740_REG_ISP_CTRL01 0x5001
/* Customer Addresses: 0x7010 - 0x710F */
#define CUSTOMER_USE_OTP_SIZE 0x100
/* OTP registers from sensor */
#define OV2740_REG_OTP_CUSTOMER 0x7010
struct nvm_data {
struct nvmem_device *nvmem;
struct regmap *regmap;
char *nvm_buffer;
};
enum {
OV2740_LINK_FREQ_360MHZ_INDEX,
};
struct ov2740_reg {
u16 address;
u8 val;
};
struct ov2740_reg_list {
u32 num_of_regs;
const struct ov2740_reg *regs;
};
struct ov2740_link_freq_config {
const struct ov2740_reg_list reg_list;
};
struct ov2740_mode {
/* Frame width in pixels */
u32 width;
/* Frame height in pixels */
u32 height;
/* Horizontal timining size */
u32 hts;
/* Default vertical timining size */
u32 vts_def;
/* Min vertical timining size */
u32 vts_min;
/* Link frequency needed for this resolution */
u32 link_freq_index;
/* Sensor register settings for this resolution */
const struct ov2740_reg_list reg_list;
};
static const struct ov2740_reg mipi_data_rate_720mbps[] = {
{0x0103, 0x01},
{0x0302, 0x4b},
{0x030d, 0x4b},
{0x030e, 0x02},
{0x030a, 0x01},
{0x0312, 0x11},
};
static const struct ov2740_reg mode_1932x1092_regs[] = {
{0x3000, 0x00},
{0x3018, 0x32},
{0x3031, 0x0a},
{0x3080, 0x08},
{0x3083, 0xB4},
{0x3103, 0x00},
{0x3104, 0x01},
{0x3106, 0x01},
{0x3500, 0x00},
{0x3501, 0x44},
{0x3502, 0x40},
{0x3503, 0x88},
{0x3507, 0x00},
{0x3508, 0x00},
{0x3509, 0x80},
{0x350c, 0x00},
{0x350d, 0x80},
{0x3510, 0x00},
{0x3511, 0x00},
{0x3512, 0x20},
{0x3632, 0x00},
{0x3633, 0x10},
{0x3634, 0x10},
{0x3635, 0x10},
{0x3645, 0x13},
{0x3646, 0x81},
{0x3636, 0x10},
{0x3651, 0x0a},
{0x3656, 0x02},
{0x3659, 0x04},
{0x365a, 0xda},
{0x365b, 0xa2},
{0x365c, 0x04},
{0x365d, 0x1d},
{0x365e, 0x1a},
{0x3662, 0xd7},
{0x3667, 0x78},
{0x3669, 0x0a},
{0x366a, 0x92},
{0x3700, 0x54},
{0x3702, 0x10},
{0x3706, 0x42},