Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Driver for MT9T001 CMOS Image Sensor from Aptina (Micron)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2010-2011, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Based on the MT9M001 driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/log2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/v4l2-mediabus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <media/i2c/mt9t001.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <media/v4l2-subdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define MT9T001_PIXEL_ARRAY_HEIGHT			1568
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define MT9T001_PIXEL_ARRAY_WIDTH			2112
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define MT9T001_CHIP_VERSION				0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define		MT9T001_CHIP_ID				0x1621
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define MT9T001_ROW_START				0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define		MT9T001_ROW_START_MIN			0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define		MT9T001_ROW_START_DEF			20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define		MT9T001_ROW_START_MAX			1534
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define MT9T001_COLUMN_START				0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define		MT9T001_COLUMN_START_MIN		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define		MT9T001_COLUMN_START_DEF		32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define		MT9T001_COLUMN_START_MAX		2046
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define MT9T001_WINDOW_HEIGHT				0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define		MT9T001_WINDOW_HEIGHT_MIN		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define		MT9T001_WINDOW_HEIGHT_DEF		1535
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define		MT9T001_WINDOW_HEIGHT_MAX		1567
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define MT9T001_WINDOW_WIDTH				0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define		MT9T001_WINDOW_WIDTH_MIN		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define		MT9T001_WINDOW_WIDTH_DEF		2047
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define		MT9T001_WINDOW_WIDTH_MAX		2111
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define MT9T001_HORIZONTAL_BLANKING			0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define		MT9T001_HORIZONTAL_BLANKING_MIN		21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) #define		MT9T001_HORIZONTAL_BLANKING_MAX		1023
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) #define MT9T001_VERTICAL_BLANKING			0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define		MT9T001_VERTICAL_BLANKING_MIN		3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define		MT9T001_VERTICAL_BLANKING_MAX		1023
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) #define MT9T001_OUTPUT_CONTROL				0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) #define		MT9T001_OUTPUT_CONTROL_SYNC		(1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #define		MT9T001_OUTPUT_CONTROL_CHIP_ENABLE	(1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #define		MT9T001_OUTPUT_CONTROL_TEST_DATA	(1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define		MT9T001_OUTPUT_CONTROL_DEF		0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) #define MT9T001_SHUTTER_WIDTH_HIGH			0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) #define MT9T001_SHUTTER_WIDTH_LOW			0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) #define		MT9T001_SHUTTER_WIDTH_MIN		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) #define		MT9T001_SHUTTER_WIDTH_DEF		1561
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) #define		MT9T001_SHUTTER_WIDTH_MAX		(1024 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) #define MT9T001_PIXEL_CLOCK				0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) #define		MT9T001_PIXEL_CLOCK_INVERT		(1 << 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) #define		MT9T001_PIXEL_CLOCK_SHIFT_MASK		(7 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) #define		MT9T001_PIXEL_CLOCK_SHIFT_SHIFT		8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #define		MT9T001_PIXEL_CLOCK_DIVIDE_MASK		(0x7f << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) #define MT9T001_FRAME_RESTART				0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) #define MT9T001_SHUTTER_DELAY				0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) #define		MT9T001_SHUTTER_DELAY_MAX		2047
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) #define MT9T001_RESET					0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) #define MT9T001_READ_MODE1				0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) #define		MT9T001_READ_MODE_SNAPSHOT		(1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) #define		MT9T001_READ_MODE_STROBE_ENABLE		(1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) #define		MT9T001_READ_MODE_STROBE_WIDTH		(1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) #define		MT9T001_READ_MODE_STROBE_OVERRIDE	(1 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) #define MT9T001_READ_MODE2				0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) #define		MT9T001_READ_MODE_BAD_FRAMES		(1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) #define		MT9T001_READ_MODE_LINE_VALID_CONTINUOUS	(1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) #define		MT9T001_READ_MODE_LINE_VALID_FRAME	(1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) #define MT9T001_READ_MODE3				0x21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) #define		MT9T001_READ_MODE_GLOBAL_RESET		(1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) #define		MT9T001_READ_MODE_GHST_CTL		(1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) #define MT9T001_ROW_ADDRESS_MODE			0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) #define		MT9T001_ROW_SKIP_MASK			(7 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) #define		MT9T001_ROW_BIN_MASK			(3 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) #define		MT9T001_ROW_BIN_SHIFT			3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) #define MT9T001_COLUMN_ADDRESS_MODE			0x23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) #define		MT9T001_COLUMN_SKIP_MASK		(7 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) #define		MT9T001_COLUMN_BIN_MASK			(3 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) #define		MT9T001_COLUMN_BIN_SHIFT		3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) #define MT9T001_GREEN1_GAIN				0x2b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) #define MT9T001_BLUE_GAIN				0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) #define MT9T001_RED_GAIN				0x2d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) #define MT9T001_GREEN2_GAIN				0x2e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) #define MT9T001_TEST_DATA				0x32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) #define MT9T001_GLOBAL_GAIN				0x35
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) #define		MT9T001_GLOBAL_GAIN_MIN			8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) #define		MT9T001_GLOBAL_GAIN_MAX			1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define MT9T001_BLACK_LEVEL				0x49
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define MT9T001_ROW_BLACK_DEFAULT_OFFSET		0x4b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define MT9T001_BLC_DELTA_THRESHOLDS			0x5d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define MT9T001_CAL_THRESHOLDS				0x5f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define MT9T001_GREEN1_OFFSET				0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define MT9T001_GREEN2_OFFSET				0x61
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define MT9T001_BLACK_LEVEL_CALIBRATION			0x62
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define		MT9T001_BLACK_LEVEL_OVERRIDE		(1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define		MT9T001_BLACK_LEVEL_DISABLE_OFFSET	(1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define		MT9T001_BLACK_LEVEL_RECALCULATE		(1 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define		MT9T001_BLACK_LEVEL_LOCK_RED_BLUE	(1 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define		MT9T001_BLACK_LEVEL_LOCK_GREEN		(1 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define MT9T001_RED_OFFSET				0x63
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define MT9T001_BLUE_OFFSET				0x64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct mt9t001 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	struct v4l2_subdev subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	struct media_pad pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	struct regulator_bulk_data regulators[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	struct mutex power_lock; /* lock to protect power_count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	int power_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	struct v4l2_mbus_framefmt format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	struct v4l2_rect crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	struct v4l2_ctrl_handler ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	struct v4l2_ctrl *gains[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	u16 output_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	u16 black_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static inline struct mt9t001 *to_mt9t001(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	return container_of(sd, struct mt9t001, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static int mt9t001_read(struct i2c_client *client, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	return i2c_smbus_read_word_swapped(client, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	return i2c_smbus_write_word_swapped(client, reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 				      u16 set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	u16 value = (mt9t001->output_control & ~clear) | set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (value == mt9t001->output_control)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	ret = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	mt9t001->output_control = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static int mt9t001_reset(struct mt9t001 *mt9t001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	/* Reset the chip and stop data read out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	ret = mt9t001_write(client, MT9T001_RESET, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	ret = mt9t001_write(client, MT9T001_RESET, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	mt9t001->output_control = MT9T001_OUTPUT_CONTROL_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	return mt9t001_set_output_control(mt9t001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 					  MT9T001_OUTPUT_CONTROL_CHIP_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 					  0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int mt9t001_power_on(struct mt9t001 *mt9t001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	/* Bring up the supplies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	ret = regulator_bulk_enable(ARRAY_SIZE(mt9t001->regulators),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 				   mt9t001->regulators);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	/* Enable clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	ret = clk_prepare_enable(mt9t001->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		regulator_bulk_disable(ARRAY_SIZE(mt9t001->regulators),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 				       mt9t001->regulators);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void mt9t001_power_off(struct mt9t001 *mt9t001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	regulator_bulk_disable(ARRAY_SIZE(mt9t001->regulators),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 			       mt9t001->regulators);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	clk_disable_unprepare(mt9t001->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static int __mt9t001_set_power(struct mt9t001 *mt9t001, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	if (!on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		mt9t001_power_off(mt9t001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	ret = mt9t001_power_on(mt9t001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	ret = mt9t001_reset(mt9t001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		dev_err(&client->dev, "Failed to reset the camera\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		goto e_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	ret = v4l2_ctrl_handler_setup(&mt9t001->ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		dev_err(&client->dev, "Failed to set up control handlers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		goto e_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) e_power:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	mt9t001_power_off(mt9t001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)  * V4L2 subdev video operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static struct v4l2_mbus_framefmt *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) __mt9t001_get_pad_format(struct mt9t001 *mt9t001, struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 			 unsigned int pad, enum v4l2_subdev_format_whence which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	switch (which) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	case V4L2_SUBDEV_FORMAT_TRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		return v4l2_subdev_get_try_format(&mt9t001->subdev, cfg, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	case V4L2_SUBDEV_FORMAT_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		return &mt9t001->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static struct v4l2_rect *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) __mt9t001_get_pad_crop(struct mt9t001 *mt9t001, struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		       unsigned int pad, enum v4l2_subdev_format_whence which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	switch (which) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	case V4L2_SUBDEV_FORMAT_TRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		return v4l2_subdev_get_try_crop(&mt9t001->subdev, cfg, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	case V4L2_SUBDEV_FORMAT_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		return &mt9t001->crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	const u16 mode = MT9T001_OUTPUT_CONTROL_CHIP_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	struct i2c_client *client = v4l2_get_subdevdata(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	struct mt9t001_platform_data *pdata = client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	struct v4l2_mbus_framefmt *format = &mt9t001->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	struct v4l2_rect *crop = &mt9t001->crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	unsigned int hratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	unsigned int vratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	if (!enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		return mt9t001_set_output_control(mt9t001, mode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	/* Configure the pixel clock polarity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	if (pdata->clk_pol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		ret  = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 				     MT9T001_PIXEL_CLOCK_INVERT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	/* Configure the window size and row/column bin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	ret = mt9t001_write(client, MT9T001_ROW_ADDRESS_MODE, hratio - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	ret = mt9t001_write(client, MT9T001_COLUMN_ADDRESS_MODE, vratio - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	ret = mt9t001_write(client, MT9T001_COLUMN_START, crop->left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	ret = mt9t001_write(client, MT9T001_ROW_START, crop->top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	ret = mt9t001_write(client, MT9T001_WINDOW_WIDTH, crop->width - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	ret = mt9t001_write(client, MT9T001_WINDOW_HEIGHT, crop->height - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	/* Switch to master "normal" mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	return mt9t001_set_output_control(mt9t001, 0, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static int mt9t001_enum_mbus_code(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 				  struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 				  struct v4l2_subdev_mbus_code_enum *code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	if (code->index > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static int mt9t001_enum_frame_size(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 				   struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 				   struct v4l2_subdev_frame_size_enum *fse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	fse->min_width = (MT9T001_WINDOW_WIDTH_DEF + 1) / fse->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	fse->max_width = fse->min_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	fse->min_height = (MT9T001_WINDOW_HEIGHT_DEF + 1) / fse->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	fse->max_height = fse->min_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int mt9t001_get_format(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 			      struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			      struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	format->format = *__mt9t001_get_pad_format(mt9t001, cfg, format->pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 						   format->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static int mt9t001_set_format(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 			      struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 			      struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	struct v4l2_mbus_framefmt *__format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	struct v4l2_rect *__crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	unsigned int width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	unsigned int height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	unsigned int hratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	unsigned int vratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	__crop = __mt9t001_get_pad_crop(mt9t001, cfg, format->pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 					format->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	/* Clamp the width and height to avoid dividing by zero. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 			max_t(unsigned int, __crop->width / 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 			      MT9T001_WINDOW_HEIGHT_MIN + 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 			__crop->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 			 max_t(unsigned int, __crop->height / 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 			       MT9T001_WINDOW_HEIGHT_MIN + 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 			 __crop->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	hratio = DIV_ROUND_CLOSEST(__crop->width, width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	vratio = DIV_ROUND_CLOSEST(__crop->height, height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	__format = __mt9t001_get_pad_format(mt9t001, cfg, format->pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 					    format->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	__format->width = __crop->width / hratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	__format->height = __crop->height / vratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	format->format = *__format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static int mt9t001_get_selection(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 				 struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 				 struct v4l2_subdev_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	if (sel->target != V4L2_SEL_TGT_CROP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	sel->r = *__mt9t001_get_pad_crop(mt9t001, cfg, sel->pad, sel->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int mt9t001_set_selection(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 				 struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 				 struct v4l2_subdev_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	struct v4l2_mbus_framefmt *__format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	struct v4l2_rect *__crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	struct v4l2_rect rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	if (sel->target != V4L2_SEL_TGT_CROP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	 * pixels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	rect.left = clamp(ALIGN(sel->r.left, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 			  MT9T001_COLUMN_START_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 			  MT9T001_COLUMN_START_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	rect.top = clamp(ALIGN(sel->r.top, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 			 MT9T001_ROW_START_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 			 MT9T001_ROW_START_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 			     MT9T001_WINDOW_WIDTH_MIN + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 			     MT9T001_WINDOW_WIDTH_MAX + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 			      MT9T001_WINDOW_HEIGHT_MIN + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 			      MT9T001_WINDOW_HEIGHT_MAX + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	rect.width = min_t(unsigned int, rect.width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 			   MT9T001_PIXEL_ARRAY_WIDTH - rect.left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	rect.height = min_t(unsigned int, rect.height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 			    MT9T001_PIXEL_ARRAY_HEIGHT - rect.top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	__crop = __mt9t001_get_pad_crop(mt9t001, cfg, sel->pad, sel->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	if (rect.width != __crop->width || rect.height != __crop->height) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		/* Reset the output image size if the crop rectangle size has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		 * been modified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		__format = __mt9t001_get_pad_format(mt9t001, cfg, sel->pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 						    sel->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		__format->width = rect.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		__format->height = rect.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	*__crop = rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	sel->r = rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)  * V4L2 subdev control operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) #define V4L2_CID_TEST_PATTERN_COLOR	(V4L2_CID_USER_BASE | 0x1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) #define V4L2_CID_BLACK_LEVEL_AUTO	(V4L2_CID_USER_BASE | 0x1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) #define V4L2_CID_BLACK_LEVEL_OFFSET	(V4L2_CID_USER_BASE | 0x1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) #define V4L2_CID_BLACK_LEVEL_CALIBRATE	(V4L2_CID_USER_BASE | 0x1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) #define V4L2_CID_GAIN_RED		(V4L2_CTRL_CLASS_CAMERA | 0x1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) #define V4L2_CID_GAIN_GREEN_RED		(V4L2_CTRL_CLASS_CAMERA | 0x1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) #define V4L2_CID_GAIN_GREEN_BLUE	(V4L2_CTRL_CLASS_CAMERA | 0x1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) #define V4L2_CID_GAIN_BLUE		(V4L2_CTRL_CLASS_CAMERA | 0x1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static u16 mt9t001_gain_value(s32 *gain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	/* Gain is controlled by 2 analog stages and a digital stage. Valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	 * values for the 3 stages are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	 * Stage		Min	Max	Step
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	 * ------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	 * First analog stage	x1	x2	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	 * Second analog stage	x1	x4	0.125
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	 * Digital stage	x1	x16	0.125
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	 * To minimize noise, the gain stages should be used in the second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	 * analog stage, first analog stage, digital stage order. Gain from a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	 * previous stage should be pushed to its maximum value before the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	 * stage is used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	if (*gain <= 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 		return *gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	if (*gain <= 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		*gain &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		return (1 << 6) | (*gain >> 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	*gain &= ~7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	return ((*gain - 64) << 5) | (1 << 6) | 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static int mt9t001_ctrl_freeze(struct mt9t001 *mt9t001, bool freeze)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	return mt9t001_set_output_control(mt9t001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		freeze ? 0 : MT9T001_OUTPUT_CONTROL_SYNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		freeze ? MT9T001_OUTPUT_CONTROL_SYNC : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	static const u8 gains[4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 		MT9T001_RED_GAIN, MT9T001_GREEN1_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		MT9T001_GREEN2_GAIN, MT9T001_BLUE_GAIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	struct mt9t001 *mt9t001 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 			container_of(ctrl->handler, struct mt9t001, ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	unsigned int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	u16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	case V4L2_CID_GAIN_RED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	case V4L2_CID_GAIN_GREEN_RED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	case V4L2_CID_GAIN_GREEN_BLUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	case V4L2_CID_GAIN_BLUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		/* Disable control updates if more than one control has changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		 * in the cluster.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		for (i = 0, count = 0; i < 4; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 			struct v4l2_ctrl *gain = mt9t001->gains[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 			if (gain->val != gain->cur.val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 				count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		if (count > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 			ret = mt9t001_ctrl_freeze(mt9t001, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 			if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 		/* Update the gain controls. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		for (i = 0; i < 4; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 			struct v4l2_ctrl *gain = mt9t001->gains[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 			if (gain->val == gain->cur.val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 			value = mt9t001_gain_value(&gain->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 			ret = mt9t001_write(client, gains[i], value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 			if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 				mt9t001_ctrl_freeze(mt9t001, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 		/* Enable control updates. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		if (count > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 			ret = mt9t001_ctrl_freeze(mt9t001, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 			if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	case V4L2_CID_EXPOSURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		ret = mt9t001_write(client, MT9T001_SHUTTER_WIDTH_LOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 				    ctrl->val & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		return mt9t001_write(client, MT9T001_SHUTTER_WIDTH_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 				     ctrl->val >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	case V4L2_CID_TEST_PATTERN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 		return mt9t001_set_output_control(mt9t001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 			ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 			ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	case V4L2_CID_TEST_PATTERN_COLOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 		return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	case V4L2_CID_BLACK_LEVEL_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 		value = ctrl->val ? 0 : MT9T001_BLACK_LEVEL_OVERRIDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 		ret = mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 				    value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		mt9t001->black_level = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	case V4L2_CID_BLACK_LEVEL_OFFSET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 		ret = mt9t001_write(client, MT9T001_GREEN1_OFFSET, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 		ret = mt9t001_write(client, MT9T001_GREEN2_OFFSET, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 		ret = mt9t001_write(client, MT9T001_RED_OFFSET, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 		return mt9t001_write(client, MT9T001_BLUE_OFFSET, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	case V4L2_CID_BLACK_LEVEL_CALIBRATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		return mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 				     MT9T001_BLACK_LEVEL_RECALCULATE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 				     mt9t001->black_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static const struct v4l2_ctrl_ops mt9t001_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	.s_ctrl = mt9t001_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static const char * const mt9t001_test_pattern_menu[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	"Disabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	"Enabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) static const struct v4l2_ctrl_config mt9t001_ctrls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 		.ops		= &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 		.id		= V4L2_CID_TEST_PATTERN_COLOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 		.type		= V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 		.name		= "Test Pattern Color",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 		.min		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 		.max		= 1023,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 		.step		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 		.def		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 		.flags		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 		.ops		= &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 		.id		= V4L2_CID_BLACK_LEVEL_AUTO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 		.type		= V4L2_CTRL_TYPE_BOOLEAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 		.name		= "Black Level, Auto",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 		.min		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 		.max		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 		.step		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 		.def		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 		.flags		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 		.ops		= &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 		.id		= V4L2_CID_BLACK_LEVEL_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 		.type		= V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 		.name		= "Black Level, Offset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 		.min		= -256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 		.max		= 255,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 		.step		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 		.def		= 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 		.flags		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 		.ops		= &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 		.id		= V4L2_CID_BLACK_LEVEL_CALIBRATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		.type		= V4L2_CTRL_TYPE_BUTTON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 		.name		= "Black Level, Calibrate",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 		.min		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 		.max		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 		.step		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 		.def		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 		.flags		= V4L2_CTRL_FLAG_WRITE_ONLY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) static const struct v4l2_ctrl_config mt9t001_gains[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 		.ops		= &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 		.id		= V4L2_CID_GAIN_RED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 		.type		= V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 		.name		= "Gain, Red",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 		.min		= MT9T001_GLOBAL_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 		.max		= MT9T001_GLOBAL_GAIN_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 		.step		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 		.def		= MT9T001_GLOBAL_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 		.flags		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 		.ops		= &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 		.id		= V4L2_CID_GAIN_GREEN_RED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 		.type		= V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 		.name		= "Gain, Green (R)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 		.min		= MT9T001_GLOBAL_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 		.max		= MT9T001_GLOBAL_GAIN_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 		.step		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 		.def		= MT9T001_GLOBAL_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 		.flags		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 		.ops		= &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 		.id		= V4L2_CID_GAIN_GREEN_BLUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 		.type		= V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 		.name		= "Gain, Green (B)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 		.min		= MT9T001_GLOBAL_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 		.max		= MT9T001_GLOBAL_GAIN_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 		.step		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 		.def		= MT9T001_GLOBAL_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 		.flags		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 		.ops		= &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 		.id		= V4L2_CID_GAIN_BLUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 		.type		= V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 		.name		= "Gain, Blue",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 		.min		= MT9T001_GLOBAL_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 		.max		= MT9T001_GLOBAL_GAIN_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 		.step		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 		.def		= MT9T001_GLOBAL_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 		.flags		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)  * V4L2 subdev core operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) static int mt9t001_set_power(struct v4l2_subdev *subdev, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	mutex_lock(&mt9t001->power_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	/* If the power count is modified from 0 to != 0 or from != 0 to 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	 * update the power state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 	if (mt9t001->power_count == !on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 		ret = __mt9t001_set_power(mt9t001, !!on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	/* Update the power count. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	mt9t001->power_count += on ? 1 : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 	WARN_ON(mt9t001->power_count < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	mutex_unlock(&mt9t001->power_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)  * V4L2 subdev internal operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) static int mt9t001_registered(struct v4l2_subdev *subdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 	struct i2c_client *client = v4l2_get_subdevdata(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 	s32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	ret = mt9t001_power_on(mt9t001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 		dev_err(&client->dev, "MT9T001 power up failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 	/* Read out the chip version register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 	data = mt9t001_read(client, MT9T001_CHIP_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 	mt9t001_power_off(mt9t001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 	if (data != MT9T001_CHIP_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 		dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 			"MT9T001 not detected, wrong version 0x%04x\n", data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 	dev_info(&client->dev, "MT9T001 detected at address 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 		 client->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 	struct v4l2_mbus_framefmt *format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 	struct v4l2_rect *crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 	crop = v4l2_subdev_get_try_crop(subdev, fh->pad, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 	crop->left = MT9T001_COLUMN_START_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 	crop->top = MT9T001_ROW_START_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 	crop->width = MT9T001_WINDOW_WIDTH_DEF + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 	crop->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 	format = v4l2_subdev_get_try_format(subdev, fh->pad, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 	format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 	format->width = MT9T001_WINDOW_WIDTH_DEF + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 	format->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 	format->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 	format->colorspace = V4L2_COLORSPACE_SRGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 	return mt9t001_set_power(subdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) static int mt9t001_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 	return mt9t001_set_power(subdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) static const struct v4l2_subdev_core_ops mt9t001_subdev_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	.s_power = mt9t001_set_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static const struct v4l2_subdev_video_ops mt9t001_subdev_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 	.s_stream = mt9t001_s_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) static const struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 	.enum_mbus_code = mt9t001_enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 	.enum_frame_size = mt9t001_enum_frame_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 	.get_fmt = mt9t001_get_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	.set_fmt = mt9t001_set_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 	.get_selection = mt9t001_get_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 	.set_selection = mt9t001_set_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) static const struct v4l2_subdev_ops mt9t001_subdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 	.core = &mt9t001_subdev_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 	.video = &mt9t001_subdev_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 	.pad = &mt9t001_subdev_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) static const struct v4l2_subdev_internal_ops mt9t001_subdev_internal_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 	.registered = mt9t001_registered,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 	.open = mt9t001_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 	.close = mt9t001_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static int mt9t001_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 			 const struct i2c_device_id *did)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 	struct mt9t001_platform_data *pdata = client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	struct mt9t001 *mt9t001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 	if (pdata == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 		dev_err(&client->dev, "No platform data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 	if (!i2c_check_functionality(client->adapter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 				     I2C_FUNC_SMBUS_WORD_DATA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) 		dev_warn(&client->adapter->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 	mt9t001 = devm_kzalloc(&client->dev, sizeof(*mt9t001), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 	if (!mt9t001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) 	mutex_init(&mt9t001->power_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 	mt9t001->output_control = MT9T001_OUTPUT_CONTROL_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 	mt9t001->regulators[0].supply = "vdd";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 	mt9t001->regulators[1].supply = "vaa";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) 	ret = devm_regulator_bulk_get(&client->dev, 2, mt9t001->regulators);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 		dev_err(&client->dev, "Unable to get regulators\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 	mt9t001->clk = devm_clk_get(&client->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) 	if (IS_ERR(mt9t001->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) 		dev_err(&client->dev, "Unable to get clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 		return PTR_ERR(mt9t001->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) 	v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) 						ARRAY_SIZE(mt9t001_gains) + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) 	v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) 			  V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) 			  MT9T001_SHUTTER_WIDTH_MAX, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) 			  MT9T001_SHUTTER_WIDTH_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) 	v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) 			  V4L2_CID_BLACK_LEVEL, 1, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) 	v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) 			  V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) 			  1, pdata->ext_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 	v4l2_ctrl_new_std_menu_items(&mt9t001->ctrls, &mt9t001_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) 			V4L2_CID_TEST_PATTERN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) 			ARRAY_SIZE(mt9t001_test_pattern_menu) - 1, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) 			0, mt9t001_test_pattern_menu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) 	for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) 		v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) 	for (i = 0; i < ARRAY_SIZE(mt9t001_gains); ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) 		mt9t001->gains[i] = v4l2_ctrl_new_custom(&mt9t001->ctrls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) 			&mt9t001_gains[i], NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) 	v4l2_ctrl_cluster(ARRAY_SIZE(mt9t001_gains), mt9t001->gains);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) 	mt9t001->subdev.ctrl_handler = &mt9t001->ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 	if (mt9t001->ctrls.error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) 		printk(KERN_INFO "%s: control initialization error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) 		       __func__, mt9t001->ctrls.error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 		goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) 	mt9t001->crop.left = MT9T001_COLUMN_START_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) 	mt9t001->crop.top = MT9T001_ROW_START_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) 	mt9t001->crop.width = MT9T001_WINDOW_WIDTH_DEF + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 	mt9t001->crop.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 	mt9t001->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) 	mt9t001->format.width = MT9T001_WINDOW_WIDTH_DEF + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) 	mt9t001->format.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) 	mt9t001->format.field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) 	mt9t001->format.colorspace = V4L2_COLORSPACE_SRGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) 	v4l2_i2c_subdev_init(&mt9t001->subdev, client, &mt9t001_subdev_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) 	mt9t001->subdev.internal_ops = &mt9t001_subdev_internal_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) 	mt9t001->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) 	mt9t001->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) 	mt9t001->pad.flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) 	ret = media_entity_pads_init(&mt9t001->subdev.entity, 1, &mt9t001->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) 		v4l2_ctrl_handler_free(&mt9t001->ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) 		media_entity_cleanup(&mt9t001->subdev.entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static int mt9t001_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) 	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) 	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) 	v4l2_ctrl_handler_free(&mt9t001->ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) 	v4l2_device_unregister_subdev(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) 	media_entity_cleanup(&subdev->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) static const struct i2c_device_id mt9t001_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) 	{ "mt9t001", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) MODULE_DEVICE_TABLE(i2c, mt9t001_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) static struct i2c_driver mt9t001_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) 		.name = "mt9t001",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) 	.probe		= mt9t001_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) 	.remove		= mt9t001_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) 	.id_table	= mt9t001_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) module_i2c_driver(mt9t001_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) MODULE_LICENSE("GPL");