// SPDX-License-Identifier: GPL-2.0-only
/*
* Driver for the Sony IMX415 CMOS Image Sensor.
*
* Copyright (C) 2023 WolfVision GmbH.
*/
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
#define IMX415_PIXEL_ARRAY_TOP 0
#define IMX415_PIXEL_ARRAY_LEFT 0
#define IMX415_PIXEL_ARRAY_WIDTH 3864
#define IMX415_PIXEL_ARRAY_HEIGHT 2192
#define IMX415_PIXEL_ARRAY_VBLANK 58
#define IMX415_NUM_CLK_PARAM_REGS 11
#define IMX415_REG_8BIT(n) ((1 << 16) | (n))
#define IMX415_REG_16BIT(n) ((2 << 16) | (n))
#define IMX415_REG_24BIT(n) ((3 << 16) | (n))
#define IMX415_REG_SIZE_SHIFT 16
#define IMX415_REG_ADDR_MASK 0xffff
#define IMX415_MODE IMX415_REG_8BIT(0x3000)
#define IMX415_MODE_OPERATING (0)
#define IMX415_MODE_STANDBY BIT(0)
#define IMX415_REGHOLD IMX415_REG_8BIT(0x3001)
#define IMX415_REGHOLD_INVALID (0)
#define IMX415_REGHOLD_VALID BIT(0)
#define IMX415_XMSTA IMX415_REG_8BIT(0x3002)
#define IMX415_XMSTA_START (0)
#define IMX415_XMSTA_STOP BIT(0)
#define IMX415_BCWAIT_TIME IMX415_REG_16BIT(0x3008)
#define IMX415_CPWAIT_TIME IMX415_REG_16BIT(0x300A)
#define IMX415_WINMODE IMX415_REG_8BIT(0x301C)
#define IMX415_ADDMODE IMX415_REG_8BIT(0x3022)
#define IMX415_REVERSE IMX415_REG_8BIT(0x3030)
#define IMX415_HREVERSE_SHIFT (0)
#define IMX415_VREVERSE_SHIFT BIT(0)
#define IMX415_ADBIT IMX415_REG_8BIT(0x3031)
#define IMX415_MDBIT IMX415_REG_8BIT(0x3032)
#define IMX415_SYS_MODE IMX415_REG_8BIT(0x3033)
#define IMX415_OUTSEL IMX415_REG_8BIT(0x30C0)
#define IMX415_DRV IMX415_REG_8BIT(0x30C1)
#define IMX415_VMAX IMX415_REG_24BIT(0x3024)
#define IMX415_HMAX IMX415_REG_16BIT(0x3028)
#define IMX415_SHR0 IMX415_REG_24BIT(0x3050)
#define IMX415_GAIN_PCG_0 IMX415_REG_16BIT(0x3090)
#define IMX415_AGAIN_MIN 0
#define IMX415_AGAIN_MAX 100
#define IMX415_AGAIN_STEP 1
#define IMX415_BLKLEVEL IMX415_REG_16BIT(0x30E2)
#define IMX415_BLKLEVEL_DEFAULT 50
#define IMX415_TPG_EN_DUOUT IMX415_REG_8BIT(0x30E4)
#define IMX415_TPG_PATSEL_DUOUT IMX415_REG_8BIT(0x30E6)
#define IMX415_TPG_COLORWIDTH IMX415_REG_8BIT(0x30E8)
#define IMX415_TESTCLKEN_MIPI IMX415_REG_8BIT(0x3110)
#define IMX415_INCKSEL1 IMX415_REG_8BIT(0x3115)
#define IMX415_INCKSEL2 IMX415_REG_8BIT(0x3116)
#define IMX415_INCKSEL3 IMX415_REG_16BIT(0x3118)
#define IMX415_INCKSEL4 IMX415_REG_16BIT(0x311A)
#define IMX415_INCKSEL5 IMX415_REG_8BIT(0x311E)
#define IMX415_DIG_CLP_MODE IMX415_REG_8BIT(0x32C8)
#define IMX415_WRJ_OPEN IMX415_REG_8BIT(0x3390)
#define IMX415_SENSOR_INFO IMX415_REG_16BIT(0x3F12)
#define IMX415_SENSOR_INFO_MASK 0xFFF
#define IMX415_CHIP_ID 0x514
#define IMX415_LANEMODE IMX415_REG_16BIT(0x4001)
#define IMX415_LANEMODE_2 1
#define IMX415_LANEMODE_4 3
#define IMX415_TXCLKESC_FREQ IMX415_REG_16BIT(0x4004)
#define IMX415_INCKSEL6 IMX415_REG_8BIT(0x400C)
#define IMX415_TCLKPOST IMX415_REG_16BIT(0x4018)
#define IMX415_TCLKPREPARE IMX415_REG_16BIT(0x401A)
#define IMX415_TCLKTRAIL IMX415_REG_16BIT(0x401C)
#define IMX415_TCLKZERO IMX415_REG_16BIT(0x401E)
#define IMX415_THSPREPARE IMX415_REG_16BIT(0x4020)
#define IMX415_THSZERO IMX415_REG_16BIT(0x4022)
#define IMX415_THSTRAIL IMX415_REG_16BIT(0x4024)
#define IMX415_THSEXIT IMX415_REG_16BIT(0x4026)
#define IMX415_TLPX IMX415_REG_16BIT(0x4028)
#define IMX415_INCKSEL7 IMX415_REG_8BIT(0x4074)
struct imx415_reg {
u32 address;
u32 val;
};
static const char *const imx415_supply_names[] = {
"dvdd",
"ovdd",
"avdd",
};
/*
* The IMX415 data sheet uses lane rates but v4l2 uses link frequency to
* describe MIPI CSI-2 speed. This driver uses lane rates wherever possible
* and converts them to link frequencies by a factor of two when needed.
*/
static const s64 link_freq_menu_items[] = {
594000000 / 2, 720000000 / 2, 891000000 / 2,
1440000000 / 2, 1485000000 / 2,
};
struct imx415_clk_params {
u64 lane_rate;
u64 inck;
struct imx415_reg regs[IMX415_NUM_CLK_PARAM_REGS];
};
/* INCK Settings - includes all lane rate and INCK dependent registers */
static const struct imx415_clk_params imx415_clk_params[] = {
{
.lane_rate = 594000000,
.inck = 27000000,
.regs[0] = { IMX415_BCWAIT_TIME, 0x05D },
.regs[1] = { IMX415_CPWAIT_TIME, 0x042 },
.regs[2] = { IMX415_SYS_MODE, 0x7 },
.regs[3] = { IMX415_INCKSEL1, 0x00 },
.regs[4] = { IMX415_INCKSEL2, 0x23 },
.regs[5] = { IMX415_INCKSEL3, 0x084 },
.regs[6] = { IMX415_INCKSEL4, 0x0E7 },
.regs[7] = { IMX415_INCKSEL5