^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 MT9V022, MT9V024, MT9V032, and MT9V034 CMOS Image Sensors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010, 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/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/log2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of_graph.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/v4l2-mediabus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <media/i2c/mt9v032.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <media/v4l2-fwnode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <media/v4l2-subdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* The first four rows are black rows. The active area spans 753x481 pixels. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define MT9V032_PIXEL_ARRAY_HEIGHT 485
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define MT9V032_PIXEL_ARRAY_WIDTH 753
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define MT9V032_SYSCLK_FREQ_DEF 26600000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MT9V032_CHIP_VERSION 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define MT9V032_CHIP_ID_REV1 0x1311
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define MT9V032_CHIP_ID_REV3 0x1313
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define MT9V034_CHIP_ID_REV1 0X1324
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define MT9V032_COLUMN_START 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MT9V032_COLUMN_START_MIN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define MT9V032_COLUMN_START_DEF 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define MT9V032_COLUMN_START_MAX 752
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define MT9V032_ROW_START 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define MT9V032_ROW_START_MIN 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define MT9V032_ROW_START_DEF 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define MT9V032_ROW_START_MAX 482
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define MT9V032_WINDOW_HEIGHT 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define MT9V032_WINDOW_HEIGHT_MIN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define MT9V032_WINDOW_HEIGHT_DEF 480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define MT9V032_WINDOW_HEIGHT_MAX 480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define MT9V032_WINDOW_WIDTH 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define MT9V032_WINDOW_WIDTH_MIN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define MT9V032_WINDOW_WIDTH_DEF 752
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define MT9V032_WINDOW_WIDTH_MAX 752
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define MT9V032_HORIZONTAL_BLANKING 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define MT9V032_HORIZONTAL_BLANKING_MIN 43
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define MT9V034_HORIZONTAL_BLANKING_MIN 61
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define MT9V032_HORIZONTAL_BLANKING_DEF 94
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define MT9V032_HORIZONTAL_BLANKING_MAX 1023
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define MT9V032_VERTICAL_BLANKING 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define MT9V032_VERTICAL_BLANKING_MIN 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define MT9V034_VERTICAL_BLANKING_MIN 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define MT9V032_VERTICAL_BLANKING_DEF 45
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define MT9V032_VERTICAL_BLANKING_MAX 3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define MT9V034_VERTICAL_BLANKING_MAX 32288
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define MT9V032_CHIP_CONTROL 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define MT9V032_CHIP_CONTROL_MASTER_MODE (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define MT9V032_CHIP_CONTROL_DOUT_ENABLE (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define MT9V032_CHIP_CONTROL_SEQUENTIAL (1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define MT9V032_SHUTTER_WIDTH1 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define MT9V032_SHUTTER_WIDTH2 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define MT9V032_SHUTTER_WIDTH_CONTROL 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define MT9V032_TOTAL_SHUTTER_WIDTH 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define MT9V032_TOTAL_SHUTTER_WIDTH_MIN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define MT9V034_TOTAL_SHUTTER_WIDTH_MIN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define MT9V032_TOTAL_SHUTTER_WIDTH_DEF 480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define MT9V032_TOTAL_SHUTTER_WIDTH_MAX 32767
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define MT9V034_TOTAL_SHUTTER_WIDTH_MAX 32765
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define MT9V032_RESET 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define MT9V032_READ_MODE 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define MT9V032_READ_MODE_ROW_BIN_MASK (3 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define MT9V032_READ_MODE_ROW_BIN_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define MT9V032_READ_MODE_COLUMN_BIN_MASK (3 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define MT9V032_READ_MODE_COLUMN_BIN_SHIFT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define MT9V032_READ_MODE_ROW_FLIP (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define MT9V032_READ_MODE_DARK_ROWS (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define MT9V032_READ_MODE_RESERVED 0x0300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define MT9V032_PIXEL_OPERATION_MODE 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define MT9V032_PIXEL_OPERATION_MODE_COLOR (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define MT9V032_PIXEL_OPERATION_MODE_HDR (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define MT9V032_ANALOG_GAIN 0x35
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define MT9V032_ANALOG_GAIN_MIN 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define MT9V032_ANALOG_GAIN_DEF 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define MT9V032_ANALOG_GAIN_MAX 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define MT9V032_MAX_ANALOG_GAIN 0x36
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define MT9V032_MAX_ANALOG_GAIN_MAX 127
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define MT9V032_FRAME_DARK_AVERAGE 0x42
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define MT9V032_DARK_AVG_THRESH 0x46
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define MT9V032_DARK_AVG_LOW_THRESH_MASK (255 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define MT9V032_DARK_AVG_LOW_THRESH_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define MT9V032_DARK_AVG_HIGH_THRESH_MASK (255 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define MT9V032_DARK_AVG_HIGH_THRESH_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define MT9V032_ROW_NOISE_CORR_CONTROL 0x70
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define MT9V034_ROW_NOISE_CORR_ENABLE (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define MT9V034_ROW_NOISE_CORR_USE_BLK_AVG (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define MT9V032_ROW_NOISE_CORR_ENABLE (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define MT9V032_ROW_NOISE_CORR_USE_BLK_AVG (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define MT9V032_PIXEL_CLOCK 0x74
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define MT9V034_PIXEL_CLOCK 0x72
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define MT9V032_PIXEL_CLOCK_INV_LINE (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define MT9V032_PIXEL_CLOCK_INV_FRAME (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define MT9V032_PIXEL_CLOCK_XOR_LINE (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define MT9V032_PIXEL_CLOCK_CONT_LINE (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define MT9V032_PIXEL_CLOCK_INV_PXL_CLK (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define MT9V032_TEST_PATTERN 0x7f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define MT9V032_TEST_PATTERN_DATA_MASK (1023 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define MT9V032_TEST_PATTERN_DATA_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define MT9V032_TEST_PATTERN_USE_DATA (1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define MT9V032_TEST_PATTERN_GRAY_MASK (3 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define MT9V032_TEST_PATTERN_GRAY_NONE (0 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define MT9V032_TEST_PATTERN_GRAY_VERTICAL (1 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define MT9V032_TEST_PATTERN_GRAY_HORIZONTAL (2 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define MT9V032_TEST_PATTERN_GRAY_DIAGONAL (3 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define MT9V032_TEST_PATTERN_ENABLE (1 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define MT9V032_TEST_PATTERN_FLIP (1 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define MT9V032_AEGC_DESIRED_BIN 0xa5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define MT9V032_AEC_UPDATE_FREQUENCY 0xa6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define MT9V032_AEC_LPF 0xa8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define MT9V032_AGC_UPDATE_FREQUENCY 0xa9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define MT9V032_AGC_LPF 0xaa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define MT9V032_AEC_AGC_ENABLE 0xaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define MT9V032_AEC_ENABLE (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define MT9V032_AGC_ENABLE (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define MT9V034_AEC_MAX_SHUTTER_WIDTH 0xad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define MT9V032_AEC_MAX_SHUTTER_WIDTH 0xbd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define MT9V032_THERMAL_INFO 0xc1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) enum mt9v032_model {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) MT9V032_MODEL_V022_COLOR, /* MT9V022IX7ATC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) MT9V032_MODEL_V022_MONO, /* MT9V022IX7ATM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) MT9V032_MODEL_V024_COLOR, /* MT9V024IA7XTC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) MT9V032_MODEL_V024_MONO, /* MT9V024IA7XTM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) MT9V032_MODEL_V032_COLOR, /* MT9V032C12STM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) MT9V032_MODEL_V032_MONO, /* MT9V032C12STC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) MT9V032_MODEL_V034_COLOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) MT9V032_MODEL_V034_MONO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct mt9v032_model_version {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) unsigned int version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct mt9v032_model_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) unsigned int min_row_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned int min_hblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) unsigned int min_vblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) unsigned int max_vblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned int min_shutter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned int max_shutter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned int pclk_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) unsigned int aec_max_shutter_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) const struct v4l2_ctrl_config * const aec_max_shutter_v4l2_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct mt9v032_model_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) const struct mt9v032_model_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) bool color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static const struct mt9v032_model_version mt9v032_versions[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) { MT9V032_CHIP_ID_REV1, "MT9V022/MT9V032 rev1/2" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) { MT9V032_CHIP_ID_REV3, "MT9V022/MT9V032 rev3" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) { MT9V034_CHIP_ID_REV1, "MT9V024/MT9V034 rev1" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct mt9v032 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct v4l2_subdev subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct media_pad pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct v4l2_mbus_framefmt format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct v4l2_rect crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unsigned int hratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned int vratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct v4l2_ctrl_handler ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct v4l2_ctrl *link_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct v4l2_ctrl *pixel_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct mutex power_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int power_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct gpio_desc *reset_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct gpio_desc *standby_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct mt9v032_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) const struct mt9v032_model_info *model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) const struct mt9v032_model_version *version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u32 sysclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) u16 aec_agc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) u16 hblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct v4l2_ctrl *test_pattern;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct v4l2_ctrl *test_pattern_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return container_of(sd, struct mt9v032, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct regmap *map = mt9v032->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u16 value = mt9v032->aec_agc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) value |= which;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) value &= ~which;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ret = regmap_write(map, MT9V032_AEC_AGC_ENABLE, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) mt9v032->aec_agc = value;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) mt9v032_update_hblank(struct mt9v032 *mt9v032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct v4l2_rect *crop = &mt9v032->crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned int min_hblank = mt9v032->model->data->min_hblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) unsigned int hblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (mt9v032->version->version == MT9V034_CHIP_ID_REV1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) min_hblank += (mt9v032->hratio - 1) * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) min_hblank = max_t(int, mt9v032->model->data->min_row_time - crop->width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) min_hblank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) hblank = max_t(unsigned int, mt9v032->hblank, min_hblank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return regmap_write(mt9v032->regmap, MT9V032_HORIZONTAL_BLANKING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) hblank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static int mt9v032_power_on(struct mt9v032 *mt9v032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct regmap *map = mt9v032->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) gpiod_set_value_cansleep(mt9v032->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* System clock has to be enabled before releasing the reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ret = clk_prepare_enable(mt9v032->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (mt9v032->reset_gpio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) gpiod_set_value_cansleep(mt9v032->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* After releasing reset we need to wait 10 clock cycles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * before accessing the sensor over I2C. As the minimum SYSCLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * frequency is 13MHz, waiting 1µs will be enough in the worst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Reset the chip and stop data read out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ret = regmap_write(map, MT9V032_RESET, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) ret = regmap_write(map, MT9V032_RESET, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) ret = regmap_write(map, MT9V032_CHIP_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) MT9V032_CHIP_CONTROL_MASTER_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) clk_disable_unprepare(mt9v032->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static void mt9v032_power_off(struct mt9v032 *mt9v032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) clk_disable_unprepare(mt9v032->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct regmap *map = mt9v032->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (!on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) mt9v032_power_off(mt9v032);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) ret = mt9v032_power_on(mt9v032);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /* Configure the pixel clock polarity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ret = regmap_write(map, mt9v032->model->data->pclk_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* Disable the noise correction algorithm and restore the controls. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) ret = regmap_write(map, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return v4l2_ctrl_handler_setup(&mt9v032->ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^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) * V4L2 subdev video operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static struct v4l2_mbus_framefmt *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) __mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) unsigned int pad, enum v4l2_subdev_format_whence which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) switch (which) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) case V4L2_SUBDEV_FORMAT_TRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return v4l2_subdev_get_try_format(&mt9v032->subdev, cfg, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) case V4L2_SUBDEV_FORMAT_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return &mt9v032->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static struct v4l2_rect *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) __mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) unsigned int pad, enum v4l2_subdev_format_whence which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) switch (which) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) case V4L2_SUBDEV_FORMAT_TRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return v4l2_subdev_get_try_crop(&mt9v032->subdev, cfg, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case V4L2_SUBDEV_FORMAT_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return &mt9v032->crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) const u16 mode = MT9V032_CHIP_CONTROL_DOUT_ENABLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) | MT9V032_CHIP_CONTROL_SEQUENTIAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct mt9v032 *mt9v032 = to_mt9v032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct v4l2_rect *crop = &mt9v032->crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct regmap *map = mt9v032->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) unsigned int hbin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) unsigned int vbin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (!enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* Configure the window size and row/column bin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) hbin = fls(mt9v032->hratio) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) vbin = fls(mt9v032->vratio) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) ret = regmap_update_bits(map, MT9V032_READ_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) ~MT9V032_READ_MODE_RESERVED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) ret = regmap_write(map, MT9V032_COLUMN_START, crop->left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ret = regmap_write(map, MT9V032_ROW_START, crop->top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ret = regmap_write(map, MT9V032_WINDOW_WIDTH, crop->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) ret = regmap_write(map, MT9V032_WINDOW_HEIGHT, crop->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ret = mt9v032_update_hblank(mt9v032);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* Switch to master "normal" mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct v4l2_subdev_mbus_code_enum *code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) struct mt9v032 *mt9v032 = to_mt9v032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (code->index > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) code->code = mt9v032->format.code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct v4l2_subdev_frame_size_enum *fse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct mt9v032 *mt9v032 = to_mt9v032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (fse->index >= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (mt9v032->format.code != fse->code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) fse->min_width = MT9V032_WINDOW_WIDTH_DEF / (1 << fse->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) fse->max_width = fse->min_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / (1 << fse->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) fse->max_height = fse->min_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static int mt9v032_get_format(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) struct mt9v032 *mt9v032 = to_mt9v032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) format->format = *__mt9v032_get_pad_format(mt9v032, cfg, format->pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) format->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return 0;
^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) static void mt9v032_configure_pixel_rate(struct mt9v032 *mt9v032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) mt9v032->sysclk / mt9v032->hratio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static unsigned int mt9v032_calc_ratio(unsigned int input, unsigned int output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* Compute the power-of-two binning factor closest to the input size to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * output size ratio. Given that the output size is bounded by input/4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * and input, a generic implementation would be an ineffective luxury.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (output * 3 > input * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (output * 3 > input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static int mt9v032_set_format(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct mt9v032 *mt9v032 = to_mt9v032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct v4l2_mbus_framefmt *__format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct v4l2_rect *__crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) unsigned int width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) unsigned int height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) unsigned int hratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) unsigned int vratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) __crop = __mt9v032_get_pad_crop(mt9v032, cfg, format->pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) format->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /* Clamp the width and height to avoid dividing by zero. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) width = clamp(ALIGN(format->format.width, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) max_t(unsigned int, __crop->width / 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) MT9V032_WINDOW_WIDTH_MIN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) __crop->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) height = clamp(ALIGN(format->format.height, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) max_t(unsigned int, __crop->height / 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) MT9V032_WINDOW_HEIGHT_MIN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) __crop->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) hratio = mt9v032_calc_ratio(__crop->width, width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) vratio = mt9v032_calc_ratio(__crop->height, height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) __format = __mt9v032_get_pad_format(mt9v032, cfg, format->pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) format->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) __format->width = __crop->width / hratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) __format->height = __crop->height / vratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) mt9v032->hratio = hratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) mt9v032->vratio = vratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) mt9v032_configure_pixel_rate(mt9v032);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) format->format = *__format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static int mt9v032_get_selection(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct v4l2_subdev_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct mt9v032 *mt9v032 = to_mt9v032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (sel->target != V4L2_SEL_TGT_CROP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) sel->r = *__mt9v032_get_pad_crop(mt9v032, cfg, sel->pad, sel->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) static int mt9v032_set_selection(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct v4l2_subdev_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct mt9v032 *mt9v032 = to_mt9v032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct v4l2_mbus_framefmt *__format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct v4l2_rect *__crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct v4l2_rect rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (sel->target != V4L2_SEL_TGT_CROP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) /* Clamp the crop rectangle boundaries and align them to a non multiple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * of 2 pixels to ensure a GRBG Bayer pattern.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) rect.left = clamp(ALIGN(sel->r.left + 1, 2) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) MT9V032_COLUMN_START_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) MT9V032_COLUMN_START_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) rect.top = clamp(ALIGN(sel->r.top + 1, 2) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) MT9V032_ROW_START_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) MT9V032_ROW_START_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) MT9V032_WINDOW_WIDTH_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) MT9V032_WINDOW_WIDTH_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) MT9V032_WINDOW_HEIGHT_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) MT9V032_WINDOW_HEIGHT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) rect.width = min_t(unsigned int,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) rect.width, MT9V032_PIXEL_ARRAY_WIDTH - rect.left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) rect.height = min_t(unsigned int,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) __crop = __mt9v032_get_pad_crop(mt9v032, cfg, sel->pad, sel->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (rect.width != __crop->width || rect.height != __crop->height) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /* Reset the output image size if the crop rectangle size has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * been modified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) __format = __mt9v032_get_pad_format(mt9v032, cfg, sel->pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) sel->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) __format->width = rect.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) __format->height = rect.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) mt9v032->hratio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) mt9v032->vratio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) mt9v032_configure_pixel_rate(mt9v032);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) *__crop = rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) sel->r = rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * V4L2 subdev control operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) #define V4L2_CID_TEST_PATTERN_COLOR (V4L2_CID_USER_BASE | 0x1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * Value between 1 and 64 to set the desired bin. This is effectively a measure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * of how bright the image is supposed to be. Both AGC and AEC try to reach
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) #define V4L2_CID_AEGC_DESIRED_BIN (V4L2_CID_USER_BASE | 0x1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * LPF is the low pass filter capability of the chip. Both AEC and AGC have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * this setting. This limits the speed in which AGC/AEC adjust their settings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * Possible values are 0-2. 0 means no LPF. For 1 and 2 this equation is used:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * if |(calculated new exp - current exp)| > (current exp / 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * next exp = calculated new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * next exp = current exp + ((calculated new exp - current exp) / 2^LPF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) #define V4L2_CID_AEC_LPF (V4L2_CID_USER_BASE | 0x1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) #define V4L2_CID_AGC_LPF (V4L2_CID_USER_BASE | 0x1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * Value between 0 and 15. This is the number of frames being skipped before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * updating the auto exposure/gain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) #define V4L2_CID_AEC_UPDATE_INTERVAL (V4L2_CID_USER_BASE | 0x1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) #define V4L2_CID_AGC_UPDATE_INTERVAL (V4L2_CID_USER_BASE | 0x1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * Maximum shutter width used for AEC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) #define V4L2_CID_AEC_MAX_SHUTTER_WIDTH (V4L2_CID_USER_BASE | 0x1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct mt9v032 *mt9v032 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) container_of(ctrl->handler, struct mt9v032, ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct regmap *map = mt9v032->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) u32 freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) u16 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case V4L2_CID_AUTOGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return mt9v032_update_aec_agc(mt9v032, MT9V032_AGC_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) case V4L2_CID_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return regmap_write(map, MT9V032_ANALOG_GAIN, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) case V4L2_CID_EXPOSURE_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) !ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) case V4L2_CID_EXPOSURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return regmap_write(map, MT9V032_TOTAL_SHUTTER_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) case V4L2_CID_HBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) mt9v032->hblank = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return mt9v032_update_hblank(mt9v032);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) case V4L2_CID_VBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return regmap_write(map, MT9V032_VERTICAL_BLANKING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) case V4L2_CID_PIXEL_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) case V4L2_CID_LINK_FREQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (mt9v032->link_freq == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) *mt9v032->pixel_rate->p_new.p_s64 = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) mt9v032->sysclk = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) case V4L2_CID_TEST_PATTERN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) switch (mt9v032->test_pattern->val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) data = MT9V032_TEST_PATTERN_GRAY_VERTICAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) | MT9V032_TEST_PATTERN_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) data = MT9V032_TEST_PATTERN_GRAY_HORIZONTAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) | MT9V032_TEST_PATTERN_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) data = MT9V032_TEST_PATTERN_GRAY_DIAGONAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) | MT9V032_TEST_PATTERN_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) data = (mt9v032->test_pattern_color->val <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) MT9V032_TEST_PATTERN_DATA_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) | MT9V032_TEST_PATTERN_USE_DATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) | MT9V032_TEST_PATTERN_ENABLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) | MT9V032_TEST_PATTERN_FLIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return regmap_write(map, MT9V032_TEST_PATTERN, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) case V4L2_CID_AEGC_DESIRED_BIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return regmap_write(map, MT9V032_AEGC_DESIRED_BIN, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) case V4L2_CID_AEC_LPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return regmap_write(map, MT9V032_AEC_LPF, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) case V4L2_CID_AGC_LPF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return regmap_write(map, MT9V032_AGC_LPF, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) case V4L2_CID_AEC_UPDATE_INTERVAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return regmap_write(map, MT9V032_AEC_UPDATE_FREQUENCY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) case V4L2_CID_AGC_UPDATE_INTERVAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return regmap_write(map, MT9V032_AGC_UPDATE_FREQUENCY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) case V4L2_CID_AEC_MAX_SHUTTER_WIDTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return regmap_write(map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) mt9v032->model->data->aec_max_shutter_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) ctrl->val);
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static const struct v4l2_ctrl_ops mt9v032_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) .s_ctrl = mt9v032_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static const char * const mt9v032_test_pattern_menu[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) "Disabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) "Gray Vertical Shade",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) "Gray Horizontal Shade",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) "Gray Diagonal Shade",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) "Plain",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static const struct v4l2_ctrl_config mt9v032_test_pattern_color = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) .ops = &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) .id = V4L2_CID_TEST_PATTERN_COLOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) .name = "Test Pattern Color",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) .min = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) .max = 1023,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) .def = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static const struct v4l2_ctrl_config mt9v032_aegc_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) .ops = &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) .id = V4L2_CID_AEGC_DESIRED_BIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) .name = "AEC/AGC Desired Bin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) .min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) .max = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .def = 58,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .ops = &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) .id = V4L2_CID_AEC_LPF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) .name = "AEC Low Pass Filter",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) .min = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) .max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) .def = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) .ops = &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) .id = V4L2_CID_AGC_LPF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .name = "AGC Low Pass Filter",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .min = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) .max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .def = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .ops = &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .id = V4L2_CID_AEC_UPDATE_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .name = "AEC Update Interval",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .min = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) .max = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .def = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) .ops = &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) .id = V4L2_CID_AGC_UPDATE_INTERVAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .name = "AGC Update Interval",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .min = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) .max = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) .def = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static const struct v4l2_ctrl_config mt9v032_aec_max_shutter_width = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) .ops = &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) .id = V4L2_CID_AEC_MAX_SHUTTER_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) .name = "AEC Max Shutter Width",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) .min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) .max = 2047,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) .def = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) .flags = 0,
^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_ctrl_config mt9v034_aec_max_shutter_width = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) .ops = &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) .id = V4L2_CID_AEC_MAX_SHUTTER_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) .type = V4L2_CTRL_TYPE_INTEGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) .name = "AEC Max Shutter Width",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) .min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) .max = 32765,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) .step = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) .def = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) };
^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) * V4L2 subdev core operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static int mt9v032_set_power(struct v4l2_subdev *subdev, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct mt9v032 *mt9v032 = to_mt9v032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) mutex_lock(&mt9v032->power_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /* If the power count is modified from 0 to != 0 or from != 0 to 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * update the power state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (mt9v032->power_count == !on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) ret = __mt9v032_set_power(mt9v032, !!on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) /* Update the power count. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) mt9v032->power_count += on ? 1 : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) WARN_ON(mt9v032->power_count < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) mutex_unlock(&mt9v032->power_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * V4L2 subdev internal operations
^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) static int mt9v032_registered(struct v4l2_subdev *subdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) struct i2c_client *client = v4l2_get_subdevdata(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct mt9v032 *mt9v032 = to_mt9v032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) u32 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) client->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) ret = mt9v032_power_on(mt9v032);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) dev_err(&client->dev, "MT9V032 power up failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /* Read and check the sensor version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) ret = regmap_read(mt9v032->regmap, MT9V032_CHIP_VERSION, &version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) mt9v032_power_off(mt9v032);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) dev_err(&client->dev, "Failed reading chip version\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) for (i = 0; i < ARRAY_SIZE(mt9v032_versions); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (mt9v032_versions[i].version == version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) mt9v032->version = &mt9v032_versions[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (mt9v032->version == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) dev_err(&client->dev, "Unsupported chip version 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) dev_info(&client->dev, "%s detected at address 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) mt9v032->version->name, client->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) mt9v032_configure_pixel_rate(mt9v032);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct mt9v032 *mt9v032 = to_mt9v032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) struct v4l2_mbus_framefmt *format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct v4l2_rect *crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) crop = v4l2_subdev_get_try_crop(subdev, fh->pad, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) crop->left = MT9V032_COLUMN_START_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) crop->top = MT9V032_ROW_START_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) crop->width = MT9V032_WINDOW_WIDTH_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) crop->height = MT9V032_WINDOW_HEIGHT_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) format = v4l2_subdev_get_try_format(subdev, fh->pad, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (mt9v032->model->color)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) format->code = MEDIA_BUS_FMT_Y10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) format->width = MT9V032_WINDOW_WIDTH_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) format->height = MT9V032_WINDOW_HEIGHT_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) format->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) format->colorspace = V4L2_COLORSPACE_SRGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return mt9v032_set_power(subdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) static int mt9v032_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return mt9v032_set_power(subdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) static const struct v4l2_subdev_core_ops mt9v032_subdev_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) .s_power = mt9v032_set_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) static const struct v4l2_subdev_video_ops mt9v032_subdev_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) .s_stream = mt9v032_s_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) static const struct v4l2_subdev_pad_ops mt9v032_subdev_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) .enum_mbus_code = mt9v032_enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) .enum_frame_size = mt9v032_enum_frame_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) .get_fmt = mt9v032_get_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) .set_fmt = mt9v032_set_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) .get_selection = mt9v032_get_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) .set_selection = mt9v032_set_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) static const struct v4l2_subdev_ops mt9v032_subdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) .core = &mt9v032_subdev_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) .video = &mt9v032_subdev_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) .pad = &mt9v032_subdev_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) .registered = mt9v032_registered,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) .open = mt9v032_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) .close = mt9v032_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) static const struct regmap_config mt9v032_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) .val_bits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) .max_register = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) .cache_type = REGCACHE_RBTREE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) * Driver initialization and probing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) static struct mt9v032_platform_data *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) mt9v032_get_pdata(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) struct mt9v032_platform_data *pdata = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) np = of_graph_get_next_endpoint(client->dev.of_node, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (!np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &endpoint) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) prop = of_find_property(np, "link-frequencies", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) u64 *link_freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) size_t size = prop->length / sizeof(*link_freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) link_freqs = devm_kcalloc(&client->dev, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) sizeof(*link_freqs), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (!link_freqs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (of_property_read_u64_array(np, "link-frequencies",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) link_freqs, size) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) pdata->link_freqs = link_freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) pdata->link_def_freq = link_freqs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) pdata->clk_pol = !!(endpoint.bus.parallel.flags &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) V4L2_MBUS_PCLK_SAMPLE_RISING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static int mt9v032_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) const struct i2c_device_id *did)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) struct mt9v032_platform_data *pdata = mt9v032_get_pdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) struct mt9v032 *mt9v032;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) mt9v032 = devm_kzalloc(&client->dev, sizeof(*mt9v032), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (!mt9v032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) mt9v032->regmap = devm_regmap_init_i2c(client, &mt9v032_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (IS_ERR(mt9v032->regmap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return PTR_ERR(mt9v032->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) mt9v032->clk = devm_clk_get(&client->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (IS_ERR(mt9v032->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return PTR_ERR(mt9v032->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) mt9v032->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (IS_ERR(mt9v032->reset_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) return PTR_ERR(mt9v032->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) mt9v032->standby_gpio = devm_gpiod_get_optional(&client->dev, "standby",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (IS_ERR(mt9v032->standby_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) return PTR_ERR(mt9v032->standby_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) mutex_init(&mt9v032->power_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) mt9v032->pdata = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) mt9v032->model = (const void *)did->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) v4l2_ctrl_handler_init(&mt9v032->ctrls, 11 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) ARRAY_SIZE(mt9v032_aegc_controls));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) V4L2_CID_GAIN, MT9V032_ANALOG_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) MT9V032_ANALOG_GAIN_MAX, 1, MT9V032_ANALOG_GAIN_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) v4l2_ctrl_new_std_menu(&mt9v032->ctrls, &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) V4L2_EXPOSURE_AUTO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) V4L2_CID_EXPOSURE, mt9v032->model->data->min_shutter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) mt9v032->model->data->max_shutter, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) MT9V032_TOTAL_SHUTTER_WIDTH_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) V4L2_CID_HBLANK, mt9v032->model->data->min_hblank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) MT9V032_HORIZONTAL_BLANKING_MAX, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) MT9V032_HORIZONTAL_BLANKING_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) V4L2_CID_VBLANK, mt9v032->model->data->min_vblank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) mt9v032->model->data->max_vblank, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) MT9V032_VERTICAL_BLANKING_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) mt9v032->test_pattern = v4l2_ctrl_new_std_menu_items(&mt9v032->ctrls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) &mt9v032_ctrl_ops, V4L2_CID_TEST_PATTERN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ARRAY_SIZE(mt9v032_test_pattern_menu) - 1, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) mt9v032_test_pattern_menu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) mt9v032->test_pattern_color = v4l2_ctrl_new_custom(&mt9v032->ctrls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) &mt9v032_test_pattern_color, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) v4l2_ctrl_new_custom(&mt9v032->ctrls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) mt9v032->model->data->aec_max_shutter_v4l2_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) for (i = 0; i < ARRAY_SIZE(mt9v032_aegc_controls); ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_aegc_controls[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) v4l2_ctrl_cluster(2, &mt9v032->test_pattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) mt9v032->pixel_rate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (pdata && pdata->link_freqs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) unsigned int def = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) for (i = 0; pdata->link_freqs[i]; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (pdata->link_freqs[i] == pdata->link_def_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) def = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) mt9v032->link_freq =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) v4l2_ctrl_new_int_menu(&mt9v032->ctrls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) &mt9v032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) V4L2_CID_LINK_FREQ, i - 1, def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) pdata->link_freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) v4l2_ctrl_cluster(2, &mt9v032->link_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) mt9v032->subdev.ctrl_handler = &mt9v032->ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (mt9v032->ctrls.error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) dev_err(&client->dev, "control initialization error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) mt9v032->ctrls.error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) ret = mt9v032->ctrls.error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) mt9v032->crop.left = MT9V032_COLUMN_START_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) mt9v032->crop.top = MT9V032_ROW_START_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) mt9v032->crop.width = MT9V032_WINDOW_WIDTH_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (mt9v032->model->color)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) mt9v032->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) mt9v032->format.code = MEDIA_BUS_FMT_Y10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) mt9v032->format.field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) mt9v032->hratio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) mt9v032->vratio = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) mt9v032->hblank = MT9V032_HORIZONTAL_BLANKING_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) mt9v032->sysclk = MT9V032_SYSCLK_FREQ_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) mt9v032->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) mt9v032->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) ret = media_entity_pads_init(&mt9v032->subdev.entity, 1, &mt9v032->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) mt9v032->subdev.dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) ret = v4l2_async_register_subdev(&mt9v032->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) media_entity_cleanup(&mt9v032->subdev.entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) v4l2_ctrl_handler_free(&mt9v032->ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) static int mt9v032_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) struct v4l2_subdev *subdev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct mt9v032 *mt9v032 = to_mt9v032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) v4l2_async_unregister_subdev(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) v4l2_ctrl_handler_free(&mt9v032->ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) media_entity_cleanup(&subdev->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) static const struct mt9v032_model_data mt9v032_model_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) /* MT9V022, MT9V032 revisions 1/2/3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) .min_row_time = 660,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) .min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) .min_vblank = MT9V032_VERTICAL_BLANKING_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) .max_vblank = MT9V032_VERTICAL_BLANKING_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) .min_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) .max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) .pclk_reg = MT9V032_PIXEL_CLOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) .aec_max_shutter_reg = MT9V032_AEC_MAX_SHUTTER_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) .aec_max_shutter_v4l2_ctrl = &mt9v032_aec_max_shutter_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) /* MT9V024, MT9V034 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) .min_row_time = 690,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) .min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) .min_vblank = MT9V034_VERTICAL_BLANKING_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) .max_vblank = MT9V034_VERTICAL_BLANKING_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) .min_shutter = MT9V034_TOTAL_SHUTTER_WIDTH_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) .max_shutter = MT9V034_TOTAL_SHUTTER_WIDTH_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) .pclk_reg = MT9V034_PIXEL_CLOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) .aec_max_shutter_reg = MT9V034_AEC_MAX_SHUTTER_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) .aec_max_shutter_v4l2_ctrl = &mt9v034_aec_max_shutter_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) static const struct mt9v032_model_info mt9v032_models[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) [MT9V032_MODEL_V022_COLOR] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) .data = &mt9v032_model_data[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) .color = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) [MT9V032_MODEL_V022_MONO] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) .data = &mt9v032_model_data[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) .color = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) [MT9V032_MODEL_V024_COLOR] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) .data = &mt9v032_model_data[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) .color = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) [MT9V032_MODEL_V024_MONO] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) .data = &mt9v032_model_data[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) .color = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) [MT9V032_MODEL_V032_COLOR] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) .data = &mt9v032_model_data[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) .color = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) [MT9V032_MODEL_V032_MONO] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) .data = &mt9v032_model_data[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) .color = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) [MT9V032_MODEL_V034_COLOR] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) .data = &mt9v032_model_data[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) .color = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) [MT9V032_MODEL_V034_MONO] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) .data = &mt9v032_model_data[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) .color = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) static const struct i2c_device_id mt9v032_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) { "mt9v022", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_COLOR] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) { "mt9v022m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_MONO] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) { "mt9v024", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_COLOR] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) { "mt9v024m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_MONO] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) { "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_COLOR] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) { "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) { "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) { "mt9v034m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_MONO] },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) MODULE_DEVICE_TABLE(i2c, mt9v032_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) #if IS_ENABLED(CONFIG_OF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) static const struct of_device_id mt9v032_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) { .compatible = "aptina,mt9v022" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) { .compatible = "aptina,mt9v022m" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) { .compatible = "aptina,mt9v024" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) { .compatible = "aptina,mt9v024m" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) { .compatible = "aptina,mt9v032" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) { .compatible = "aptina,mt9v032m" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) { .compatible = "aptina,mt9v034" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) { .compatible = "aptina,mt9v034m" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) { /* Sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) MODULE_DEVICE_TABLE(of, mt9v032_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) static struct i2c_driver mt9v032_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) .name = "mt9v032",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) .of_match_table = of_match_ptr(mt9v032_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) .probe = mt9v032_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) .remove = mt9v032_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) .id_table = mt9v032_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) module_i2c_driver(mt9v032_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) MODULE_DESCRIPTION("Aptina MT9V032 Camera driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) MODULE_LICENSE("GPL");