// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Driver for the OV5645 camera sensor.
*
* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
* Copyright (C) 2015 By Tech Design S.L. All Rights Reserved.
* Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
*
* Based on:
* - the OV5645 driver from QC msm-3.10 kernel on codeaurora.org:
* https://us.codeaurora.org/cgit/quic/la/kernel/msm-3.10/tree/drivers/
* media/platform/msm/camera_v2/sensor/ov5645.c?h=LA.BR.1.2.4_rb1.41
* - the OV5640 driver posted on linux-media:
* https://www.mail-archive.com/linux-media%40vger.kernel.org/msg92671.html
*/
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
#define OV5645_SYSTEM_CTRL0 0x3008
#define OV5645_SYSTEM_CTRL0_START 0x02
#define OV5645_SYSTEM_CTRL0_STOP 0x42
#define OV5645_CHIP_ID_HIGH 0x300a
#define OV5645_CHIP_ID_HIGH_BYTE 0x56
#define OV5645_CHIP_ID_LOW 0x300b
#define OV5645_CHIP_ID_LOW_BYTE 0x45
#define OV5645_IO_MIPI_CTRL00 0x300e
#define OV5645_PAD_OUTPUT00 0x3019
#define OV5645_AWB_MANUAL_CONTROL 0x3406
#define OV5645_AWB_MANUAL_ENABLE BIT(0)
#define OV5645_AEC_PK_MANUAL 0x3503
#define OV5645_AEC_MANUAL_ENABLE BIT(0)
#define OV5645_AGC_MANUAL_ENABLE BIT(1)
#define OV5645_TIMING_TC_REG20 0x3820
#define OV5645_SENSOR_VFLIP BIT(1)
#define OV5645_ISP_VFLIP BIT(2)
#define OV5645_TIMING_TC_REG21 0x3821
#define OV5645_SENSOR_MIRROR BIT(1)
#define OV5645_MIPI_CTRL00 0x4800
#define OV5645_PRE_ISP_TEST_SETTING_1 0x503d
#define OV5645_TEST_PATTERN_MASK 0x3
#define OV5645_SET_TEST_PATTERN(x) ((x) & OV5645_TEST_PATTERN_MASK)
#define OV5645_TEST_PATTERN_ENABLE BIT(7)
#define OV5645_SDE_SAT_U 0x5583
#define OV5645_SDE_SAT_V 0x5584
/* regulator supplies */
static const char * const ov5645_supply_name[] = {
"vdddo", /* Digital I/O (1.8V) supply */
"vdda", /* Analog (2.8V) supply */
"vddd", /* Digital Core (1.5V) supply */
};
#define OV5645_NUM_SUPPLIES ARRAY_SIZE(ov5645_supply_name)
struct reg_value {
u16 reg;
u8 val;
};
struct ov5645_mode_info {
u32 width;
u32 height;
const struct reg_value *data;
u32 data_size;
u32 pixel_clock;
u32 link_freq;
};
struct ov5645 {
struct i2c_client *i2c_client;
struct device *dev;
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_fwnode_endpoint ep;
struct v4l2_mbus_framefmt fmt;
struct v4l2_rect crop;
struct clk *xclk;
struct regulator_bulk_data supplies[OV5645_NUM_SUPPLIES];
const struct ov5645_mode_info *current_mode;
struct v4l2_ctrl_handler ctrls;
struct v4l2_ctrl *pixel_clock;
struct v4l2_ctrl *link_freq;
/* Cached register values */
u8 aec_pk_manual;
u8 timing_tc_reg20;
u8 timing_tc_reg21;
struct mutex power_lock; /* lock to protect power state */
struct gpio_desc *enable_gpio;
struct gpio_desc *rst_gpio;
};
static inline struct ov5645 *to_ov5645(struct v4l2_subdev *sd)
{
return container_of(sd, struct ov5645, sd);
}
static const struct reg_value ov5645_global_init_setting[] = {
{ 0x3103, 0x11 },
{ 0x3008, 0x82 },
{ 0x3008, 0x42 },
{ 0x3103, 0x03 },
{ 0x3503, 0x07 },
{ 0x3002, 0x1c },
{ 0x3006, 0xc3 },
{ 0x3017, 0x00 },
{ 0x3018, 0x00 },
{ 0x302e, 0x0b },
{ 0x3037, 0x13 },
{ 0x3108, 0x01 },
{ 0x