// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2022 Intel Corporation.
#include <linux/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/regulator/consumer.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#define OG01A1B_REG_VALUE_08BIT 1
#define OG01A1B_REG_VALUE_16BIT 2
#define OG01A1B_REG_VALUE_24BIT 3
#define OG01A1B_LINK_FREQ_500MHZ 500000000ULL
#define OG01A1B_SCLK 120000000LL
#define OG01A1B_MCLK 19200000
#define OG01A1B_DATA_LANES 2
#define OG01A1B_RGB_DEPTH 10
#define OG01A1B_REG_CHIP_ID 0x300a
#define OG01A1B_CHIP_ID 0x470141
#define OG01A1B_REG_MODE_SELECT 0x0100
#define OG01A1B_MODE_STANDBY 0x00
#define OG01A1B_MODE_STREAMING 0x01
/* vertical-timings from sensor */
#define OG01A1B_REG_VTS 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 0x380c
/* Exposure controls from sensor */
#define OG01A1B_REG_EXPOSURE 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 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 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
/* Group Access */
#define OG01A1B_REG_GROUP_ACCESS 0x3208
#define OG01A1B_GROUP_HOLD_START 0x0
#define OG01A1B_GROUP_HOLD_END 0x10
#define OG01A1B_GROUP_HOLD_LAUNCH 0xa0
/* Test Pattern Control */
#define OG01A1B_REG_TEST_PATTERN 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 {
u16 address;
u8 val;
};
struct og01a1b_reg_list {
u32 num_of_regs;
const struct og01a1b_reg *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 struct og01a1b_reg mipi_data_rate_1000mbps[] = {
{0x0103, 0x01},
{0x0303, 0x02},
{0x0304, 0x00},
{0x0305, 0xd2},
{0x0323, 0x02},
{0x0324, 0x01},
{0x0325, 0x77},
};
static const struct og01a1b_reg mode_1280x1024_regs[] = {
{0x0300, 0x0a},
{0x0301, 0x29},
{0x0302, 0x31},
{0x0303, 0x02},
{0x0304, 0x00},
{0x0305, 0xd2},
{0x0306, 0x00},
{0x0307, 0x01},
{0x0308, 0x02},
{0x0309, 0x00},
{0x0310, 0x00},
{0x0311, 0x00},
{0x0312, 0x07},
{0x0313, 0x00},
{0x0314, 0x00},
{0x0315, 0x00},
{0x0320, 0x02},
{0x0321, 0x01},
{0x0322, 0x01},
{0x0323, 0x02},
{0x0324, 0x01},
{0x0325, 0x77},
{0x0326, 0xce},
{0x0327, 0x04},
{0x0329, 0x02},
{0x032a, 0x04},
{0x032b, 0x04},
{0x032c, 0x02},
{0x032d, 0x01},
{0x032e, 0x00},
{0x300d, 0x02},
{0x300e, 0x04},
{0x3021, 0x08},
{0x301e, 0x03},
{0x3103, 0x00},
{0x3106, 0x08},
{0x3107, 0x40},
{0x3216, 0x01},
{0x3217, 0x00},
{0x3218, 0xc0},
{0x3219, 0x55},
{0x3500, 0x00},
{0x3501, 0x04},
{0x3502, 0x8a},
{0x3506, 0x01},
{0x3507, 0x72},
{0x3508, 0x01},
{0x3509, 0x00