// SPDX-License-Identifier: GPL-2.0-only
/*
* Sony imx335 Camera Sensor Driver
*
* Copyright (C) 2021 Intel Corporation
*/
#include <asm/unaligned.h>
#include <linux/clk.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-fwnode.h>
#include <media/v4l2-subdev.h>
/* Streaming Mode */
#define IMX335_REG_MODE_SELECT 0x3000
#define IMX335_MODE_STANDBY 0x01
#define IMX335_MODE_STREAMING 0x00
/* Lines per frame */
#define IMX335_REG_LPFR 0x3030
/* Chip ID */
#define IMX335_REG_ID 0x3912
#define IMX335_ID 0x00
/* Exposure control */
#define IMX335_REG_SHUTTER 0x3058
#define IMX335_EXPOSURE_MIN 1
#define IMX335_EXPOSURE_OFFSET 9
#define IMX335_EXPOSURE_STEP 1
#define IMX335_EXPOSURE_DEFAULT 0x0648
/* Analog gain control */
#define IMX335_REG_AGAIN 0x30e8
#define IMX335_AGAIN_MIN 0
#define IMX335_AGAIN_MAX 240
#define IMX335_AGAIN_STEP 1
#define IMX335_AGAIN_DEFAULT 0
/* Group hold register */
#define IMX335_REG_HOLD 0x3001
/* Input clock rate */
#define IMX335_INCLK_RATE 24000000
/* CSI2 HW configuration */
#define IMX335_LINK_FREQ 594000000
#define IMX335_NUM_DATA_LANES 4
#define IMX335_REG_MIN 0x00
#define IMX335_REG_MAX 0xfffff
/* IMX335 native and active pixel array size. */
#define IMX335_NATIVE_WIDTH 2616U
#define IMX335_NATIVE_HEIGHT 1964U
#define IMX335_PIXEL_ARRAY_LEFT 12U
#define IMX335_PIXEL_ARRAY_TOP 12U
#define IMX335_PIXEL_ARRAY_WIDTH 2592U
#define IMX335_PIXEL_ARRAY_HEIGHT 1944U
/**
* struct imx335_reg - imx335 sensor register
* @address: Register address
* @val: Register value
*/
struct imx335_reg {
u16 address;
u8 val;
};
/**
* struct imx335_reg_list - imx335 sensor register list
* @num_of_regs: Number of registers in the list
* @regs: Pointer to register list
*/
struct imx335_reg_list {
u32 num_of_regs;
const struct imx335_reg *regs;
};
static const char * const imx335_supply_name[] = {
"avdd", /* Analog (2.9V) supply */
"ovdd", /* Digital I/O (1.8V) supply */
"dvdd", /* Digital Core (1.2V) supply */
};
/**
* struct imx335_mode - imx335 sensor mode structure
* @width: Frame width
* @height: Frame height
* @code: Format code
* @hblank: Horizontal blanking in lines
* @vblank: Vertical blanking in lines
* @vblank_min: Minimum vertical blanking in lines
* @vblank_max: Maximum vertical blanking in lines
* @pclk: Sensor pixel clock
* @link_freq_idx: Link frequency index
* @reg_list: Register list for sensor mode
*/
struct imx335_mode {
u32 width;
u32 height;
u32 code;
u32 hblank;
u32 vblank;
u32 vblank_min;
u32 vblank_max;
u64 pclk;
u32 link_freq_idx;
struct imx335_reg_list reg_list;
};
/**
* struct imx335 - imx335 sensor device structure
* @dev: Pointer to generic device
* @client: Pointer to i2c client
* @sd: V4L2 sub-device
* @pad: Media pad. Only one pad supported
* @reset_gpio: Sensor reset gpio
* @supplies: Regulator supplies to handle power control
* @inclk: Sensor input clock
* @ctrl_handler: V4L2 control handler
* @link_freq_ctrl: Pointer to link frequency control
* @pclk_ctrl: Pointer to pixel clock control
* @hblank_ctrl: Pointer to horizontal blanking control
* @vblank_ctrl: Pointer to vertical blanking control
* @exp_ctrl: Pointer to exposure control
* @again_ctrl: Pointer to analog gain control
* @vblank: Vertical blanking in lines
* @cur_mode: Pointer to current selected sensor mode
* @mutex: Mutex for serializing sensor controls
* @cur_mbus_code: Currently selected media bus format code
*/
struct imx335 {
struct device *dev;
struct i2c_client *client;
struct v4l2_subdev sd;
struct media_pad pad;
struct gpio_desc *reset_gpio;
struct regulator_bulk_data supplies[ARRAY_SIZE(imx335_supply_name)];
struct clk *inclk;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl *link_freq_ctrl;
struct v4l2_ctrl *pclk_ctrl;
struct v4l2_ctrl *hblank_ctrl;
struct v4l2_ctrl *vblank_ctrl;
struct {
struct v4l2_ctrl *exp_ctrl;
struct v4l2_ctrl *again_ctrl;
};
u32 vblank;
const struct imx335_mode *cur_mode;
struct mutex mutex;
u32 cur_mbus_code;
};
static const s64 link_freq[] = {
IMX335_LINK_FREQ,
};
/* Sensor mode registers */
static const struct imx335_reg mode_2592x1940_regs[] = {
{0x3000, 0x01},
{0x3002, 0x00},
{0x300c, 0x3b},
{0x300d, 0x2a},
{0x3018, 0x04},
{0x302c, 0x3c},
{0x302e, 0x20},
{0x3056, 0x94},
{0x3074, 0xc8},
{0x3076, 0x28},
{0x304c