// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018 Intel Corporation
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <asm/unaligned.h>
#define IMX258_REG_VALUE_08BIT 1
#define IMX258_REG_VALUE_16BIT 2
#define IMX258_REG_MODE_SELECT 0x0100
#define IMX258_MODE_STANDBY 0x00
#define IMX258_MODE_STREAMING 0x01
/* Chip ID */
#define IMX258_REG_CHIP_ID 0x0016
#define IMX258_CHIP_ID 0x0258
/* V_TIMING internal */
#define IMX258_VTS_30FPS 0x0c98
#define IMX258_VTS_30FPS_2K 0x0638
#define IMX258_VTS_30FPS_VGA 0x034c
#define IMX258_VTS_MAX 0xffff
/*Frame Length Line*/
#define IMX258_FLL_MIN 0x08a6
#define IMX258_FLL_MAX 0xffff
#define IMX258_FLL_STEP 1
#define IMX258_FLL_DEFAULT 0x0c98
/* HBLANK control - read only */
#define IMX258_PPL_DEFAULT 5352
/* Exposure control */
#define IMX258_REG_EXPOSURE 0x0202
#define IMX258_EXPOSURE_MIN 4
#define IMX258_EXPOSURE_STEP 1
#define IMX258_EXPOSURE_DEFAULT 0x640
#define IMX258_EXPOSURE_MAX 65535
/* Analog gain control */
#define IMX258_REG_ANALOG_GAIN 0x0204
#define IMX258_ANA_GAIN_MIN 0
#define IMX258_ANA_GAIN_MAX 0x1fff
#define IMX258_ANA_GAIN_STEP 1
#define IMX258_ANA_GAIN_DEFAULT 0x0
/* Digital gain control */
#define IMX258_REG_GR_DIGITAL_GAIN 0x020e
#define IMX258_REG_R_DIGITAL_GAIN 0x0210
#define IMX258_REG_B_DIGITAL_GAIN 0x0212
#define IMX258_REG_GB_DIGITAL_GAIN 0x0214
#define IMX258_DGTL_GAIN_MIN 0
#define IMX258_DGTL_GAIN_MAX 4096 /* Max = 0xFFF */
#define IMX258_DGTL_GAIN_DEFAULT 1024
#define IMX258_DGTL_GAIN_STEP 1
/* Test Pattern Control */
#define IMX258_REG_TEST_PATTERN 0x0600
/* Orientation */
#define REG_MIRROR_FLIP_CONTROL 0x0101
#define REG_CONFIG_MIRROR_FLIP 0x03
#define REG_CONFIG_FLIP_TEST_PATTERN 0x02
struct imx258_reg {
u16 address;
u8 val;
};
struct imx258_reg_list {
u32 num_of_regs;
const struct imx258_reg *regs;
};
/* Link frequency config */
struct imx258_link_freq_config {
u32 pixels_per_line;
/* PLL registers for this link frequency */
struct imx258_reg_list reg_list;
};
/* Mode : resolution and related config&values */
struct imx258_mode {
/* Frame width */
u32 width;
/* Frame height */
u32 height;
/* V-timing */
u32 vts_def;
u32 vts_min;
/* Index of Link frequency config to be used */
u32 link_freq_index;
/* Default register values */
struct imx258_reg_list reg_list;
};
/* 4208x3118 needs 1267Mbps/lane, 4 lanes */
static const struct imx258_reg mipi_data_rate_1267mbps[] = {
{ 0x0301, 0x05 },
{ 0x0303, 0x02 },
{ 0x0305, 0x03 },
{ 0x0306, 0x00 },
{ 0x0307, 0xC6 },
{ 0x0309, 0x0A },
{ 0x030B, 0x01 },
{ 0x030D, 0x02 },
{ 0x030E, 0x00 },
{ 0x030F, 0xD8 },
{ 0x0310, 0x00 },
{ 0x0820, 0x13 },
{ 0x0821, 0x4C },
{ 0x0822, 0xCC },
{ 0x0823, 0xCC },
};
static const struct imx258_reg mipi_data_rate_640mbps[] = {
{ 0x0301, 0x05 },
{ 0x0303, 0x02 },
{ 0x0305, 0x03 },
{ 0x0306, 0x00 },
{ 0x0307, 0x64 },
{ 0x0309, 0x0A },
{ 0x030B, 0x01 },
{ 0x030D, 0x02 },
{ 0x030E, 0x00 },
{ 0x030F, 0xD8 },
{ 0x0310, 0x00 },
{ 0x0820, 0x0A },
{ 0x0821, 0x00 },
{ 0x0822, 0x00 },
{ 0x0823, 0x00 },
};
static const struct imx258_reg mode_4208x3118_regs[] = {
{ 0x0136, 0x13 },
{ 0x0137,