// SPDX-License-Identifier: GPL-2.0
/*
* A V4L2 driver for Sony IMX219 cameras.
* Copyright (C) 2019, Raspberry Pi (Trading) Ltd
*
* Based on Sony imx258 camera driver
* Copyright (C) 2018 Intel Corporation
*
* DT / fwnode changes, and regulator / GPIO control taken from imx214 driver
* Copyright 2018 Qtechnology A/S
*
* Flip handling taken from the Sony IMX319 driver.
* Copyright (C) 2018 Intel Corporation
*
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/minmax.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-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h>
/* Chip ID */
#define IMX219_REG_CHIP_ID CCI_REG16(0x0000)
#define IMX219_CHIP_ID 0x0219
#define IMX219_REG_MODE_SELECT CCI_REG8(0x0100)
#define IMX219_MODE_STANDBY 0x00
#define IMX219_MODE_STREAMING 0x01
#define IMX219_REG_CSI_LANE_MODE CCI_REG8(0x0114)
#define IMX219_CSI_2_LANE_MODE 0x01
#define IMX219_CSI_4_LANE_MODE 0x03
#define IMX219_REG_DPHY_CTRL CCI_REG8(0x0128)
#define IMX219_DPHY_CTRL_TIMING_AUTO 0
#define IMX219_DPHY_CTRL_TIMING_MANUAL 1
#define IMX219_REG_EXCK_FREQ CCI_REG16(0x012a)
#define IMX219_EXCK_FREQ(n) ((n) * 256) /* n expressed in MHz */
/* Analog gain control */
#define IMX219_REG_ANALOG_GAIN CCI_REG8(0x0157)
#define IMX219_ANA_GAIN_MIN 0
#define IMX219_ANA_GAIN_MAX 232
#define IMX219_ANA_GAIN_STEP 1
#define IMX219_ANA_GAIN_DEFAULT 0x0
/* Digital gain control */
#define IMX219_REG_DIGITAL_GAIN CCI_REG16(0x0158)
#define IMX219_DGTL_GAIN_MIN 0x0100
#define IMX219_DGTL_GAIN_MAX 0x0fff
#define IMX219_DGTL_GAIN_DEFAULT 0x0100
#define IMX219_DGTL_GAIN_STEP 1
/* Exposure control */
#define IMX219_REG_EXPOSURE CCI_REG16(0x015a)
#define IMX219_EXPOSURE_MIN 4
#define IMX219_EXPOSURE_STEP 1
#define IMX219_EXPOSURE_DEFAULT 0x640
#define IMX219_EXPOSURE_MAX 65535
/* V_TIMING internal */
#define IMX219_REG_VTS CCI_REG16(0x0160)
#define IMX219_VTS_MAX 0xffff
#define IMX219_VBLANK_MIN 4
/* HBLANK control - read only */
#define IMX219_PPL_DEFAULT 3448
#define IMX219_REG_LINE_LENGTH_A CCI_REG16(0x0162)
#define IMX219_REG_X_ADD_STA_A CCI_REG16(0x0164)
#define IMX219_REG_X_ADD_END_A CCI_REG16(0x0166)
#define IMX219_REG_Y_ADD_STA_A CCI_REG16(0x0168)
#define IMX219_REG_Y_ADD_END_A CCI_REG16(0x016a)
#define IMX219_REG_X_OUTPUT_SIZE CCI_REG16(0x016c)
#define IMX219_REG_Y_OUTPUT_SIZE CCI_REG16(0x016e)
#define IMX219_REG_X_ODD_INC_A CCI_REG8(0x0170)
#define IMX219_REG_Y_ODD_INC_A CCI_REG8(0x0171)
#define IMX219_REG_ORIENTATION CCI_REG8(0x0172)
/* Binning Mode */
#define IMX219_REG_BINNING_MODE_H CCI_REG8(0x0174)
#define IMX219_REG_BINNING_MODE_V CCI_REG8(0x0175)
#define IMX219_BINNING_NONE 0x00
#define IMX219_BINNING_X2 0x01
#define IMX219_BINNING_X2_ANALOG 0x03
#define IMX219_REG_CSI_DATA_FORMAT_A CCI_REG16(0x018c)
/* PLL Settings */
#define IMX219_REG_VTPXCK_DIV CCI_REG8(0x0301)
#define IMX219_REG_VTSYCK_DIV CCI_REG8(0x0303)
#define IMX219_REG_PREPLLCK_VT_DIV CCI_REG8(0x0304)
#define IMX219_REG_PREPLLCK_OP_DIV CCI_REG8(0x0305)
#define IMX219_REG_PLL_VT_MPY CCI_REG16(0x0306)
#define IMX219_REG_OPPXCK_DIV CCI_REG8(0x0309)
#define IMX219_REG_OPSYCK_DIV CCI_REG8(0x030b)
#define IMX219_REG_PLL_OP_MPY CCI_REG16(0x030c)
/* Test Pattern Control */
#define IMX219_REG_TEST_PATTERN CCI_REG16(0x0600)
#define IMX219_TEST_PATTERN_DISABLE 0
#define IMX219_TEST_PATTERN_SOLID_COLOR 1
#define IMX219_TEST_PATTERN_COLOR_BARS 2
#define IMX219_TEST_PATTERN_GREY_COLOR 3
#define IMX219_TEST_PATTERN_PN9 4
/* Test pattern colour components */
#define IMX219_REG_TESTP_RED CCI_REG16(0x0602)
#define IMX219_REG_TESTP_GREENR CCI_REG16(0x0604)
#define IMX219_REG_TESTP_BLUE CCI_REG16(0x0606)
#define IMX219_REG_TESTP_GREENB CCI_REG16(0x0608)
#define IMX219_TESTP_COLOUR_MIN 0
#define IMX219_TESTP_COLOUR_MAX 0x03ff
#define IMX219_TESTP_COLOUR_STEP 1
#define IMX219_REG_TP_WINDOW_WIDTH CCI_REG16(0x0624)
#define IMX219_REG_TP_WINDOW_HEIGHT CCI_REG16(0x0626)
/* External clock frequency is 24.0M */
#define IMX219_XCLK_FREQ 24000000
/* Pixel rate is fixed for all the modes */
#define IMX219_PIXEL_RATE 182400000
#define IMX219_PIXEL_RATE_4LANE 280800000
#define IMX219_DEFAULT_LINK_FREQ 456000000
#define IMX219_DEFAULT_LINK_FREQ_4LANE 363000000
/* IMX219 native and active pixel array size. */
#define IMX219_NATIVE_WIDTH 3296U
#define IMX219_NATIVE_HEIGHT 2480U
#define IMX219_PIXEL_ARRAY_LEFT 8U
#define IMX219_PIXEL_ARRAY_TOP 8U
#define IMX219_PIXEL_ARRAY_WIDTH 3280U
#define IMX219_PIXEL_ARRAY_HEIGHT 2464U
/* Mode : resolution and related config&values */
struct imx219_mode {
/* Frame width */
unsigned int width;
/* Frame height */
unsigned int height;
/* V-timing */
unsigned int vts_def;
};
static const struct cci_reg_sequence imx219_common_regs[] = {
{ IMX219_REG_MODE_SELECT, 0x00 }, /* Mode Select */
/* To Access Addresses 3000-5fff, send the following commands */
{ CCI_REG8(0x30eb), 0x0c },
{ CCI_REG8(0x30eb), 0x05 },
{ CCI_REG8(0x300a), 0xff },
{ CCI_REG8(0x300b), 0xff },
{ CCI_REG8(0x30eb), 0x05 },
{ CCI_REG8(0x30eb), 0x09 },
/* PLL Clock Table */
{ IMX219_REG_VTPXCK_DIV, 5 },
{ IMX219_REG_VTSYCK_DIV, 1 },
{ IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */
{ IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */
{ IMX219_REG_PLL_VT_MPY, 57 },
{ IMX219_REG_OPSYCK_DIV, 1 },
{ IMX219_REG_PLL_OP_MPY, 114 },
/* Undocumented registers */
{ CCI_REG8(0x455e), 0x00 },
{ CCI_REG8(0x471e), 0x4b },
{ CCI_REG8(0x4767), 0x0f },
{ CCI_REG8(0x4750), 0x14 },
{