^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 MT9M032 CMOS Image Sensor from Micron
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010-2011 Lund Engineering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Contact: Gil Lund <gwlund@lundeng.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Martin Hostettler <martin@neutronstar.dyndns.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/math64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/v4l2-mediabus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <media/media-entity.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <media/i2c/mt9m032.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <media/v4l2-subdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "aptina-pll.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * width and height include active boundary and black parts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * column 0- 15 active boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * column 16-1455 image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * column 1456-1471 active boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * column 1472-1599 black
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * row 0- 51 black
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * row 53- 59 active boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * row 60-1139 image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * row 1140-1147 active boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * row 1148-1151 black
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MT9M032_PIXEL_ARRAY_WIDTH 1600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define MT9M032_PIXEL_ARRAY_HEIGHT 1152
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define MT9M032_CHIP_VERSION 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define MT9M032_CHIP_VERSION_VALUE 0x1402
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define MT9M032_ROW_START 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define MT9M032_ROW_START_MIN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define MT9M032_ROW_START_MAX 1152
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define MT9M032_ROW_START_DEF 60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define MT9M032_COLUMN_START 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define MT9M032_COLUMN_START_MIN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define MT9M032_COLUMN_START_MAX 1600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define MT9M032_COLUMN_START_DEF 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define MT9M032_ROW_SIZE 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define MT9M032_ROW_SIZE_MIN 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define MT9M032_ROW_SIZE_MAX 1152
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define MT9M032_ROW_SIZE_DEF 1080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define MT9M032_COLUMN_SIZE 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define MT9M032_COLUMN_SIZE_MIN 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define MT9M032_COLUMN_SIZE_MAX 1600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define MT9M032_COLUMN_SIZE_DEF 1440
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define MT9M032_HBLANK 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define MT9M032_VBLANK 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define MT9M032_VBLANK_MAX 0x7ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define MT9M032_SHUTTER_WIDTH_HIGH 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define MT9M032_SHUTTER_WIDTH_LOW 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define MT9M032_SHUTTER_WIDTH_MIN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define MT9M032_SHUTTER_WIDTH_MAX 1048575
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define MT9M032_SHUTTER_WIDTH_DEF 1943
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define MT9M032_PIX_CLK_CTRL 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define MT9M032_PIX_CLK_CTRL_INV_PIXCLK 0x8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define MT9M032_RESTART 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define MT9M032_RESET 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define MT9M032_PLL_CONFIG1 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define MT9M032_PLL_CONFIG1_PREDIV_MASK 0x3f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define MT9M032_PLL_CONFIG1_MUL_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define MT9M032_READ_MODE1 0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define MT9M032_READ_MODE1_OUTPUT_BAD_FRAMES (1 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define MT9M032_READ_MODE1_MAINTAIN_FRAME_RATE (1 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define MT9M032_READ_MODE1_XOR_LINE_VALID (1 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define MT9M032_READ_MODE1_CONT_LINE_VALID (1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define MT9M032_READ_MODE1_INVERT_TRIGGER (1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define MT9M032_READ_MODE1_SNAPSHOT (1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define MT9M032_READ_MODE1_GLOBAL_RESET (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define MT9M032_READ_MODE1_BULB_EXPOSURE (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define MT9M032_READ_MODE1_INVERT_STROBE (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define MT9M032_READ_MODE1_STROBE_ENABLE (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define MT9M032_READ_MODE1_STROBE_START_TRIG1 (0 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define MT9M032_READ_MODE1_STROBE_START_EXP (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define MT9M032_READ_MODE1_STROBE_START_SHUTTER (2 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define MT9M032_READ_MODE1_STROBE_START_TRIG2 (3 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define MT9M032_READ_MODE1_STROBE_END_TRIG1 (0 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define MT9M032_READ_MODE1_STROBE_END_EXP (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define MT9M032_READ_MODE1_STROBE_END_SHUTTER (2 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define MT9M032_READ_MODE1_STROBE_END_TRIG2 (3 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define MT9M032_READ_MODE2 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define MT9M032_READ_MODE2_VFLIP_SHIFT 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define MT9M032_READ_MODE2_HFLIP_SHIFT 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define MT9M032_READ_MODE2_ROW_BLC 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define MT9M032_GAIN_GREEN1 0x2b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define MT9M032_GAIN_BLUE 0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define MT9M032_GAIN_RED 0x2d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define MT9M032_GAIN_GREEN2 0x2e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* write only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define MT9M032_GAIN_ALL 0x35
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define MT9M032_GAIN_DIGITAL_MASK 0x7f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define MT9M032_GAIN_DIGITAL_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define MT9M032_GAIN_AMUL_SHIFT 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define MT9M032_GAIN_ANALOG_MASK 0x3f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define MT9M032_FORMATTER1 0x9e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define MT9M032_FORMATTER1_PLL_P1_6 (1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define MT9M032_FORMATTER1_PARALLEL (1 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define MT9M032_FORMATTER2 0x9f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define MT9M032_FORMATTER2_DOUT_EN 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define MT9M032_FORMATTER2_PIXCLK_EN 0x2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * The available MT9M032 datasheet is missing documentation for register 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * MT9P031 seems to be close enough, so use constants from that datasheet for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * But keep the name MT9P031 to remind us, that this isn't really confirmed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * for this sensor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define MT9P031_PLL_CONTROL 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define MT9P031_PLL_CONTROL_PWROFF 0x0050
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define MT9P031_PLL_CONTROL_PWRON 0x0051
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define MT9P031_PLL_CONTROL_USEPLL 0x0052
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct mt9m032 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct v4l2_subdev subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct media_pad pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct mt9m032_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) unsigned int pix_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct v4l2_ctrl_handler ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct v4l2_ctrl *hflip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct v4l2_ctrl *vflip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct mutex lock; /* Protects streaming, format, interval and crop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) bool streaming;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct v4l2_mbus_framefmt format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct v4l2_rect crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct v4l2_fract frame_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define to_mt9m032(sd) container_of(sd, struct mt9m032, subdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define to_dev(sensor) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) (&((struct i2c_client *)v4l2_get_subdevdata(&(sensor)->subdev))->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int mt9m032_read(struct i2c_client *client, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return i2c_smbus_read_word_swapped(client, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int mt9m032_write(struct i2c_client *client, u8 reg, const u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return i2c_smbus_write_word_swapped(client, reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static u32 mt9m032_row_time(struct mt9m032 *sensor, unsigned int width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) unsigned int effective_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u32 ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) effective_width = width + 716; /* empirical value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ns = div_u64(1000000000ULL * effective_width, sensor->pix_clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) dev_dbg(to_dev(sensor), "MT9M032 line time: %u ns\n", ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int mt9m032_update_timing(struct mt9m032 *sensor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct v4l2_fract *interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct v4l2_rect *crop = &sensor->crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) unsigned int min_vblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned int vblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) u32 row_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (!interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) interval = &sensor->frame_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) row_time = mt9m032_row_time(sensor, crop->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) vblank = div_u64(1000000000ULL * interval->numerator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) (u64)row_time * interval->denominator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) - crop->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (vblank > MT9M032_VBLANK_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /* hardware limits to 11 bit values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) interval->denominator = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) interval->numerator =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) div_u64((crop->height + MT9M032_VBLANK_MAX) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) (u64)row_time * interval->denominator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 1000000000ULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) vblank = div_u64(1000000000ULL * interval->numerator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) (u64)row_time * interval->denominator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) - crop->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* enforce minimal 1.6ms blanking time. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) min_vblank = 1600000 / row_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) vblank = clamp_t(unsigned int, vblank, min_vblank, MT9M032_VBLANK_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return mt9m032_write(client, MT9M032_VBLANK, vblank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int mt9m032_update_geom_timing(struct mt9m032 *sensor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ret = mt9m032_write(client, MT9M032_COLUMN_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) sensor->crop.width - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ret = mt9m032_write(client, MT9M032_ROW_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) sensor->crop.height - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ret = mt9m032_write(client, MT9M032_COLUMN_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) sensor->crop.left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ret = mt9m032_write(client, MT9M032_ROW_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) sensor->crop.top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) ret = mt9m032_update_timing(sensor, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static int update_formatter2(struct mt9m032 *sensor, bool streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) u16 reg_val = MT9M032_FORMATTER2_DOUT_EN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) | 0x0070; /* parts reserved! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* possibly for changing to 14-bit mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) reg_val |= MT9M032_FORMATTER2_PIXCLK_EN; /* pixclock enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return mt9m032_write(client, MT9M032_FORMATTER2, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static int mt9m032_setup_pll(struct mt9m032 *sensor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static const struct aptina_pll_limits limits = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .ext_clock_min = 8000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .ext_clock_max = 16500000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .int_clock_min = 2000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .int_clock_max = 24000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .out_clock_min = 322000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .out_clock_max = 693000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .pix_clock_max = 99000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .n_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .n_max = 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .m_min = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .m_max = 255,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .p1_min = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .p1_max = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct mt9m032_platform_data *pdata = sensor->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct aptina_pll pll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) u16 reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) pll.ext_clock = pdata->ext_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) pll.pix_clock = pdata->pix_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ret = aptina_pll_calculate(&client->dev, &limits, &pll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) sensor->pix_clock = pdata->pix_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ret = mt9m032_write(client, MT9M032_PLL_CONFIG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) (pll.m << MT9M032_PLL_CONFIG1_MUL_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ((pll.n - 1) & MT9M032_PLL_CONFIG1_PREDIV_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ret = mt9m032_write(client, MT9P031_PLL_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) MT9P031_PLL_CONTROL_PWRON |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) MT9P031_PLL_CONTROL_USEPLL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (!ret) /* more reserved, Continuous, Master Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ret = mt9m032_write(client, MT9M032_READ_MODE1, 0x8000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) MT9M032_READ_MODE1_STROBE_START_EXP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) MT9M032_READ_MODE1_STROBE_END_SHUTTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) reg_val = (pll.p1 == 6 ? MT9M032_FORMATTER1_PLL_P1_6 : 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) | MT9M032_FORMATTER1_PARALLEL | 0x001e; /* 14-bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) ret = mt9m032_write(client, MT9M032_FORMATTER1, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * Subdev pad operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct v4l2_subdev_mbus_code_enum *code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (code->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) code->code = MEDIA_BUS_FMT_Y8_1X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return 0;
^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 mt9m032_enum_frame_size(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct v4l2_subdev_frame_size_enum *fse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (fse->index != 0 || fse->code != MEDIA_BUS_FMT_Y8_1X8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) fse->min_width = MT9M032_COLUMN_SIZE_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) fse->max_width = MT9M032_COLUMN_SIZE_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) fse->min_height = MT9M032_ROW_SIZE_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) fse->max_height = MT9M032_ROW_SIZE_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * __mt9m032_get_pad_crop() - get crop rect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * @sensor: pointer to the sensor struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * @cfg: v4l2_subdev_pad_config for getting the try crop rect from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * @which: select try or active crop rect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * Returns a pointer the current active or fh relative try crop rect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static struct v4l2_rect *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) __mt9m032_get_pad_crop(struct mt9m032 *sensor, struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) enum v4l2_subdev_format_whence which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) switch (which) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) case V4L2_SUBDEV_FORMAT_TRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return v4l2_subdev_get_try_crop(&sensor->subdev, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case V4L2_SUBDEV_FORMAT_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return &sensor->crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * __mt9m032_get_pad_format() - get format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * @sensor: pointer to the sensor struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * @cfg: v4l2_subdev_pad_config for getting the try format from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * @which: select try or active format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * Returns a pointer the current active or fh relative try format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static struct v4l2_mbus_framefmt *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) __mt9m032_get_pad_format(struct mt9m032 *sensor, struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) enum v4l2_subdev_format_whence which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) switch (which) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) case V4L2_SUBDEV_FORMAT_TRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return v4l2_subdev_get_try_format(&sensor->subdev, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case V4L2_SUBDEV_FORMAT_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return &sensor->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static int mt9m032_get_pad_format(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct v4l2_subdev_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct mt9m032 *sensor = to_mt9m032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) mutex_lock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) fmt->format = *__mt9m032_get_pad_format(sensor, cfg, fmt->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) mutex_unlock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static int mt9m032_set_pad_format(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct v4l2_subdev_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct mt9m032 *sensor = to_mt9m032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) mutex_lock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (sensor->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /* Scaling is not supported, the format is thus fixed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) fmt->format = *__mt9m032_get_pad_format(sensor, cfg, fmt->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) mutex_unlock(&sensor->lock);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static int mt9m032_get_pad_selection(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct v4l2_subdev_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct mt9m032 *sensor = to_mt9m032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (sel->target != V4L2_SEL_TGT_CROP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) mutex_lock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) sel->r = *__mt9m032_get_pad_crop(sensor, cfg, sel->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) mutex_unlock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static int mt9m032_set_pad_selection(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct v4l2_subdev_selection *sel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct mt9m032 *sensor = to_mt9m032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) struct v4l2_mbus_framefmt *format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) struct v4l2_rect *__crop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) struct v4l2_rect rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (sel->target != V4L2_SEL_TGT_CROP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) mutex_lock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (sensor->streaming && sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* Clamp the crop rectangle boundaries and align them to a multiple of 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * pixels to ensure a GRBG Bayer pattern.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) rect.left = clamp(ALIGN(sel->r.left, 2), MT9M032_COLUMN_START_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) MT9M032_COLUMN_START_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) rect.top = clamp(ALIGN(sel->r.top, 2), MT9M032_ROW_START_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) MT9M032_ROW_START_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) MT9M032_COLUMN_SIZE_MIN, MT9M032_COLUMN_SIZE_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) MT9M032_ROW_SIZE_MIN, MT9M032_ROW_SIZE_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) rect.width = min_t(unsigned int, rect.width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) MT9M032_PIXEL_ARRAY_WIDTH - rect.left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) rect.height = min_t(unsigned int, rect.height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) MT9M032_PIXEL_ARRAY_HEIGHT - rect.top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) __crop = __mt9m032_get_pad_crop(sensor, cfg, sel->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (rect.width != __crop->width || rect.height != __crop->height) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* Reset the output image size if the crop rectangle size has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * been modified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) format = __mt9m032_get_pad_format(sensor, cfg, sel->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) format->width = rect.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) format->height = rect.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) *__crop = rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) sel->r = rect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) ret = mt9m032_update_geom_timing(sensor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) mutex_unlock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static int mt9m032_get_frame_interval(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct v4l2_subdev_frame_interval *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct mt9m032 *sensor = to_mt9m032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) mutex_lock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) memset(fi, 0, sizeof(*fi));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) fi->interval = sensor->frame_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) mutex_unlock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) static int mt9m032_set_frame_interval(struct v4l2_subdev *subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct v4l2_subdev_frame_interval *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct mt9m032 *sensor = to_mt9m032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) mutex_lock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (sensor->streaming) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /* Avoid divisions by 0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (fi->interval.denominator == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) fi->interval.denominator = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) ret = mt9m032_update_timing(sensor, &fi->interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) sensor->frame_interval = fi->interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) mutex_unlock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static int mt9m032_s_stream(struct v4l2_subdev *subdev, int streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct mt9m032 *sensor = to_mt9m032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) mutex_lock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ret = update_formatter2(sensor, streaming);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) sensor->streaming = streaming;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) mutex_unlock(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * V4L2 subdev core operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static int mt9m032_g_register(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct mt9m032 *sensor = to_mt9m032(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (reg->reg > 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) val = mt9m032_read(client, reg->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) reg->size = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) reg->val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static int mt9m032_s_register(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) const struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct mt9m032 *sensor = to_mt9m032(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (reg->reg > 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return mt9m032_write(client, reg->reg, reg->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * V4L2 subdev control operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static int update_read_mode2(struct mt9m032 *sensor, bool vflip, bool hflip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) int reg_val = (vflip << MT9M032_READ_MODE2_VFLIP_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) | (hflip << MT9M032_READ_MODE2_HFLIP_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) | MT9M032_READ_MODE2_ROW_BLC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) | 0x0007;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return mt9m032_write(client, MT9M032_READ_MODE2, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static int mt9m032_set_gain(struct mt9m032 *sensor, s32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int digital_gain_val; /* in 1/8th (0..127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) int analog_mul; /* 0 or 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) int analog_gain_val; /* in 1/16th. (0..63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) u16 reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) digital_gain_val = 51; /* from setup example */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (val < 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) analog_mul = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) analog_gain_val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) analog_mul = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) analog_gain_val = val / 2;
^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) /* a_gain = (1 + analog_mul) + (analog_gain_val + 1) / 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* overall_gain = a_gain * (1 + digital_gain_val / 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) reg_val = ((digital_gain_val & MT9M032_GAIN_DIGITAL_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) << MT9M032_GAIN_DIGITAL_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) | ((analog_mul & 1) << MT9M032_GAIN_AMUL_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) | (analog_gain_val & MT9M032_GAIN_ANALOG_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return mt9m032_write(client, MT9M032_GAIN_ALL, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static int mt9m032_try_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (ctrl->id == V4L2_CID_GAIN && ctrl->val >= 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /* round because of multiplier used for values >= 63 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) ctrl->val &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) static int mt9m032_set_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct mt9m032 *sensor =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) container_of(ctrl->handler, struct mt9m032, ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) case V4L2_CID_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return mt9m032_set_gain(sensor, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) case V4L2_CID_HFLIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) /* case V4L2_CID_VFLIP: -- In the same cluster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return update_read_mode2(sensor, sensor->vflip->val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) sensor->hflip->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) case V4L2_CID_EXPOSURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ret = mt9m032_write(client, MT9M032_SHUTTER_WIDTH_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) (ctrl->val >> 16) & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return mt9m032_write(client, MT9M032_SHUTTER_WIDTH_LOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ctrl->val & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static const struct v4l2_ctrl_ops mt9m032_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) .s_ctrl = mt9m032_set_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) .try_ctrl = mt9m032_try_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /* -------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static const struct v4l2_subdev_core_ops mt9m032_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) .g_register = mt9m032_g_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) .s_register = mt9m032_s_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) static const struct v4l2_subdev_video_ops mt9m032_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) .s_stream = mt9m032_s_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) .g_frame_interval = mt9m032_get_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) .s_frame_interval = mt9m032_set_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) .enum_mbus_code = mt9m032_enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) .enum_frame_size = mt9m032_enum_frame_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) .get_fmt = mt9m032_get_pad_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) .set_fmt = mt9m032_set_pad_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) .set_selection = mt9m032_set_pad_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) .get_selection = mt9m032_get_pad_selection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) static const struct v4l2_subdev_ops mt9m032_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) .core = &mt9m032_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) .video = &mt9m032_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) .pad = &mt9m032_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * Driver initialization and probing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static int mt9m032_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) const struct i2c_device_id *devid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct mt9m032_platform_data *pdata = client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct i2c_adapter *adapter = client->adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct mt9m032 *sensor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) int chip_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (pdata == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) dev_err(&client->dev, "No platform data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) dev_warn(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (!client->dev.platform_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (sensor == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) mutex_init(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) sensor->pdata = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) chip_version = mt9m032_read(client, MT9M032_CHIP_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (chip_version != MT9M032_CHIP_VERSION_VALUE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) dev_err(&client->dev, "MT9M032 not detected, wrong version "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) "0x%04x\n", chip_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) goto error_sensor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) dev_info(&client->dev, "MT9M032 detected at address 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) client->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) sensor->frame_interval.numerator = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) sensor->frame_interval.denominator = 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) sensor->crop.left = MT9M032_COLUMN_START_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) sensor->crop.top = MT9M032_ROW_START_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) sensor->crop.width = MT9M032_COLUMN_SIZE_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) sensor->crop.height = MT9M032_ROW_SIZE_DEF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) sensor->format.width = sensor->crop.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) sensor->format.height = sensor->crop.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) sensor->format.code = MEDIA_BUS_FMT_Y8_1X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) sensor->format.field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) sensor->format.colorspace = V4L2_COLORSPACE_SRGB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) v4l2_ctrl_handler_init(&sensor->ctrls, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) V4L2_CID_GAIN, 0, 127, 1, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) &mt9m032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) V4L2_CID_HFLIP, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) &mt9m032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) V4L2_CID_VFLIP, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) MT9M032_SHUTTER_WIDTH_MAX, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) MT9M032_SHUTTER_WIDTH_DEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) V4L2_CID_PIXEL_RATE, pdata->pix_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) pdata->pix_clock, 1, pdata->pix_clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (sensor->ctrls.error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) ret = sensor->ctrls.error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) dev_err(&client->dev, "control initialization error %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) goto error_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) v4l2_ctrl_cluster(2, &sensor->hflip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) sensor->subdev.ctrl_handler = &sensor->ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) sensor->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) ret = media_entity_pads_init(&sensor->subdev.entity, 1, &sensor->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) goto error_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) ret = mt9m032_write(client, MT9M032_RESET, 1); /* reset on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) ret = mt9m032_write(client, MT9M032_RESET, 0); /* reset off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) ret = mt9m032_setup_pll(sensor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) usleep_range(10000, 11000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) ret = v4l2_ctrl_handler_setup(&sensor->ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) /* SIZE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) ret = mt9m032_update_geom_timing(sensor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) ret = mt9m032_write(client, 0x41, 0x0000); /* reserved !!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) ret = mt9m032_write(client, 0x42, 0x0003); /* reserved !!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) ret = mt9m032_write(client, 0x43, 0x0003); /* reserved !!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ret = mt9m032_write(client, 0x7f, 0x0000); /* reserved !!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (sensor->pdata->invert_pixclock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) ret = mt9m032_write(client, MT9M032_PIX_CLK_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) MT9M032_PIX_CLK_CTRL_INV_PIXCLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) ret = mt9m032_write(client, MT9M032_RESTART, 1); /* Restart on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) ret = mt9m032_write(client, MT9M032_RESTART, 0); /* Restart off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) ret = update_formatter2(sensor, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) goto error_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) error_entity:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) media_entity_cleanup(&sensor->subdev.entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) error_ctrl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) v4l2_ctrl_handler_free(&sensor->ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) error_sensor:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) mutex_destroy(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) static int mt9m032_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) struct v4l2_subdev *subdev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) struct mt9m032 *sensor = to_mt9m032(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) v4l2_device_unregister_subdev(subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) v4l2_ctrl_handler_free(&sensor->ctrls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) media_entity_cleanup(&subdev->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) mutex_destroy(&sensor->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static const struct i2c_device_id mt9m032_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) { MT9M032_NAME, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) MODULE_DEVICE_TABLE(i2c, mt9m032_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) static struct i2c_driver mt9m032_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) .name = MT9M032_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) .probe = mt9m032_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) .remove = mt9m032_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) .id_table = mt9m032_id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) module_i2c_driver(mt9m032_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) MODULE_AUTHOR("Martin Hostettler <martin@neutronstar.dyndns.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) MODULE_DESCRIPTION("MT9M032 camera sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) MODULE_LICENSE("GPL v2");