^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * gc2375h driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * V0.0X01.0X01 init driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * V0.0X01.0X02 fix mclk issue when probe multiple camera.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * V0.0X01.0X03 add enum_frame_interval function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * TODO: add OTP function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * V0.0X01.0X04 add quick stream on/off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * V0.0X01.0X05 add function g_mbus_config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * V0.0X01.0X06 fix vblank set issue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) //#define DEBUG 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/of_graph.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/of_gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/version.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/rk-camera-module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <media/media-entity.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <media/v4l2-async.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <media/v4l2-subdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/pinctrl/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #ifndef V4L2_CID_DIGITAL_GAIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define MIPI_FREQ 338000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* pixel rate = link frequency * 1 * lanes / BITS_PER_SAMPLE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define GC2375H_PIXEL_RATE (MIPI_FREQ * 2LL * 1LL / 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define GC2375H_XVCLK_FREQ 24000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define CHIP_ID 0x2375
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define GC2375H_REG_CHIP_ID_H 0xf0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define GC2375H_REG_CHIP_ID_L 0xf1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define SENSOR_ID(_msb, _lsb) ((_msb) << 8 | (_lsb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define GC2375H_REG_SET_PAGE 0xfe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define GC2375H_SET_PAGE_ONE 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define GC2375H_PAGE_SELECT 0xfe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define GC2375H_MODE_SELECT 0xef
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define GC2375H_MODE_SW_STANDBY 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define GC2375H_MODE_STREAMING 0x90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define GC2375H_REG_EXPOSURE_H 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define GC2375H_REG_EXPOSURE_L 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define GC2375H_EXPOSURE_MIN 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define GC2375H_EXPOSURE_STEP 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define GC2375H_VTS_MAX 0x7fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define GC2375H_ANALOG_GAIN_1 64 /*1.00x*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define GC2375H_ANALOG_GAIN_2 88 /*1.375x*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define GC2375H_ANALOG_GAIN_3 122 /*1.90x*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define GC2375H_ANALOG_GAIN_4 168 /*2.625x*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define GC2375H_ANALOG_GAIN_5 239 /*3.738x*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define GC2375H_ANALOG_GAIN_6 330 /*5.163x*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define GC2375H_ANALOG_GAIN_7 470 /*7.350x*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define GC2375H_ANALOG_GAIN_8 725 // 11.34x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define GC2375H_ANALOG_GAIN_9 1038 // 16.23x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define GC2375H_ANALOG_GAIN_REG 0xb6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define GC2375H_PREGAIN_H_REG 0xb1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define GC2375H_PREGAIN_L_REG 0xb2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define GC2375H_GAIN_MIN 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define GC2375H_GAIN_MAX 0x200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define GC2375H_GAIN_STEP 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define GC2375H_GAIN_DEFAULT 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define GC2375H_REG_VTS_H 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define GC2375H_REG_VTS_L 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define GC2375_MIRROR_NORMAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) //#define GC2375_MIRROR_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) //#define GC2375_MIRROR_V
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) //#define GC2375_MIRROR_HV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #if defined(GC2375_MIRROR_NORMAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define MIRROR 0xd4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define BLK_Select1_H 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define BLK_Select1_L 0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define BLK_Select2_H 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define BLK_Select2_L 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #elif defined(GC2375_MIRROR_H)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define MIRROR 0xd5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define BLK_Select1_H 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define BLK_Select1_L 0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define BLK_Select2_H 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define BLK_Select2_L 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #elif defined(GC2375_MIRROR_V)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define MIRROR 0xd6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define BLK_Select1_H 0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define BLK_Select1_L 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define BLK_Select2_H 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define BLK_Select2_L 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #elif defined(GC2375_MIRROR_HV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define MIRROR 0xd7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define BLK_Select1_H 0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define BLK_Select1_L 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define BLK_Select2_H 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define BLK_Select2_L 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define MIRROR 0xd4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define BLK_Select1_H 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define BLK_Select1_L 0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define BLK_Select2_H 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define BLK_Select2_L 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) //#define GC2375_OLD_SETTING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define REG_NULL 0xFFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define GC2375H_LANES 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define GC2375H_BITS_PER_SAMPLE 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define GC2375H_NAME "gc2375h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static const char * const gc2375h_supply_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) "avdd", /* Analog power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) "dovdd", /* Digital I/O power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) "dvdd", /* Digital core power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define GC2375H_NUM_SUPPLIES ARRAY_SIZE(gc2375h_supply_names)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct regval {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) u16 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct gc2375h_mode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) u32 width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) u32 height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct v4l2_fract max_fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) u32 hts_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) u32 vts_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) u32 exp_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) const struct regval *reg_list;
^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) struct gc2375h {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct clk *xvclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct gpio_desc *reset_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct gpio_desc *pwdn_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct regulator_bulk_data supplies[GC2375H_NUM_SUPPLIES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct pinctrl *pinctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct pinctrl_state *pins_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct pinctrl_state *pins_sleep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct v4l2_subdev subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct media_pad pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct v4l2_ctrl_handler ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct v4l2_ctrl *exposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct v4l2_ctrl *anal_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct v4l2_ctrl *digi_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct v4l2_ctrl *hblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct v4l2_ctrl *vblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct v4l2_ctrl *test_pattern;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct mutex mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) bool streaming;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) bool power_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) const struct gc2375h_mode *cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unsigned int lane_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) unsigned int cfg_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) unsigned int pixel_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) u32 module_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) const char *module_facing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) const char *module_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) const char *len_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define to_gc2375h(sd) container_of(sd, struct gc2375h, subdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * Xclk 24Mhz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static const struct regval gc2375h_global_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #ifdef GC2375_OLD_SETTING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {0xf7, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {0xf8, 0x0c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {0xf9, 0x42},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {0xfa, 0x88},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {0xfc, 0x8e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {0x88, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {0x03, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {0x04, 0x65},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {0x05, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {0x06, 0x5a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {0x07, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {0x08, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {0x09, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {0x0a, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {0x0b, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {0x0c, 0x18},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {0x0d, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {0x0e, 0xb8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {0x0f, 0x06},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {0x10, 0x48},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {0x17, 0xd4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {0x1c, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {0x1d, 0x13},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {0x20, 0x0b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {0x21, 0x6d},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {0x22, 0x0c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {0x25, 0xc1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {0x26, 0x0e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {0x27, 0x22},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {0x29, 0x5f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {0x2b, 0x88},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {0x2f, 0x12},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {0x38, 0x86},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {0x3d, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {0xcd, 0xa3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {0xce, 0x57},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {0xd0, 0x09},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {0xd1, 0xca},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {0xd2, 0x34},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {0xd3, 0xbb},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {0xd8, 0x60},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {0xe0, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {0xe1, 0x1f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {0xe4, 0xf8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {0xe5, 0x0c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {0xe6, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {0xe7, 0xcc},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {0xe8, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {0xe9, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {0xea, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {0xeb, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {0x90, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {0x92, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {0x94, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {0x95, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {0x96, 0xb0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {0x97, 0x06},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {0x98, 0x40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {0x18, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {0x1a, 0x18},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {0x28, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {0x3f, 0x40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {0x40, 0x26},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {0x41, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {0x43, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {0x4a, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {0x4e, 0x3c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {0x4f, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {0x66, 0xc0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {0x67, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {0x68, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {0xb0, 0x58},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {0xb1, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {0xb2, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {0xb6, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {0xef, 0x90},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {0xfe, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {0x01, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {0x02, 0x33},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {0x03, 0x90},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {0x04, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {0x05, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {0x06, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {0x11, 0x2b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {0x12, 0xd0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {0x13, 0x07},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {0x15, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {0x21, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {0x22, 0x05},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {0x23, 0x13},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {0x24, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {0x25, 0x13},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {0x26, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {0x29, 0x06},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {0x2a, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {0x2b, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) {0x20, 0x0b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {0x22, 0x0c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {0x26, 0x0e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {0xb6, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /*System*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {0xf7, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {0xf8, 0x0c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {0xf9, 0x42},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {0xfa, 0x88},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {0xfc, 0x8e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {0x88, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /*Analog*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {0x03, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {0x04, 0x65},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {0x05, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {0x06, 0x5a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {0x07, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {0x08, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {0x09, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {0x0a, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {0x0b, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {0x0c, 0x14},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {0x0d, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {0x0e, 0xb8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {0x0f, 0x06},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {0x10, 0x48},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {0x17, MIRROR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {0x1c, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {0x1d, 0x13},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {0x20, 0x0b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {0x21, 0x6d},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {0x22, 0x0c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {0x25, 0xc1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {0x26, 0x0e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {0x27, 0x22},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {0x29, 0x5f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {0x2b, 0x88},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {0x2f, 0x12},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {0x38, 0x86},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {0x3d, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {0xcd, 0xa3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {0xce, 0x57},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {0xd0, 0x09},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {0xd1, 0xca},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {0xd2, 0x34},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {0xd3, 0xbb},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {0xd8, 0x60},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {0xe0, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {0xe1, 0x1f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {0xe4, 0xf8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {0xe5, 0x0c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {0xe6, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {0xe7, 0xcc},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {0xe8, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {0xe9, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {0xea, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {0xeb, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /*Crop*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {0x90, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {0x92, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {0x94, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {0x95, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {0x96, 0xb0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {0x97, 0x06},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {0x98, 0x40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /*BLK*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {0x18, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {0x1a, 0x18},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {0x28, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {0x3f, 0x40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {0x40, 0x26},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {0x41, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {0x43, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {0x4a, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {0x4e, BLK_Select1_H},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {0x4f, BLK_Select1_L},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {0x66, BLK_Select2_H},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {0x67, BLK_Select2_L},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /*Dark sun*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {0x68, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /*Gain*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {0xb0, 0x58},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {0xb1, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {0xb2, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {0xb6, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /*MIPI*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {0xef, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {0xfe, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {0x01, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {0x02, 0x33},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {0x03, 0x90},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {0x04, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {0x05, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {0x06, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {0x11, 0x2b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {0x12, 0xd0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {0x13, 0x07},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {0x15, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {0x21, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {0x22, 0x05},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {0x23, 0x13},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {0x24, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {0x25, 0x13},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {0x26, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {0x29, 0x06},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {0x2a, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {0x2b, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {REG_NULL, 0x00},
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * Xclk 24Mhz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * max_framerate 30fps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * mipi_datarate per lane 1008Mbps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) static const struct regval gc2375h_1600x1200_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) {REG_NULL, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static const struct gc2375h_mode supported_modes_1lane[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) .width = 1600,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) .height = 1200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) .max_fps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) .numerator = 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) .denominator = 300000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) .exp_def = 0x04d0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) .hts_def = 0x0820,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) .vts_def = 0x04d9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) .reg_list = gc2375h_1600x1200_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static const struct gc2375h_mode *supported_modes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static const s64 link_freq_menu_items[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) MIPI_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /* sensor register write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static int gc2375h_write_reg(struct i2c_client *client, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) struct i2c_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) dev_dbg(&client->dev, "%s(%d) enter!\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) dev_dbg(&client->dev, "gc2375h write reg(0x%x val:0x%x)!\n", reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) buf[0] = reg & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) buf[1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) msg.addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) msg.flags = client->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) msg.buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) msg.len = sizeof(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) ret = i2c_transfer(client->adapter, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) "gc2375h write reg(0x%x val:0x%x) failed !\n", reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* sensor register read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static int gc2375h_read_reg(struct i2c_client *client, u8 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct i2c_msg msg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) u8 buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) buf[0] = reg & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) msg[0].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) msg[0].flags = client->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) msg[0].buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) msg[0].len = sizeof(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) msg[1].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) msg[1].flags = client->flags | I2C_M_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) msg[1].buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) msg[1].len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ret = i2c_transfer(client->adapter, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (ret >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) *val = buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) "gc2375h read reg:0x%x failed !\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static int gc2375h_write_array(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) const struct regval *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) ret = gc2375h_write_reg(client, regs[i].addr, regs[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) static int gc2375h_get_reso_dist(const struct gc2375h_mode *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct v4l2_mbus_framefmt *framefmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return abs(mode->width - framefmt->width) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) abs(mode->height - framefmt->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static const struct gc2375h_mode *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) gc2375h_find_best_fit(struct gc2375h *gc2375h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct v4l2_subdev_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct v4l2_mbus_framefmt *framefmt = &fmt->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) int dist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int cur_best_fit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) int cur_best_fit_dist = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) for (i = 0; i < gc2375h->cfg_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) dist = gc2375h_get_reso_dist(&supported_modes[i], framefmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) cur_best_fit_dist = dist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) cur_best_fit = i;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return &supported_modes[cur_best_fit];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) static int gc2375h_set_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct v4l2_subdev_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) const struct gc2375h_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) s64 h_blank, vblank_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) mutex_lock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) mode = gc2375h_find_best_fit(gc2375h, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) fmt->format.code = MEDIA_BUS_FMT_SRGGB10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) fmt->format.width = mode->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) fmt->format.height = mode->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) fmt->format.field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) mutex_unlock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) gc2375h->cur_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) h_blank = mode->hts_def - mode->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) __v4l2_ctrl_modify_range(gc2375h->hblank, h_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) h_blank, 1, h_blank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) vblank_def = mode->vts_def - mode->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) __v4l2_ctrl_modify_range(gc2375h->vblank, vblank_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) GC2375H_VTS_MAX - mode->height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 1, vblank_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) mutex_unlock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return 0;
^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 gc2375h_get_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct v4l2_subdev_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) const struct gc2375h_mode *mode = gc2375h->cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) mutex_lock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) mutex_unlock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) fmt->format.width = mode->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) fmt->format.height = mode->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) fmt->format.code = MEDIA_BUS_FMT_SRGGB10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) fmt->format.field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) mutex_unlock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static int gc2375h_enum_mbus_code(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct v4l2_subdev_mbus_code_enum *code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (code->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) code->code = MEDIA_BUS_FMT_SRGGB10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static int gc2375h_enum_frame_sizes(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct v4l2_subdev_frame_size_enum *fse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (fse->index >= gc2375h->cfg_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (fse->code != MEDIA_BUS_FMT_SRGGB10_1X10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) fse->min_width = supported_modes[fse->index].width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) fse->max_width = supported_modes[fse->index].width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) fse->max_height = supported_modes[fse->index].height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) fse->min_height = supported_modes[fse->index].height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static int gc2375h_g_frame_interval(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct v4l2_subdev_frame_interval *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) const struct gc2375h_mode *mode = gc2375h->cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) mutex_lock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) fi->interval = mode->max_fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) mutex_unlock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static void gc2375h_get_module_inf(struct gc2375h *gc2375h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct rkmodule_inf *inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) memset(inf, 0, sizeof(*inf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) strlcpy(inf->base.sensor, GC2375H_NAME, sizeof(inf->base.sensor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) strlcpy(inf->base.module, gc2375h->module_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) sizeof(inf->base.module));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) strlcpy(inf->base.lens, gc2375h->len_name, sizeof(inf->base.lens));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static long gc2375h_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) long ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) u32 stream = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) case RKMODULE_GET_MODULE_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) gc2375h_get_module_inf(gc2375h, (struct rkmodule_inf *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) case RKMODULE_SET_QUICK_STREAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) stream = *((u32 *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ret = gc2375h_write_reg(gc2375h->client, GC2375H_PAGE_SELECT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) ret |= gc2375h_write_reg(gc2375h->client, GC2375H_MODE_SELECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) GC2375H_MODE_STREAMING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) ret |= gc2375h_write_reg(gc2375h->client, GC2375H_PAGE_SELECT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) ret = gc2375h_write_reg(gc2375h->client, GC2375H_PAGE_SELECT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) ret |= gc2375h_write_reg(gc2375h->client, GC2375H_MODE_SELECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) GC2375H_MODE_SW_STANDBY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) ret |= gc2375h_write_reg(gc2375h->client, GC2375H_PAGE_SELECT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) ret = -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) static long gc2375h_compat_ioctl32(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) void __user *up = compat_ptr(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct rkmodule_inf *inf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) struct rkmodule_awb_cfg *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) u32 stream = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) case RKMODULE_GET_MODULE_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) inf = kzalloc(sizeof(*inf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (!inf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) ret = gc2375h_ioctl(sd, cmd, inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) ret = copy_to_user(up, inf, sizeof(*inf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) kfree(inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) case RKMODULE_AWB_CFG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (!cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return ret;
^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) ret = copy_from_user(cfg, up, sizeof(*cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) ret = gc2375h_ioctl(sd, cmd, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) kfree(cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) case RKMODULE_SET_QUICK_STREAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) ret = copy_from_user(&stream, up, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ret = gc2375h_ioctl(sd, cmd, &stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) ret = -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) static int __gc2375h_start_stream(struct gc2375h *gc2375h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) ret = gc2375h_write_array(gc2375h->client, gc2375h->cur_mode->reg_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) /* In case these controls are set before streaming */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) mutex_unlock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) ret = v4l2_ctrl_handler_setup(&gc2375h->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) mutex_lock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) //add mark
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) ret = gc2375h_write_reg(gc2375h->client, GC2375H_PAGE_SELECT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) ret |= gc2375h_write_reg(gc2375h->client, GC2375H_MODE_SELECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) GC2375H_MODE_STREAMING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) ret |= gc2375h_write_reg(gc2375h->client, GC2375H_PAGE_SELECT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static int __gc2375h_stop_stream(struct gc2375h *gc2375h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) ret = gc2375h_write_reg(gc2375h->client, GC2375H_PAGE_SELECT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) ret |= gc2375h_write_reg(gc2375h->client, GC2375H_MODE_SELECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) GC2375H_MODE_SW_STANDBY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) ret |= gc2375h_write_reg(gc2375h->client, GC2375H_PAGE_SELECT, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) // return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) static int gc2375h_s_stream(struct v4l2_subdev *sd, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct i2c_client *client = gc2375h->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) mutex_lock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) on = !!on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (on == gc2375h->streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) ret = pm_runtime_get_sync(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) pm_runtime_put_noidle(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) ret = __gc2375h_start_stream(gc2375h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) v4l2_err(sd, "start stream failed while write regs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) pm_runtime_put(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) __gc2375h_stop_stream(gc2375h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) pm_runtime_put(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) gc2375h->streaming = on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) unlock_and_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) mutex_unlock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static int gc2375h_s_power(struct v4l2_subdev *sd, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct i2c_client *client = gc2375h->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) mutex_lock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /* If the power state is not modified - no work to do. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (gc2375h->power_on == !!on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) ret = pm_runtime_get_sync(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) pm_runtime_put_noidle(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) ret = gc2375h_write_array(gc2375h->client, gc2375h_global_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) v4l2_err(sd, "could not set init registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) pm_runtime_put_noidle(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) gc2375h->power_on = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) pm_runtime_put(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) gc2375h->power_on = false;
^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) unlock_and_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) mutex_unlock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return ret;
^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) /* Calculate the delay in us by clock rate and clock cycles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) static inline u32 gc2375h_cal_delay(u32 cycles)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return DIV_ROUND_UP(cycles, GC2375H_XVCLK_FREQ / 1000 / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static int __gc2375h_power_on(struct gc2375h *gc2375h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) u32 delay_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct device *dev = &gc2375h->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (!IS_ERR_OR_NULL(gc2375h->pins_default)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) ret = pinctrl_select_state(gc2375h->pinctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) gc2375h->pins_default);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) dev_err(dev, "could not set pins\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ret = clk_set_rate(gc2375h->xvclk, GC2375H_XVCLK_FREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (clk_get_rate(gc2375h->xvclk) != GC2375H_XVCLK_FREQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) ret = clk_prepare_enable(gc2375h->xvclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) dev_err(dev, "Failed to enable xvclk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (!IS_ERR(gc2375h->pwdn_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) gpiod_set_value_cansleep(gc2375h->pwdn_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (!IS_ERR(gc2375h->reset_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) gpiod_set_value_cansleep(gc2375h->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) usleep_range(500, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) ret = regulator_bulk_enable(GC2375H_NUM_SUPPLIES, gc2375h->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) dev_err(dev, "Failed to enable regulators\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) goto disable_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (!IS_ERR(gc2375h->reset_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) gpiod_set_value_cansleep(gc2375h->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) /* 8192 cycles prior to first SCCB transaction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) delay_us = gc2375h_cal_delay(8192);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) usleep_range(delay_us, delay_us * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) gc2375h->power_on = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) disable_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) clk_disable_unprepare(gc2375h->xvclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static void __gc2375h_power_off(struct gc2375h *gc2375h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) struct device *dev = &gc2375h->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (!IS_ERR(gc2375h->pwdn_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) gpiod_set_value_cansleep(gc2375h->pwdn_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) clk_disable_unprepare(gc2375h->xvclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (!IS_ERR(gc2375h->reset_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) gpiod_set_value_cansleep(gc2375h->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (!IS_ERR_OR_NULL(gc2375h->pins_sleep)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) ret = pinctrl_select_state(gc2375h->pinctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) gc2375h->pins_sleep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) dev_dbg(dev, "could not set pins\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) regulator_bulk_disable(GC2375H_NUM_SUPPLIES, gc2375h->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) gc2375h->power_on = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) static int gc2375h_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return __gc2375h_power_on(gc2375h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) static int gc2375h_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) __gc2375h_power_off(gc2375h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) static int gc2375h_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) struct v4l2_mbus_framefmt *try_fmt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) v4l2_subdev_get_try_format(sd, fh->pad, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) const struct gc2375h_mode *def_mode = &supported_modes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) mutex_lock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) /* Initialize try_fmt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) try_fmt->width = def_mode->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) try_fmt->height = def_mode->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) try_fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) try_fmt->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) mutex_unlock(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /* No crop or compose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) static int gc2375h_enum_frame_interval(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct v4l2_subdev_frame_interval_enum *fie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (fie->index >= gc2375h->cfg_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (fie->code != MEDIA_BUS_FMT_SRGGB10_1X10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) fie->width = supported_modes[fie->index].width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) fie->height = supported_modes[fie->index].height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) fie->interval = supported_modes[fie->index].max_fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) static int gc2375h_g_mbus_config(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) struct v4l2_mbus_config *config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) u32 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) val = 1 << (GC2375H_LANES - 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) V4L2_MBUS_CSI2_CHANNEL_0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) config->type = V4L2_MBUS_CSI2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) config->flags = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) static const struct dev_pm_ops gc2375h_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) SET_RUNTIME_PM_OPS(gc2375h_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) gc2375h_runtime_resume, NULL)
^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) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static const struct v4l2_subdev_internal_ops gc2375h_internal_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) .open = gc2375h_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) static const struct v4l2_subdev_core_ops gc2375h_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) .s_power = gc2375h_s_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) .ioctl = gc2375h_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) .compat_ioctl32 = gc2375h_compat_ioctl32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) static const struct v4l2_subdev_video_ops gc2375h_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) .s_stream = gc2375h_s_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) .g_frame_interval = gc2375h_g_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) .g_mbus_config = gc2375h_g_mbus_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) static const struct v4l2_subdev_pad_ops gc2375h_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) .enum_mbus_code = gc2375h_enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) .enum_frame_size = gc2375h_enum_frame_sizes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) .enum_frame_interval = gc2375h_enum_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) .get_fmt = gc2375h_get_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) .set_fmt = gc2375h_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) static const struct v4l2_subdev_ops gc2375h_subdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) .core = &gc2375h_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) .video = &gc2375h_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) .pad = &gc2375h_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static int gc2375h_set_gain_reg(struct gc2375h *gc2375h, u32 a_gain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) u32 temp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) ret = gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) GC2375H_PAGE_SELECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) if (a_gain >= GC2375H_ANALOG_GAIN_1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) a_gain < GC2375H_ANALOG_GAIN_2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) ret |= gc2375h_write_reg(gc2375h->client, 0x20, 0x0b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) ret |= gc2375h_write_reg(gc2375h->client, 0x22, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) ret |= gc2375h_write_reg(gc2375h->client, 0x26, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) GC2375H_ANALOG_GAIN_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) temp = a_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) GC2375H_PREGAIN_H_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) temp >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) GC2375H_PREGAIN_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) (temp << 2) & 0xfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) } else if (a_gain >= GC2375H_ANALOG_GAIN_2 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) a_gain < GC2375H_ANALOG_GAIN_3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) ret |= gc2375h_write_reg(gc2375h->client, 0x20, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) ret |= gc2375h_write_reg(gc2375h->client, 0x22, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) ret |= gc2375h_write_reg(gc2375h->client, 0x26, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) GC2375H_ANALOG_GAIN_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) temp = 64 * a_gain / GC2375H_ANALOG_GAIN_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) GC2375H_PREGAIN_H_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) temp >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) GC2375H_PREGAIN_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) (temp << 2) & 0xfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) } else if (a_gain >= GC2375H_ANALOG_GAIN_3 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) a_gain < GC2375H_ANALOG_GAIN_4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) ret |= gc2375h_write_reg(gc2375h->client, 0x20, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) ret |= gc2375h_write_reg(gc2375h->client, 0x22, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) ret |= gc2375h_write_reg(gc2375h->client, 0x26, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) GC2375H_ANALOG_GAIN_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) temp = 64 * a_gain / GC2375H_ANALOG_GAIN_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) GC2375H_PREGAIN_H_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) temp >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) GC2375H_PREGAIN_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) (temp << 2) & 0xfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) } else if (a_gain >= GC2375H_ANALOG_GAIN_4 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) a_gain < GC2375H_ANALOG_GAIN_5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) ret |= gc2375h_write_reg(gc2375h->client, 0x20, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) ret |= gc2375h_write_reg(gc2375h->client, 0x22, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) ret |= gc2375h_write_reg(gc2375h->client, 0x26, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) GC2375H_ANALOG_GAIN_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) temp = 64 * a_gain / GC2375H_ANALOG_GAIN_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) GC2375H_PREGAIN_H_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) temp >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) GC2375H_PREGAIN_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) (temp << 2) & 0xfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) } else if (a_gain >= GC2375H_ANALOG_GAIN_5 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) a_gain < GC2375H_ANALOG_GAIN_6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) ret |= gc2375h_write_reg(gc2375h->client, 0x20, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) ret |= gc2375h_write_reg(gc2375h->client, 0x22, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) ret |= gc2375h_write_reg(gc2375h->client, 0x26, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) GC2375H_ANALOG_GAIN_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) temp = 64 * a_gain / GC2375H_ANALOG_GAIN_5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) GC2375H_PREGAIN_H_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) temp >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) GC2375H_PREGAIN_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) (temp << 2) & 0xfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) } else if (a_gain >= GC2375H_ANALOG_GAIN_6 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) a_gain < GC2375H_ANALOG_GAIN_7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) ret |= gc2375h_write_reg(gc2375h->client, 0x20, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) ret |= gc2375h_write_reg(gc2375h->client, 0x22, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) ret |= gc2375h_write_reg(gc2375h->client, 0x26, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) GC2375H_ANALOG_GAIN_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) temp = 64 * a_gain / GC2375H_ANALOG_GAIN_6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) GC2375H_PREGAIN_H_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) temp >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) GC2375H_PREGAIN_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) (temp << 2) & 0xfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) } else if (a_gain >= GC2375H_ANALOG_GAIN_7 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) a_gain < GC2375H_ANALOG_GAIN_8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) ret |= gc2375h_write_reg(gc2375h->client, 0x20, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) ret |= gc2375h_write_reg(gc2375h->client, 0x22, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) ret |= gc2375h_write_reg(gc2375h->client, 0x26, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) GC2375H_ANALOG_GAIN_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) temp = 64 * a_gain / GC2375H_ANALOG_GAIN_7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) GC2375H_PREGAIN_H_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) temp >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) GC2375H_PREGAIN_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) (temp << 2) & 0xfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) } else if (a_gain >= GC2375H_ANALOG_GAIN_8 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) a_gain < GC2375H_ANALOG_GAIN_9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ret |= gc2375h_write_reg(gc2375h->client, 0x20, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) ret |= gc2375h_write_reg(gc2375h->client, 0x22, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) ret |= gc2375h_write_reg(gc2375h->client, 0x26, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) GC2375H_ANALOG_GAIN_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) temp = 64 * a_gain / GC2375H_ANALOG_GAIN_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) GC2375H_PREGAIN_H_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) temp >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) GC2375H_PREGAIN_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) (temp << 2) & 0xfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) ret |= gc2375h_write_reg(gc2375h->client, 0x20, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) ret |= gc2375h_write_reg(gc2375h->client, 0x22, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) ret |= gc2375h_write_reg(gc2375h->client, 0x26, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) GC2375H_ANALOG_GAIN_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) temp = 64 * a_gain / GC2375H_ANALOG_GAIN_9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) GC2375H_PREGAIN_H_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) temp >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) GC2375H_PREGAIN_L_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) (temp << 2) & 0xfc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) static int gc2375h_set_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) struct gc2375h *gc2375h = container_of(ctrl->handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) struct gc2375h, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) struct i2c_client *client = gc2375h->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) s64 max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) /* Propagate change of current control to all related controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) case V4L2_CID_VBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) /* Update max exposure while meeting expected vblanking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) max = gc2375h->cur_mode->height + ctrl->val - 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) __v4l2_ctrl_modify_range(gc2375h->exposure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) gc2375h->exposure->minimum, max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) gc2375h->exposure->step,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) gc2375h->exposure->default_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (!pm_runtime_get_if_in_use(&client->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) case V4L2_CID_EXPOSURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) /* 4 least significant bits of expsoure are fractional part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) GC2375H_PAGE_SELECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) GC2375H_REG_EXPOSURE_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) (ctrl->val >> 8) & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) GC2375H_REG_EXPOSURE_L,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) ctrl->val & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) case V4L2_CID_ANALOGUE_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) ret = gc2375h_set_gain_reg(gc2375h, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) case V4L2_CID_VBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) GC2375H_PAGE_SELECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) GC2375H_REG_VTS_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) ((ctrl->val) >> 8) & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) ret |= gc2375h_write_reg(gc2375h->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) GC2375H_REG_VTS_L,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) (ctrl->val & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) __func__, ctrl->id, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) break;
^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) pm_runtime_put(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) static const struct v4l2_ctrl_ops gc2375h_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) .s_ctrl = gc2375h_set_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) static int gc2375h_initialize_controls(struct gc2375h *gc2375h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) const struct gc2375h_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) struct v4l2_ctrl_handler *handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) struct v4l2_ctrl *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) s64 exposure_max, vblank_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) u32 h_blank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) struct device *dev = &gc2375h->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) dev_info(dev, "Enter %s(%d) !\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) handler = &gc2375h->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) mode = gc2375h->cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) ret = v4l2_ctrl_handler_init(handler, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) handler->lock = &gc2375h->mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 0, 0, link_freq_menu_items);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 0, GC2375H_PIXEL_RATE, 1, GC2375H_PIXEL_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) h_blank = mode->hts_def - mode->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) gc2375h->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) h_blank, h_blank, 1, h_blank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (gc2375h->hblank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) gc2375h->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) vblank_def = mode->vts_def - mode->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) gc2375h->vblank = v4l2_ctrl_new_std(handler, &gc2375h_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) V4L2_CID_VBLANK, vblank_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) GC2375H_VTS_MAX - mode->height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 1, vblank_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) exposure_max = mode->vts_def - 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) gc2375h->exposure = v4l2_ctrl_new_std(handler, &gc2375h_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) V4L2_CID_EXPOSURE, GC2375H_EXPOSURE_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) exposure_max, GC2375H_EXPOSURE_STEP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) mode->exp_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) gc2375h->anal_gain = v4l2_ctrl_new_std(handler, &gc2375h_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) V4L2_CID_ANALOGUE_GAIN, GC2375H_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) GC2375H_GAIN_MAX, GC2375H_GAIN_STEP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) GC2375H_GAIN_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) if (handler->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) ret = handler->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) dev_err(&gc2375h->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) "Failed to init controls(%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) goto err_free_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) gc2375h->subdev.ctrl_handler = handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) err_free_handler:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) v4l2_ctrl_handler_free(handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) static int gc2375h_check_sensor_id(struct gc2375h *gc2375h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) struct device *dev = &gc2375h->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) u8 pid, ver = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) unsigned short id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) ret = gc2375h_read_reg(client, GC2375H_REG_CHIP_ID_H, &pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) dev_err(dev, "Read chip ID H register error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) ret = gc2375h_read_reg(client, GC2375H_REG_CHIP_ID_L, &ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) dev_err(dev, "Read chip ID L register error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) id = SENSOR_ID(pid, ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (id != CHIP_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) dev_info(dev, "detected gc%04x sensor\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) static int gc2375h_configure_regulators(struct gc2375h *gc2375h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) for (i = 0; i < GC2375H_NUM_SUPPLIES; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) gc2375h->supplies[i].supply = gc2375h_supply_names[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) return devm_regulator_bulk_get(&gc2375h->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) GC2375H_NUM_SUPPLIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) gc2375h->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) static int gc2375h_parse_of(struct gc2375h *gc2375h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) struct device *dev = &gc2375h->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) struct device_node *endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) struct fwnode_handle *fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (!endpoint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) dev_err(dev, "Failed to get endpoint\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) fwnode = of_fwnode_handle(endpoint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) of_node_put(endpoint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) if (rval <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) dev_warn(dev, " Get mipi lane num failed!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) gc2375h->lane_num = rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) if (1 == gc2375h->lane_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) gc2375h->cur_mode = &supported_modes_1lane[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) supported_modes = supported_modes_1lane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) gc2375h->cfg_num = ARRAY_SIZE(supported_modes_1lane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) gc2375h->pixel_rate = MIPI_FREQ * 2U * gc2375h->lane_num / 10U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) dev_info(dev, "lane_num(%d) pixel_rate(%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) gc2375h->lane_num, gc2375h->pixel_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) dev_err(dev, "unsupported lane_num(%d)\n", gc2375h->lane_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) static int gc2375h_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) struct device *dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) struct device_node *node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) struct gc2375h *gc2375h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) char facing[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) dev_info(dev, "driver version: %02x.%02x.%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) DRIVER_VERSION >> 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) (DRIVER_VERSION & 0xff00) >> 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) DRIVER_VERSION & 0x00ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) gc2375h = devm_kzalloc(dev, sizeof(*gc2375h), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (!gc2375h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) &gc2375h->module_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) &gc2375h->module_facing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) &gc2375h->module_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) &gc2375h->len_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) dev_err(dev, "could not get module information!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) gc2375h->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) gc2375h->cur_mode = &supported_modes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) gc2375h->xvclk = devm_clk_get(dev, "xvclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if (IS_ERR(gc2375h->xvclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) dev_err(dev, "Failed to get xvclk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) gc2375h->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (IS_ERR(gc2375h->reset_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) dev_warn(dev, "Failed to get reset-gpios\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) gc2375h->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (IS_ERR(gc2375h->pwdn_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) dev_warn(dev, "Failed to get pwdn-gpios\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) ret = gc2375h_parse_of(gc2375h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) gc2375h->pinctrl = devm_pinctrl_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (!IS_ERR(gc2375h->pinctrl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) gc2375h->pins_default =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) pinctrl_lookup_state(gc2375h->pinctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) OF_CAMERA_PINCTRL_STATE_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) if (IS_ERR(gc2375h->pins_default))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) dev_err(dev, "could not get default pinstate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) gc2375h->pins_sleep =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) pinctrl_lookup_state(gc2375h->pinctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) OF_CAMERA_PINCTRL_STATE_SLEEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) if (IS_ERR(gc2375h->pins_sleep))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) dev_err(dev, "could not get sleep pinstate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) dev_err(dev, "no pinctrl\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) ret = gc2375h_configure_regulators(gc2375h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) dev_err(dev, "Failed to get power regulators\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) mutex_init(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) sd = &gc2375h->subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) v4l2_i2c_subdev_init(sd, client, &gc2375h_subdev_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) ret = gc2375h_initialize_controls(gc2375h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) goto err_destroy_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) ret = __gc2375h_power_on(gc2375h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) goto err_free_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) ret = gc2375h_check_sensor_id(gc2375h, client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) goto err_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) sd->internal_ops = &gc2375h_internal_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) gc2375h->pad.flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) ret = media_entity_pads_init(&sd->entity, 1, &gc2375h->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) goto err_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) memset(facing, 0, sizeof(facing));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) if (strcmp(gc2375h->module_facing, "back") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) facing[0] = 'b';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) facing[0] = 'f';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) gc2375h->module_index, facing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) GC2375H_NAME, dev_name(sd->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) ret = v4l2_async_register_subdev_sensor_common(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) dev_err(dev, "v4l2 async register subdev failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) goto err_clean_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) pm_runtime_set_active(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) pm_runtime_enable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) pm_runtime_idle(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) err_clean_entity:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) media_entity_cleanup(&sd->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) err_power_off:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) __gc2375h_power_off(gc2375h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) err_free_handler:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) v4l2_ctrl_handler_free(&gc2375h->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) err_destroy_mutex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) mutex_destroy(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) static int gc2375h_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) struct gc2375h *gc2375h = to_gc2375h(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) v4l2_async_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) media_entity_cleanup(&sd->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) v4l2_ctrl_handler_free(&gc2375h->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) mutex_destroy(&gc2375h->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) pm_runtime_disable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) if (!pm_runtime_status_suspended(&client->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) __gc2375h_power_off(gc2375h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) pm_runtime_set_suspended(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) #if IS_ENABLED(CONFIG_OF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) static const struct of_device_id gc2375h_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) { .compatible = "galaxycore,gc2375h" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) MODULE_DEVICE_TABLE(of, gc2375h_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) static const struct i2c_device_id gc2375h_match_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) { "galaxycore,gc2375h", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) static struct i2c_driver gc2375h_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) .name = GC2375H_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) .pm = &gc2375h_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) .of_match_table = of_match_ptr(gc2375h_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) .probe = &gc2375h_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) .remove = &gc2375h_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) .id_table = gc2375h_match_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) static int __init sensor_mod_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) return i2c_add_driver(&gc2375h_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) static void __exit sensor_mod_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) i2c_del_driver(&gc2375h_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) device_initcall_sync(sensor_mod_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) module_exit(sensor_mod_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) MODULE_DESCRIPTION("GC2375H CMOS Image Sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) MODULE_LICENSE("GPL v2");