// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 Sieć Badawcza Łukasiewicz
* - Przemysłowy Instytut Automatyki i Pomiarów PIAP
* Written by Krzysztof Hałasa
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
/* External clock (extclk) frequencies */
#define AR0521_EXTCLK_MIN (10 * 1000 * 1000)
#define AR0521_EXTCLK_MAX (48 * 1000 * 1000)
/* PLL and PLL2 */
#define AR0521_PLL_MIN (320 * 1000 * 1000)
#define AR0521_PLL_MAX (1280 * 1000 * 1000)
/* Effective pixel sample rate on the pixel array. */
#define AR0521_PIXEL_CLOCK_RATE (184 * 1000 * 1000)
#define AR0521_PIXEL_CLOCK_MIN (168 * 1000 * 1000)
#define AR0521_PIXEL_CLOCK_MAX (414 * 1000 * 1000)
#define AR0521_NATIVE_WIDTH 2604u
#define AR0521_NATIVE_HEIGHT 1964u
#define AR0521_MIN_X_ADDR_START 0u
#define AR0521_MIN_Y_ADDR_START 0u
#define AR0521_MAX_X_ADDR_END 2603u
#define AR0521_MAX_Y_ADDR_END 1955u
#define AR0521_WIDTH_MIN 8u
#define AR0521_WIDTH_MAX 2592u
#define AR0521_HEIGHT_MIN 8u
#define AR0521_HEIGHT_MAX 1944u
#define AR0521_WIDTH_BLANKING_MIN 572u
#define AR0521_HEIGHT_BLANKING_MIN 38u /* must be even */
#define AR0521_TOTAL_HEIGHT_MAX 65535u /* max_frame_length_lines */
#define AR0521_TOTAL_WIDTH_MAX 65532u /* max_line_length_pck */
#define AR0521_ANA_GAIN_MIN 0x00
#define AR0521_ANA_GAIN_MAX 0x3f
#define AR0521_ANA_GAIN_STEP 0x01
#define AR0521_ANA_GAIN_DEFAULT 0x00
/* AR0521 registers */
#define AR0521_REG_VT_PIX_CLK_DIV 0x0300
#define AR0521_REG_FRAME_LENGTH_LINES 0x0340
#define AR0521_REG_CHIP_ID 0x3000
#define AR0521_REG_COARSE_INTEGRATION_TIME 0x3012
#define AR0521_REG_ROW_SPEED 0x3016
#define AR0521_REG_EXTRA_DELAY 0x3018
#define AR0521_REG_RESET 0x301A
#define AR0521_REG_RESET_DEFAULTS 0x0238
#define AR0521_REG_RESET_GROUP_PARAM_HOLD 0x8000
#define AR0521_REG_RESET_STREAM BIT(2)
#define AR0521_REG_RESET_RESTART BIT(1)
#define AR0521_REG_RESET_INIT BIT(0)
#define AR0521_REG_ANA_GAIN_CODE_GLOBAL 0x3028
#define AR0521_REG_GREEN1_GAIN 0x3056
#define AR0521_REG_BLUE_GAIN 0x3058
#define AR0521_REG_RED_GAIN 0x305A
#define AR0521_REG_GREEN2_GAIN 0x305C
#define AR0521_REG_GLOBAL_GAIN 0x305E
#define AR0521_REG_HISPI_TEST_MODE 0x3066
#define AR0521_REG_HISPI_TEST_MODE_LP11 0x0004
#define AR0521_REG_TEST_PATTERN_MODE 0x3070
#define AR0521_REG_SERIAL_FORMAT 0x31AE
#define AR0521_REG_SERIAL_FORMAT_MIPI 0x0200
#define AR0521_REG_HISPI_CONTROL_STATUS 0x31C6
#define AR0521_REG_HISPI_CONTROL_STATUS_FRAMER_TEST_MODE_ENABLE 0x80
#define be cpu_to_be16
static const char * const ar0521_supply_names[] = {
"vdd_io", /* I/O (1.8V) supply */
"vdd", /* Core, PLL and MIPI (1.2V) supply */
"vaa", /* Analog (2.7V) supply */
};
static const s64 ar0521_link_frequencies[] = {
184000000,
};
struct ar0521_ctrls {
struct v4l2_ctrl_handler handler;
struct {
struct v4l2_ctrl *gain;
struct v4l2_ctrl *red_balance;
struct v4l2_ctrl *blue_balance;
};
struct {
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *vblank;
};
struct v4l2_ctrl *pixrate;
struct v4l2_ctrl *exposure;
struct v4l2_ctrl *test_pattern;
};
struct ar0521_dev {
struct i2c_client *i2c_client;
struct v4l2_subdev sd;
struct media_pad pad;
struct clk *extclk;
u32 extclk_freq;
struct regulator *supplies[ARRAY_SIZE(ar0521_supply_names)];
struct gpio_desc *reset_gpio;
/* lock to protect all members below */
struct mutex lock;
struct v4l2_mbus_framefmt fmt;
struct ar0521_ctrls ctrls;
unsigned int lane_count;
struct {
u16 pre;
u16 mult;
u16 pre2;
u16 mult2;
u16 vt_pix;
} pll;
};
static inline struct ar0521_dev *to_ar0521_dev(struct v4l2_subdev *sd)
{
return container_of(sd, struct ar0521_dev, sd);
}
static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
{
return &container_of(ctrl->handler, struct ar0521_dev,
ctrls.handler)->sd;
}
static u32 div64_round(u64 v, u32 d)
{
return div_u64(v + (d >> 1), d);
}
static u32 div64_round_up(u64 v, u32 d)
{
return div_u64(v + d - 1, d);
}
static int ar0521_code_to_bpp(struct ar0521_dev *sensor)
{
switch (sensor->fmt.code) {
case MEDIA_BUS_FMT_SGRBG8_1X8:
return 8;
}
return -EINVAL;
}
/* Data must be BE16, the first value is the register address */
static int ar0521_write_regs(struct ar0521_dev *sensor, const __be16 *data,
unsigned int count)
{
struct i2c_client *client = sensor->i2c_client;
struct i2c_msg msg;
int ret;
msg.addr = client->addr;
msg.flags = client->flags;
msg.buf = (u8 *)data;
msg.len = count * sizeof(*data);
ret = i2c_transfer(client->adapter, &msg, 1);
if (ret < 0) {
v4l2_err(&sensor->sd, "%s: I2C write error\n