// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2022 Intel Corporation.
#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/regulator/consumer.h>
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#define OG01A1B_LINK_FREQ_500MHZ 500000000ULL
#define OG01A1B_SCLK 120000000LL
#define OG01A1B_MCLK 19200000
#define OG01A1B_DATA_LANES 2
#define OG01A1B_REG_CHIP_ID CCI_REG24(0x300a)
#define OG01A1B_CHIP_ID 0x470141
#define OG01A1B_REG_MODE_SELECT CCI_REG8(0x0100)
#define OG01A1B_MODE_STANDBY 0x00
#define OG01A1B_MODE_STREAMING 0x01
/* vertical-timings from sensor */
#define OG01A1B_REG_VTS CCI_REG16(0x380e)
#define OG01A1B_VTS_120FPS 0x0498
#define OG01A1B_VTS_120FPS_MIN 0x0498
#define OG01A1B_VTS_MAX 0x7fff
/* horizontal-timings from sensor */
#define OG01A1B_REG_HTS CCI_REG16(0x380c)
/* Exposure controls from sensor */
#define OG01A1B_REG_EXPOSURE CCI_REG16(0x3501)
#define OG01A1B_EXPOSURE_MIN 1
#define OG01A1B_EXPOSURE_MAX_MARGIN 14
#define OG01A1B_EXPOSURE_STEP 1
/* Analog gain controls from sensor */
#define OG01A1B_REG_ANALOG_GAIN CCI_REG16(0x3508)
#define OG01A1B_ANAL_GAIN_MIN 16
#define OG01A1B_ANAL_GAIN_MAX 248 /* Max = 15.5x */
#define OG01A1B_ANAL_GAIN_STEP 1
/* Digital gain controls from sensor */
#define OG01A1B_REG_DIG_GAIN CCI_REG24(0x350a)
#define OG01A1B_DGTL_GAIN_MIN 1024
#define OG01A1B_DGTL_GAIN_MAX 16384 /* Max = 16x */
#define OG01A1B_DGTL_GAIN_STEP 1
#define OG01A1B_DGTL_GAIN_DEFAULT 1024
/* Test Pattern Control */
#define OG01A1B_REG_TEST_PATTERN CCI_REG8(0x5100)
#define OG01A1B_TEST_PATTERN_ENABLE BIT(7)
#define OG01A1B_TEST_PATTERN_BAR_SHIFT 2
#define to_og01a1b(_sd) container_of(_sd, struct og01a1b, sd)
enum {
OG01A1B_LINK_FREQ_1000MBPS,
};
struct og01a1b_reg_list {
const struct cci_reg_sequence *regs;
u32 num_of_regs;
};
struct og01a1b_link_freq_config {
const struct og01a1b_reg_list reg_list;
};
struct og01a1b_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 og01a1b_reg_list reg_list;
};
static const u32 og01a1b_mbus_formats[] = {
MEDIA_BUS_FMT_Y10_1X10,
MEDIA_BUS_FMT_Y8_1X8,
};
static const struct cci_reg_sequence mipi_data_rate_1000mbps[] = {
{ CCI_REG8(0x0103), 0x01 },
{ CCI_REG8(0x0303), 0x02 },
{ CCI_REG8(0x0304), 0x00 },
{ CCI_REG8(0x0305), 0xd2 },
{ CCI_REG8(0x0323), 0x02 },
{ CCI_REG8(0x0324), 0x01 },
{ CCI_REG8(0x0325), 0x77 },
};
static const struct cci_reg_sequence mode_1280x1024_regs[] = {
{ CCI_REG8(0x0300), 0x0a },
{ CCI_REG8(0x0301), 0x29 },
{ CCI_REG8(0x0302), 0x31 },
{ CCI_REG8(0x0303), 0x02 },
{ CCI_REG8(0x0304), 0x00 },
{ CCI_REG8(0x0305), 0xd2 },
{ CCI_REG8(0x0306), 0x00 },
{ CCI_REG8(0x0307), 0x01 },
{ CCI_REG8(0x0308), 0x02 },
{ CCI_REG8(0x0309), 0x00 },
{ CCI_REG8(0x0310), 0x00 },
{ CCI_REG8(0x0311), 0x00 },
{ CCI_REG8(0x0312), 0x07 },
{ CCI_REG8(0x0313), 0x00 },
{ CCI_REG8(0x0314), 0x00 },
{ CCI_REG8(0x0315), 0x00 },
{ CCI_REG8(0x0320), 0x02 },
{ CCI_REG8(0x0321), 0x01 },
{ CCI_REG8(0x0322), 0x01 },
{ CCI_REG8(0x0323), 0x02 },
{ CCI_REG8(0x0324), 0x01 },
{ CCI_REG8(0x0325), 0x77 },
{ CCI_REG8(0x0326), 0xce },
{ CCI_REG8(0x0327), 0x04 },
{