// SPDX-License-Identifier: GPL-2.0
/*
* Driver for OV5642 CMOS Image Sensor from Omnivision
*
* Copyright (C) 2011, Bastian Hecht <hechtb@gmail.com>
*
* Based on Sony IMX074 Camera Driver
* Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
*
* Based on Omnivision OV7670 Camera Driver
* Copyright (C) 2006-7 Jonathan Corbet <corbet@lwn.net>
*/
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/module.h>
#include <linux/v4l2-mediabus.h>
#include <media/soc_camera.h>
#include <media/v4l2-clk.h>
#include <media/v4l2-subdev.h>
/* OV5642 registers */
#define REG_CHIP_ID_HIGH 0x300a
#define REG_CHIP_ID_LOW 0x300b
#define REG_WINDOW_START_X_HIGH 0x3800
#define REG_WINDOW_START_X_LOW 0x3801
#define REG_WINDOW_START_Y_HIGH 0x3802
#define REG_WINDOW_START_Y_LOW 0x3803
#define REG_WINDOW_WIDTH_HIGH 0x3804
#define REG_WINDOW_WIDTH_LOW 0x3805
#define REG_WINDOW_HEIGHT_HIGH 0x3806
#define REG_WINDOW_HEIGHT_LOW 0x3807
#define REG_OUT_WIDTH_HIGH 0x3808
#define REG_OUT_WIDTH_LOW 0x3809
#define REG_OUT_HEIGHT_HIGH 0x380a
#define REG_OUT_HEIGHT_LOW 0x380b
#define REG_OUT_TOTAL_WIDTH_HIGH 0x380c
#define REG_OUT_TOTAL_WIDTH_LOW 0x380d
#define REG_OUT_TOTAL_HEIGHT_HIGH 0x380e
#define REG_OUT_TOTAL_HEIGHT_LOW 0x380f
#define REG_OUTPUT_FORMAT 0x4300
#define REG_ISP_CTRL_01 0x5001
#define REG_AVG_WINDOW_END_X_HIGH 0x5682
#define REG_AVG_WINDOW_END_X_LOW 0x5683
#define REG_AVG_WINDOW_END_Y_HIGH 0x5686
#define REG_AVG_WINDOW_END_Y_LOW 0x5687
/* active pixel array size */
#define OV5642_SENSOR_SIZE_X 2592
#define OV5642_SENSOR_SIZE_Y 1944
/*
* About OV5642 resolution, cropping and binning:
* This sensor supports it all, at least in the feature description.
* Unfortunately, no combination of appropriate registers settings could make
* the chip work the intended way. As it works with predefined register lists,
* some undocumented registers are presumably changed there to achieve their
* goals.
* This driver currently only works for resolutions up to 720 lines with a
* 1:1 scale. Hopefully these restrictions will be removed in the future.
*/
#define OV5642_MAX_WIDTH OV5642_SENSOR_SIZE_X
#define OV5642_MAX_HEIGHT 720
/* default sizes */
#define OV5642_DEFAULT_WIDTH 1280
#define OV5642_DEFAULT_HEIGHT OV5642_MAX_HEIGHT
/* minimum extra blanking */
#define BLANKING_EXTRA_WIDTH 500
#define BLANKING_EXTRA_HEIGHT 20
/*
* the sensor's autoexposure is buggy when setting total_height low.
* It tries to expose longer than 1 frame period without taking care of it
* and this leads to weird output. So we set 1000 lines as minimum.
*/
#define BLANKING_MIN_HEIGHT 1000
struct regval_list {
u16 reg_num;
u8 value;
};
static struct regval_list ov5642_default_regs_init[] = {
{ 0x3103, 0x93 },
{ 0x3008, 0x82 },
{ 0x3017, 0x7f },
{ 0x3018, 0xfc },
{ 0x3810, 0xc2 },
{ 0x3615, 0xf0 },
{ 0x3000, 0x0 },
{ 0x3001, 0x0 },
{ 0x3002, 0x0 },
{ 0x3003, 0x0 },
{ 0x3004, 0xff },
{ 0x3030, 0x2b },
{ 0x3011, 0x8 },
{ 0x3010, 0x10 },
{ 0x3604, 0x60 },
{ 0x3622, 0x60 },
{ 0x3621, 0x9 },
{ 0x3709, 0x0 },
{ 0x4000, 0x21 },
{ 0x401d, 0x22 },
{ 0x3600, 0x54 },
{ 0x3605, 0x4 },
{ 0x3606, 0x3f },
{ 0x3c01, 0x80 },
{ 0x300d, 0x22 },
{ 0x3623, 0x22 },
{ 0x5000, 0x4f },
{ 0x5020, 0x4 },
{ 0x5181, 0x79 },
{ 0x5182, 0x0 },
{ 0x5185, 0x22 },
{ 0x5197, 0x1 },
{ 0x5500, 0xa },
{ 0x5504, 0x0 },
{ 0x5505, 0x7f },
{ 0x5080, 0x8 },
{ 0x300e, 0x18 },
{ 0x4610, 0x0 },
{ 0x471d, 0x5 },
{ 0x4708, 0x6 },
{ 0x370c, 0xa0 },
{ 0x5687, 0x94 },
{ 0x501f, 0x0 },
{ 0x5000, 0x4f },
{ 0x5001, 0xcf },
{ 0x4300, 0x30 },
{ 0x4300, 0x30 },
{ 0x460b, 0x35 },
{ 0x471d, 0x0 },
{ 0x3002, 0xc },
{ 0x3002, 0x0 },
{ 0x4713, 0x3 },
{ 0x471c, 0x50 },
{ 0x4721, 0x2 },
{ 0x4402, 0x90 },
{ 0x460c, 0x22 },
{ 0x3815, 0x44 },
{ 0x3503, 0x7 },
{ 0x3501, 0x73 },
{