// SPDX-License-Identifier: GPL-2.0
/*
* V4L2 sensor driver for Aptina MT9V111 image sensor
* Copyright (C) 2018 Jacopo Mondi <jacopo@jmondi.org>
*
* Based on mt9v032 driver
* Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
* Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
*
* Based on mt9v011 driver
* Copyright (c) 2009 Mauro Carvalho Chehab <mchehab@kernel.org>
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/v4l2-mediabus.h>
#include <linux/module.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-image-sizes.h>
#include <media/v4l2-subdev.h>
/*
* MT9V111 is a 1/4-Inch CMOS digital image sensor with an integrated
* Image Flow Processing (IFP) engine and a sensor core loosely based on
* MT9V011.
*
* The IFP can produce several output image formats from the sensor core
* output. This driver currently supports only YUYV format permutations.
*
* The driver allows manual frame rate control through s_frame_interval subdev
* operation or V4L2_CID_V/HBLANK controls, but it is known that the
* auto-exposure algorithm might modify the programmed frame rate. While the
* driver initially programs the sensor with auto-exposure and
* auto-white-balancing enabled, it is possible to disable them and more
* precisely control the frame rate.
*
* While it seems possible to instruct the auto-exposure control algorithm to
* respect a programmed frame rate when adjusting the pixel integration time,
* registers controlling this feature are not documented in the public
* available sensor manual used to develop this driver (09005aef80e90084,
* MT9V111_1.fm - Rev. G 1/05 EN).
*/
#define MT9V111_CHIP_ID_HIGH 0x82
#define MT9V111_CHIP_ID_LOW 0x3a
#define MT9V111_R01_ADDR_SPACE 0x01
#define MT9V111_R01_IFP 0x01
#define MT9V111_R01_CORE 0x04
#define MT9V111_IFP_R06_OPMODE_CTRL 0x06
#define MT9V111_IFP_R06_OPMODE_CTRL_AWB_EN BIT(1)
#define MT9V111_IFP_R06_OPMODE_CTRL_AE_EN BIT(14)
#define MT9V111_IFP_R07_IFP_RESET 0x07
#define MT9V111_IFP_R07_IFP_RESET_MASK BIT(0)
#define MT9V111_IFP_R08_OUTFMT_CTRL 0x08
#define MT9V111_IFP_R08_OUTFMT_CTRL_FLICKER BIT(11)
#define MT9V111_IFP_R08_OUTFMT_CTRL_PCLK BIT(5)
#define MT9V111_IFP_R3A_OUTFMT_CTRL2 0x3a
#define MT9V111_IFP_R3A_OUTFMT_CTRL2_SWAP_CBCR BIT(0)
#define MT9V111_IFP_R3A_OUTFMT_CTRL2_SWAP_YC BIT(1)
#define MT9V111_IFP_R3A_OUTFMT_CTRL2_SWAP_MASK GENMASK(2, 0)
#define MT9V111_IFP_RA5_HPAN 0xa5
#define MT9V111_IFP_RA6_HZOOM 0xa6
#define MT9V111_IFP_RA7_HOUT 0xa7
#define MT9V111_IFP_RA8_VPAN 0xa8
#define MT9V111_IFP_RA9_VZOOM 0xa9
#define MT9V111_IFP_RAA_VOUT 0xaa
#define MT9V111_IFP_DECIMATION_MASK GENMASK(9, 0)
#define MT9V111_IFP_DECIMATION_FREEZE BIT(15)
#define MT9V111_CORE_R03_WIN_HEIGHT 0x03
#define MT9V111_CORE_R03_WIN_V_OFFS 2
#define MT9V111_CORE_R04_WIN_WIDTH 0x04
#define MT9V111_CORE_R04_WIN_H_OFFS 114
#define MT9V111_CORE_R05_HBLANK 0x05
#define MT9V111_CORE_R05_MIN_HBLANK 0x09
#define MT9V111_CORE_R05_MAX_HBLANK GENMASK(9, 0)
#define MT9V111_CORE_R05_DEF_HBLANK 0x26
#define MT9V111_CORE_R06_VBLANK 0x06
#define MT9V111_CORE_R06_MIN_VBLANK 0x03
#define MT9V111_CORE_R06_MAX_VBLANK GENMASK(11, 0)
#define MT9V111_CORE_R06_DEF_VBLANK 0x04
#define MT9V111_CORE_R07_OUT_CTRL 0x07
#define MT9V111_CORE_R07_OUT_CTRL_SAMPLE BIT(4)
#define MT9V111_CORE_R09_PIXEL_INT 0x09
#define MT9V111_CORE_R09_PIXEL_INT_MASK GENMASK(11, 0)
#define MT9V111_CORE_R0D_CORE_RESET 0x0d
#define MT9V111_CORE_R0D_CORE_RESET_MASK BIT(0)
#define MT9V111_CORE_RFF_CHIP_VER 0xff
#define MT9V111_PIXEL_ARRAY_WIDTH 640
#define MT9V111_PIXEL_ARRAY_HEIGHT 480
#define MT9V111_MAX_CLKIN 27000000
/* The default sensor configuration at startup time. */
static struct v4l2_mbus_framefmt mt9v111_def_fmt = {
.width = 640,
.height = 480,
.code = MEDIA_BUS_FMT_UYVY8_2X8,
.field = V4L2_FIELD_NONE,
.colorspace = V4L2_COLORSPACE_SRGB,
.ycbcr_enc = V4L2_YCBCR_ENC_601,
.quantization = V4L2_QUANTIZATION_LIM_RANGE,
.xfer_func = V4L2_XFER_FUNC_SRGB,
};
struct mt9v111_dev {
struct device *dev;
struct i2c_client *client;
u8 addr_space;
struct v4l2_subdev sd;
#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
struct media_pad pad;
#endif
struct v4l2_ctrl *auto_awb;
struct v4l2_ctrl *auto_exp;
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *vblank;
struct v4l2_ctrl_handler ctrls;
/* Output image format and sizes. */
struct v4l2_mbus_framefmt fmt;
unsigned int fps;
/* Protects power up/down sequences. */
struct mutex pwr_mutex;
int pwr_count;
/* Protects stream on/off sequences. */
struct mutex stream_mutex;
bool streaming;
/* Flags to mark HW settings as not yet applied. */
bool pending;
/* Clock provider and system clock frequency. */
struct clk *clk;
u32 sysclk;
struct gpio_desc *oe;
struct gpio_desc *standby;
struct gpio_desc *reset;
};
#define sd_to_mt9v111(__sd) container_of((__sd), struct mt9v111_dev, sd)
/*
* mt9v111_mbus_fmt - List all media bus formats supported by the driver.
*
* Only list the media bus code here. The image sizes are fre