^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) * gc0403 driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2019 Fuzhou Rockchip Electronics Co.,Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * V0.0X01.0X02 add enum_frame_interval function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * V0.0X01.0X03 add quick stream on/off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * V0.0X01.0X04 add function g_mbus_config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <media/media-entity.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <media/v4l2-async.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <media/v4l2-subdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/rk-camera-module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/version.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * GC0403 register definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define GC0403_REG_EXP_H 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define GC0403_REG_EXP_L 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define GC0403_REG_VBLK_H 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define GC0403_REG_VBLK_L 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define GC0403_REG_MIPI_EN 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define GC0403_REG_DGAIN_H 0xb1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define GC0403_REG_DGAIN_L 0xb2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define GC0403_REG_AGAIN 0xb6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define GC0403_REG_CHIP_ID_H 0xf0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define GC0403_REG_CHIP_ID_L 0xf1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define PAGE_SELECT_REG 0xfe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define REG_NULL 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define GC0403_CHIP_ID 0x0403
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define SENSOR_ID(_msb, _lsb) ((_msb) << 8 | (_lsb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define GC0403_ANALOG_GAIN_MIN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define GC0403_ANALOG_GAIN_MAX 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define GC0403_ANALOG_GAIN_STP 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define GC0403_ANALOG_GAIN_DFT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* gain[4:0] [0x00,0x0a]*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define GC0403_FETCH_ANALOG_GAIN(VAL) ((VAL) & 0x0F)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #ifndef V4L2_CID_DIGITAL_GAIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define GC0403_DIGI_GAIN_MIN 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define GC0403_DIGI_GAIN_MAX 0x3ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define GC0403_DIGI_GAIN_STP 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define GC0403_DIGI_GAIN_DFT 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* gain[9:6] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define GC0403_FETCH_DIGITAL_GAIN_HIGH(VAL) (((VAL) >> 6) & 0x0F)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* gain[5:0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define GC0403_FETCH_DIGITAL_GAIN_LOW(VAL) (((VAL) << 2) & 0xFC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define GC0403_TOTAL_GAIN_MIN 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define GC0403_TOTAL_GAIN_MAX 3200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define GC0403_TOTAL_GAIN_STEP 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define GC0403_EXPOSURE_MAX 8191
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define GC0403_EXPOSURE_MIN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define GC0403_NAME "gc0403"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define GC0403_XVCLK_FREQ 24000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define GC0403_LINK_FREQ 96000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define GC0403_PIXEL_RATE (GC0403_LINK_FREQ * 2 * 1 / 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define GC0403_LANES 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static const s64 link_freq_menu_items[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) GC0403_LINK_FREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static const char * const gc0403_supply_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) "dovdd", /* Digital I/O power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) "avdd", /* Analog power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define GC0403_NUM_SUPPLIES ARRAY_SIZE(gc0403_supply_names)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct regval {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u8 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct gc0403_mode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) u32 width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u32 height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct v4l2_fract max_fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u32 hts_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u32 vts_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u32 exp_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) const struct regval *reg_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct gc0403 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct clk *xvclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct gpio_desc *pwdn_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct regulator_bulk_data supplies[GC0403_NUM_SUPPLIES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct v4l2_subdev subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct media_pad pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct v4l2_ctrl_handler ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct v4l2_ctrl *exposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct v4l2_ctrl *anal_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct v4l2_ctrl *digi_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct v4l2_ctrl *hblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct v4l2_ctrl *vblank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* mutex lock, protect current operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct mutex mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) bool streaming;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) const struct gc0403_mode *cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) u32 module_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) const char *module_facing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) const char *module_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) const char *len_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define to_gc0403(sd) container_of(sd, struct gc0403, subdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * MCLK=24Mhz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * MIPI_CLOCK=192Mbps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * Actual_window_size=640*480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * HD=1362
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * VD=586
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * row_time=56.75us,FPS = 30fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static const struct regval gc0403_vga_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /****SYS****/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {0xfe, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {0xfe, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {0xfe, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {0xf2, 0x00}, /* sync_pad_io_ebi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {0xf6, 0x00}, /*up down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {0xfc, 0xc6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {0xf7, 0x19}, /* pll enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {0xf8, 0x01}, /* Pll mode 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {0xf9, 0x3e}, /* [0] pll enable solve IOVDD large current problem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {0xfe, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {0x06, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {0x06, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {0xf9, 0x2e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {0xfa, 0x00}, /* div */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /**ANALOG&CISCTL**/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {0x03, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {0x04, 0x55},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {0x05, 0x01}, /* H blank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {0x06, 0x49}, /* H blank=bb=187 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {0x07, 0x00}, /* VB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {0x08, 0x5a}, /* VB=E8=232 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {0x09, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {0x0a, 0x2c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {0x0b, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {0x0c, 0x3c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {0x0d, 0x01}, /* win_height */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {0x0e, 0xf0}, /* 496 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {0x0f, 0x02}, /* win_width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {0x10, 0x90}, /* 656 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {0x11, 0x23}, /* 44FPN abnormal column */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {0x12, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {0x13, 0x11},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {0x14, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {0x15, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {0x16, 0xc0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {0x17, 0x14},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {0x18, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {0x19, 0x38},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {0x1a, 0x11},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {0x1b, 0x06},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {0x1c, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {0x1d, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {0x1e, 0xfc},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {0x1f, 0x09},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {0x20, 0xb5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {0x21, 0x3f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {0x22, 0xe6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {0x23, 0x32},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {0x24, 0x2f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {0x27, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {0x28, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {0x2a, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {0x2b, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {0x2c, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {0x2d, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {0x2e, 0xf0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {0x2f, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {0x25, 0xc0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {0x3d, 0xe0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {0x3e, 0x45},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {0x3f, 0x1f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {0xc2, 0x17},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {0x30, 0x22},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {0x31, 0x23},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {0x32, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {0x33, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {0x34, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {0x35, 0x05},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {0x36, 0x06},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {0x37, 0x07},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {0x38, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {0x39, 0x17},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {0x3a, 0x1f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /****ISP****/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {0x8a, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {0x8c, 0x07},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {0x8e, 0x02}, /* luma value not normal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {0x90, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {0x94, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {0x95, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {0x96, 0xe0}, /* 480 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {0x97, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {0x98, 0x80}, /* 640 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /****BLK****/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {0x18, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {0x40, 0x22},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {0x41, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {0x5e, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {0x66, 0x20},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /****MIPI****/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {0xfe, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {0x01, 0x83},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {0x02, 0x11},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {0x03, 0x96},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {0x04, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {0x05, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {0x06, 0xa4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {0x10, 0x90},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {0x11, 0x2b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {0x12, 0x20},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {0x13, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {0x15, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {0x21, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {0x22, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {0x23, 0x20},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {0x24, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {0x25, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {0x26, 0x05},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {0x21, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {0x29, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {0x2a, 0x0a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {0x2b, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {0xb0, 0x50},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {0xb6, 0x09},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {REG_NULL, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * MCLK=24Mhz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * MIPI_CLOCK=192Mbps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * Actual_window_size=768*576
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * HD=1206
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * VD=663
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * row_time=50.25us,FPS = 30fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static const struct regval gc0403_768x576_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /****SYS****/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {0xfe, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {0xfe, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {0xfe, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {0xf2, 0x00}, /* sync_pad_io_ebi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {0xf6, 0x00}, /* up down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {0xfc, 0xc6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {0xf7, 0x19}, /* pll enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {0xf8, 0x01}, /* Pll mode 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {0xf9, 0x3e}, /* [0] pll enable solve IOVDD large current problem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {0xfe, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {0x06, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {0x06, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {0xf9, 0x2e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {0xfa, 0x00}, /* div */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /**ANALOG&CISCTL**/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {0x03, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {0x04, 0x55},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {0x05, 0x00}, /* H blank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {0x06, 0xbb}, /* H blank=bb=187 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {0x07, 0x00}, /* VB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {0x08, 0x46}, /* VB=E8=232 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {0x0c, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {0x0d, 0x02}, /* win_height */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {0x0e, 0x48}, /* 584 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {0x0f, 0x03}, /* win_width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {0x10, 0x08}, /* 776 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {0x11, 0x23}, /* 44FPN abnormal column */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {0x12, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {0x13, 0x11},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) {0x14, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {0x15, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {0x16, 0xc0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {0x17, 0x14},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {0x18, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {0x19, 0x38},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {0x1a, 0x11},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {0x1b, 0x06},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {0x1c, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {0x1d, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {0x1e, 0xfc},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {0x1f, 0x09},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {0x20, 0xb5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {0x21, 0x3f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {0x22, 0xe6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {0x23, 0x32},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {0x24, 0x2f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {0x27, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {0x28, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {0x2a, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {0x2b, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {0x2c, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {0x2d, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {0x2e, 0xf0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {0x2f, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {0x25, 0xc0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {0x3d, 0xe0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {0x3e, 0x45},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {0x3f, 0x1f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {0xc2, 0x17},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {0x30, 0x22},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {0x31, 0x23},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {0x32, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {0x33, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {0x34, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {0x35, 0x05},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {0x36, 0x06},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {0x37, 0x07},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {0x38, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {0x39, 0x17},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {0x3a, 0x1f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /****ISP****/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {0x8a, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {0x8c, 0x07},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {0x8e, 0x02}, /* luma value not normal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {0x90, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {0x94, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {0x95, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {0x96, 0x40}, /* 576 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {0x97, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {0x98, 0x00}, /* 768 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /****BLK****/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {0x18, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {0x40, 0x22},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {0x41, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {0x5e, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {0x66, 0x20},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /****MIPI****/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {0xfe, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {0x01, 0x83},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {0x02, 0x11},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {0x03, 0x96},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {0x04, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {0x05, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {0x06, 0xa4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {0x10, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {0x11, 0x2b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {0x12, 0xc0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {0x13, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {0x15, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {0x21, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {0x22, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {0x23, 0x20},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {0x24, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {0x25, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {0x26, 0x05},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {0x21, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {0x29, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {0x2a, 0x0a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {0x2b, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {0xfe, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {0xb0, 0x50},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {0xb6, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {REG_NULL, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static const struct gc0403_mode supported_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) .width = 640,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) .height = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .max_fps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .numerator = 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) .denominator = 300000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) .exp_def = 500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .hts_def = 1362,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .vts_def = 586,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .reg_list = gc0403_vga_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .width = 768,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .height = 576,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .max_fps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) .numerator = 10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) .denominator = 300000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) .exp_def = 500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) .hts_def = 1206,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) .vts_def = 663,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) .reg_list = gc0403_768x576_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* sensor register write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int gc0403_write_reg(struct i2c_client *client, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct i2c_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) u8 buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) buf[0] = reg & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) buf[1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) msg.addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) msg.flags = client->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) msg.buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) msg.len = sizeof(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) ret = i2c_transfer(client->adapter, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) "gc0403 write reg(0x%x val:0x%x) failed !\n", reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static int gc0403_write_array(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) const struct regval *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) while (regs[i].addr != REG_NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ret = gc0403_write_reg(client, regs[i].addr, regs[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) dev_err(&client->dev, "%s failed !\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* sensor register read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int gc0403_read_reg(struct i2c_client *client, u8 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct i2c_msg msg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) u8 buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) buf[0] = reg & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) msg[0].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) msg[0].flags = client->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) msg[0].buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) msg[0].len = sizeof(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) msg[1].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) msg[1].flags = client->flags | I2C_M_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) msg[1].buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) msg[1].len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) ret = i2c_transfer(client->adapter, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (ret >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) *val = buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) "gc0403 read reg(0x%x val:0x%x) failed !\n", reg, *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static int gc0403_get_reso_dist(const struct gc0403_mode *mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct v4l2_mbus_framefmt *framefmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return abs(mode->width - framefmt->width) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) abs(mode->height - framefmt->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static const struct gc0403_mode *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) gc0403_find_best_fit(struct v4l2_subdev_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct v4l2_mbus_framefmt *framefmt = &fmt->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) int dist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) int cur_best_fit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) int cur_best_fit_dist = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) dist = gc0403_get_reso_dist(&supported_modes[i], framefmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) cur_best_fit_dist = dist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) cur_best_fit = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return &supported_modes[cur_best_fit];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int gc0403_set_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct v4l2_subdev_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct gc0403 *gc0403 = to_gc0403(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) const struct gc0403_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) mutex_lock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) mode = gc0403_find_best_fit(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) fmt->format.code = MEDIA_BUS_FMT_SRGGB10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) fmt->format.width = mode->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) fmt->format.height = mode->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) fmt->format.field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) mutex_unlock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) gc0403->cur_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mutex_unlock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return 0;
^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 gc0403_get_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 gc0403 *gc0403 = to_gc0403(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) const struct gc0403_mode *mode = gc0403->cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) mutex_lock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) mutex_unlock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) fmt->format.width = mode->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) fmt->format.height = mode->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) fmt->format.code = MEDIA_BUS_FMT_SRGGB10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) fmt->format.field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) mutex_unlock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static int gc0403_enum_mbus_code(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) struct v4l2_subdev_mbus_code_enum *code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (code->index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) code->code = MEDIA_BUS_FMT_SRGGB10_1X10;
^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 gc0403_enum_frame_sizes(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_frame_size_enum *fse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (fse->index >= ARRAY_SIZE(supported_modes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (fse->code != MEDIA_BUS_FMT_SRGGB10_1X10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) fse->min_width = supported_modes[fse->index].width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) fse->max_width = supported_modes[fse->index].width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) fse->max_height = supported_modes[fse->index].height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) fse->min_height = supported_modes[fse->index].height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) static int gc0403_g_frame_interval(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct v4l2_subdev_frame_interval *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) struct gc0403 *gc0403 = to_gc0403(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) const struct gc0403_mode *mode = gc0403->cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) mutex_lock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) fi->interval = mode->max_fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) mutex_unlock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) static void gc0403_get_module_inf(struct gc0403 *gc0403,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) struct rkmodule_inf *inf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) memset(inf, 0, sizeof(*inf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) strlcpy(inf->base.sensor, GC0403_NAME, sizeof(inf->base.sensor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) strlcpy(inf->base.module, gc0403->module_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) sizeof(inf->base.module));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) strlcpy(inf->base.lens, gc0403->len_name, sizeof(inf->base.lens));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) static long gc0403_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) struct gc0403 *gc0403 = to_gc0403(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) long ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) u32 stream = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) case RKMODULE_GET_MODULE_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) gc0403_get_module_inf(gc0403, (struct rkmodule_inf *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) case RKMODULE_SET_QUICK_STREAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) stream = *((u32 *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ret = gc0403_write_reg(gc0403->client, PAGE_SELECT_REG, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) ret |= gc0403_write_reg(gc0403->client, GC0403_REG_MIPI_EN, 0x90);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) ret |= gc0403_write_reg(gc0403->client, PAGE_SELECT_REG, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) ret = gc0403_write_reg(gc0403->client, PAGE_SELECT_REG, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) ret |= gc0403_write_reg(gc0403->client, GC0403_REG_MIPI_EN, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ret |= gc0403_write_reg(gc0403->client, PAGE_SELECT_REG, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) ret = -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) break;
^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) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static long gc0403_compat_ioctl32(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) void __user *up = compat_ptr(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct rkmodule_inf *inf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct rkmodule_awb_cfg *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) u32 stream = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) case RKMODULE_GET_MODULE_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) inf = kzalloc(sizeof(*inf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (!inf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) ret = gc0403_ioctl(sd, cmd, inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) ret = copy_to_user(up, inf, sizeof(*inf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) kfree(inf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) case RKMODULE_AWB_CFG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (!cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ret = copy_from_user(cfg, up, sizeof(*cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) ret = gc0403_ioctl(sd, cmd, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) kfree(cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) case RKMODULE_SET_QUICK_STREAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ret = copy_from_user(&stream, up, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) ret = gc0403_ioctl(sd, cmd, &stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ret = -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static int __gc0403_start_stream(struct gc0403 *gc0403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /* In case these controls are set before streaming */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) mutex_unlock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) ret = v4l2_ctrl_handler_setup(&gc0403->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) mutex_lock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) ret = gc0403_write_reg(gc0403->client, PAGE_SELECT_REG, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) ret |= gc0403_write_reg(gc0403->client, GC0403_REG_MIPI_EN, 0x90);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ret |= gc0403_write_reg(gc0403->client, PAGE_SELECT_REG, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) static int __gc0403_stop_stream(struct gc0403 *gc0403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) ret = gc0403_write_reg(gc0403->client, PAGE_SELECT_REG, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ret |= gc0403_write_reg(gc0403->client, GC0403_REG_MIPI_EN, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) ret |= gc0403_write_reg(gc0403->client, PAGE_SELECT_REG, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static int __gc0403_power_on(struct gc0403 *gc0403);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) static void __gc0403_power_off(struct gc0403 *gc0403);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) static int gc0403_s_power(struct v4l2_subdev *sd, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct gc0403 *gc0403 = to_gc0403(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) mutex_lock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) on = !!on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) ret = pm_runtime_get_sync(&gc0403->client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) ret = pm_runtime_put(&gc0403->client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) mutex_unlock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) static int gc0403_s_stream(struct v4l2_subdev *sd, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) struct gc0403 *gc0403 = to_gc0403(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) mutex_lock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) on = !!on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (on == gc0403->streaming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) ret = __gc0403_start_stream(gc0403);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) v4l2_err(sd, "start stream failed while write regs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) goto unlock_and_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) __gc0403_stop_stream(gc0403);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) usleep_range(33 * 1000, 35 * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) gc0403->streaming = on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) unlock_and_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) mutex_unlock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) /* Calculate the delay in us by clock rate and clock cycles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static int __gc0403_power_on(struct gc0403 *gc0403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) struct device *dev = &gc0403->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) ret = clk_set_rate(gc0403->xvclk, GC0403_XVCLK_FREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (clk_get_rate(gc0403->xvclk) != GC0403_XVCLK_FREQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) dev_warn(dev, "xvclk mismatched,modes are based on 24MHz\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) ret = clk_prepare_enable(gc0403->xvclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) dev_err(dev, "Failed to enable xvclk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) ret = regulator_bulk_enable(GC0403_NUM_SUPPLIES, gc0403->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) dev_err(dev, "Failed to enable regulators\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) goto disable_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (!IS_ERR(gc0403->pwdn_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) gpiod_set_value_cansleep(gc0403->pwdn_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /* here usleep at least 10~15ms,will better */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) usleep_range(10 * 1000, 15 * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) ret = gc0403_write_array(gc0403->client, gc0403->cur_mode->reg_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) usleep_range(10 * 1000, 20 * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) disable_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) clk_disable_unprepare(gc0403->xvclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) static void __gc0403_power_off(struct gc0403 *gc0403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (!IS_ERR(gc0403->pwdn_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) gpiod_set_value_cansleep(gc0403->pwdn_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) clk_disable_unprepare(gc0403->xvclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) regulator_bulk_disable(GC0403_NUM_SUPPLIES, gc0403->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static int gc0403_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) struct gc0403 *gc0403 = to_gc0403(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) ret = __gc0403_power_on(gc0403);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) if (gc0403->streaming) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) ret = gc0403_s_stream(sd, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) __gc0403_power_off(gc0403);
^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) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) static int gc0403_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) struct gc0403 *gc0403 = to_gc0403(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) __gc0403_power_off(gc0403);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) static int gc0403_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) struct gc0403 *gc0403 = to_gc0403(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) struct v4l2_mbus_framefmt *try_fmt =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) v4l2_subdev_get_try_format(sd, fh->pad, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) const struct gc0403_mode *def_mode = &supported_modes[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) mutex_lock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /* Initialize try_fmt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) try_fmt->width = def_mode->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) try_fmt->height = def_mode->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) try_fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) try_fmt->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) mutex_unlock(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* No crop or compose */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) static int gc0403_enum_frame_interval(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct v4l2_subdev_frame_interval_enum *fie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (fie->index >= ARRAY_SIZE(supported_modes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (fie->code != MEDIA_BUS_FMT_SRGGB10_1X10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) fie->width = supported_modes[fie->index].width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) fie->height = supported_modes[fie->index].height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) fie->interval = supported_modes[fie->index].max_fps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static int gc0403_g_mbus_config(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct v4l2_mbus_config *config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) u32 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) val = 1 << (GC0403_LANES - 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) V4L2_MBUS_CSI2_CHANNEL_0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) config->type = V4L2_MBUS_CSI2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) config->flags = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) static const struct dev_pm_ops gc0403_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) SET_RUNTIME_PM_OPS(gc0403_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) gc0403_runtime_resume, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) static const struct v4l2_subdev_internal_ops gc0403_internal_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .open = gc0403_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static struct v4l2_subdev_core_ops gc0403_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) .s_power = gc0403_s_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) .ioctl = gc0403_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) .compat_ioctl32 = gc0403_compat_ioctl32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) static const struct v4l2_subdev_video_ops gc0403_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) .s_stream = gc0403_s_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) .g_frame_interval = gc0403_g_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) .g_mbus_config = gc0403_g_mbus_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) static const struct v4l2_subdev_pad_ops gc0403_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) .enum_mbus_code = gc0403_enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) .enum_frame_size = gc0403_enum_frame_sizes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) .enum_frame_interval = gc0403_enum_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) .get_fmt = gc0403_get_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) .set_fmt = gc0403_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) static const struct v4l2_subdev_ops gc0403_subdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) .core = &gc0403_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) .video = &gc0403_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) .pad = &gc0403_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) static int gc0403_set_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) struct gc0403 *gc0403 = container_of(ctrl->handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) struct gc0403, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) struct i2c_client *client = gc0403->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) int analog_gain_table[] = {100, 142, 250, 354, 490, 691, 970,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) 1363, 1945, 2704, 3889};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) int table_cnt = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) int analog_gain_reg_value = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) int digital_gain_reg_value = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) int total_gain = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) int analog_gain = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (!pm_runtime_get_if_in_use(&client->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) case V4L2_CID_EXPOSURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) dev_dbg(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) "gc0403: V4L2_CID_EXPOSURE exp val = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) /* 4 least significant bits of expsoure are fractional part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) ret = gc0403_write_reg(gc0403->client, GC0403_REG_EXP_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) (ctrl->val >> 8) & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) ret |= gc0403_write_reg(gc0403->client, GC0403_REG_EXP_L,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) ctrl->val & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) case V4L2_CID_ANALOGUE_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) case V4L2_CID_DIGITAL_GAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) total_gain = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) for (i = 0; i < table_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (total_gain < analog_gain_table[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) i = i - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (i < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) analog_gain = analog_gain_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) analog_gain_reg_value = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) digital_gain_reg_value = total_gain * 64 / analog_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (analog_gain_reg_value < GC0403_ANALOG_GAIN_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) analog_gain_reg_value = GC0403_ANALOG_GAIN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (analog_gain_reg_value > GC0403_ANALOG_GAIN_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) analog_gain_reg_value = GC0403_ANALOG_GAIN_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (digital_gain_reg_value < GC0403_DIGI_GAIN_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) digital_gain_reg_value = GC0403_DIGI_GAIN_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (digital_gain_reg_value > GC0403_DIGI_GAIN_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) digital_gain_reg_value = GC0403_DIGI_GAIN_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) ret = gc0403_write_reg(gc0403->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) GC0403_REG_AGAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) GC0403_FETCH_ANALOG_GAIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) (analog_gain_reg_value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) ret |= gc0403_write_reg(gc0403->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) GC0403_REG_DGAIN_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) GC0403_FETCH_DIGITAL_GAIN_HIGH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) (digital_gain_reg_value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) ret |= gc0403_write_reg(gc0403->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) GC0403_REG_DGAIN_L,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) GC0403_FETCH_DIGITAL_GAIN_LOW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) (digital_gain_reg_value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) dev_dbg(&client->dev, "gc0403: gain: %d,a: %d,d: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) total_gain, analog_gain_reg_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) digital_gain_reg_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) case V4L2_CID_VBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) ret = gc0403_write_reg(gc0403->client, GC0403_REG_VBLK_H,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) (ctrl->val) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) ret |= gc0403_write_reg(gc0403->client, GC0403_REG_VBLK_L,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) (ctrl->val) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) __func__, ctrl->id, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) pm_runtime_put(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) static const struct v4l2_ctrl_ops gc0403_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) .s_ctrl = gc0403_set_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) static int gc0403_initialize_controls(struct gc0403 *gc0403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) const struct gc0403_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) struct v4l2_ctrl_handler *handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) struct v4l2_ctrl *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) s64 vblank_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) u32 h_blank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) handler = &gc0403->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) mode = gc0403->cur_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) ret = v4l2_ctrl_handler_init(handler, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) handler->lock = &gc0403->mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 0, 0, link_freq_menu_items);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 0, GC0403_PIXEL_RATE, 1, GC0403_PIXEL_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) h_blank = mode->hts_def - mode->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) gc0403->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) h_blank, h_blank, 1, h_blank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (gc0403->hblank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) gc0403->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) vblank_def = mode->vts_def - mode->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) gc0403->vblank = v4l2_ctrl_new_std(handler, &gc0403_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) V4L2_CID_VBLANK, vblank_def, vblank_def,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 1, vblank_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) gc0403->exposure = v4l2_ctrl_new_std(handler, &gc0403_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) V4L2_CID_EXPOSURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) GC0403_EXPOSURE_MIN, GC0403_EXPOSURE_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 1, mode->exp_def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) /* Anolog gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) gc0403->anal_gain = v4l2_ctrl_new_std(handler, &gc0403_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) V4L2_CID_ANALOGUE_GAIN, GC0403_TOTAL_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) GC0403_TOTAL_GAIN_MAX, GC0403_TOTAL_GAIN_STEP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) GC0403_TOTAL_GAIN_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /* Digital gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) gc0403->digi_gain = v4l2_ctrl_new_std(handler, &gc0403_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) V4L2_CID_DIGITAL_GAIN, GC0403_TOTAL_GAIN_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) GC0403_TOTAL_GAIN_MAX, GC0403_TOTAL_GAIN_STEP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) GC0403_TOTAL_GAIN_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (handler->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) ret = handler->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) dev_err(&gc0403->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) "Failed to init controls(%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) goto err_free_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) gc0403->subdev.ctrl_handler = handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) err_free_handler:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) v4l2_ctrl_handler_free(handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) static int gc0403_check_sensor_id(struct gc0403 *gc0403,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) struct device *dev = &gc0403->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) u8 pid = 0, ver = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) u16 id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) /* Check sensor revision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) ret = gc0403_read_reg(client, GC0403_REG_CHIP_ID_H, &pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) ret |= gc0403_read_reg(client, GC0403_REG_CHIP_ID_L, &ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) dev_err(&client->dev, "gc0403_read_reg failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) id = SENSOR_ID(pid, ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (id != GC0403_CHIP_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) "Sensor detection failed (%04X,%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) id, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) dev_info(dev, "Detected GC%04x sensor\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) static int gc0403_configure_regulators(struct gc0403 *gc0403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) for (i = 0; i < GC0403_NUM_SUPPLIES; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) gc0403->supplies[i].supply = gc0403_supply_names[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return devm_regulator_bulk_get(&gc0403->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) GC0403_NUM_SUPPLIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) gc0403->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) static int gc0403_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) struct device *dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) /* add a dev_node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) struct device_node *node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) struct gc0403 *gc0403;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) char facing[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /* add info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) dev_info(dev, "driver version: %02x.%02x.%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) DRIVER_VERSION >> 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) (DRIVER_VERSION & 0xff00) >> 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) DRIVER_VERSION & 0x00ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) gc0403 = devm_kzalloc(dev, sizeof(*gc0403), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (!gc0403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) &gc0403->module_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) &gc0403->module_facing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) &gc0403->module_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) &gc0403->len_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) dev_err(dev, "could not get module information!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) gc0403->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) gc0403->cur_mode = &supported_modes[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) gc0403->xvclk = devm_clk_get(dev, "xvclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (IS_ERR(gc0403->xvclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) dev_err(dev, "Failed to get xvclk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) gc0403->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (IS_ERR(gc0403->pwdn_gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) dev_warn(dev, "Failed to get pwdn-gpios\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) ret = gc0403_configure_regulators(gc0403);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) dev_err(dev, "Failed to get power regulators\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) mutex_init(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) sd = &gc0403->subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) v4l2_i2c_subdev_init(sd, client, &gc0403_subdev_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) ret = gc0403_initialize_controls(gc0403);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) goto err_destroy_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) ret = __gc0403_power_on(gc0403);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) goto err_free_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) ret = gc0403_check_sensor_id(gc0403, client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) goto err_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) sd->internal_ops = &gc0403_internal_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) V4L2_SUBDEV_FL_HAS_EVENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) gc0403->pad.flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) ret = media_entity_pads_init(&sd->entity, 1, &gc0403->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) goto err_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) memset(facing, 0, sizeof(facing));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (strcmp(gc0403->module_facing, "back") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) facing[0] = 'b';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) facing[0] = 'f';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) gc0403->module_index, facing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) GC0403_NAME, dev_name(sd->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) ret = v4l2_async_register_subdev_sensor_common(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) dev_err(dev, "v4l2 async register subdev failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) goto err_clean_entity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) pm_runtime_set_active(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) pm_runtime_enable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) pm_runtime_idle(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) err_clean_entity:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) media_entity_cleanup(&sd->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) err_power_off:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) __gc0403_power_off(gc0403);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) err_free_handler:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) v4l2_ctrl_handler_free(&gc0403->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) err_destroy_mutex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) mutex_destroy(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) static int gc0403_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) struct gc0403 *gc0403 = to_gc0403(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) v4l2_async_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) media_entity_cleanup(&sd->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) v4l2_ctrl_handler_free(&gc0403->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) mutex_destroy(&gc0403->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) pm_runtime_disable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) if (!pm_runtime_status_suspended(&client->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) __gc0403_power_off(gc0403);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) pm_runtime_set_suspended(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) #if IS_ENABLED(CONFIG_OF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) static const struct of_device_id gc0403_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) { .compatible = "galaxycore,gc0403" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) MODULE_DEVICE_TABLE(of, gc0403_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) static const struct i2c_device_id gc0403_match_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) { "gc0403", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) static struct i2c_driver gc0403_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) .name = "gc0403",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) .pm = &gc0403_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) .of_match_table = of_match_ptr(gc0403_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) .probe = &gc0403_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) .remove = &gc0403_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) .id_table = gc0403_match_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) static int __init sensor_mod_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) return i2c_add_driver(&gc0403_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) static void __exit sensor_mod_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) i2c_del_driver(&gc0403_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) device_initcall_sync(sensor_mod_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) module_exit(sensor_mod_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) MODULE_DESCRIPTION("Galaxycore gc0403 sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) MODULE_LICENSE("GPL v2");