^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");