^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) // Copyright (c) 2017 Microchip Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <media/v4l2-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <media/v4l2-image-sizes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <media/v4l2-subdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define REG_OUTSIZE_LSB 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /* OV7740 register tables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define REG_BGAIN 0x01 /* blue gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define REG_RGAIN 0x02 /* red gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define REG_GGAIN 0x03 /* green gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define REG_REG04 0x04 /* analog setting, don't change*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define REG_BAVG 0x05 /* b channel average */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define REG_GAVG 0x06 /* g channel average */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define REG_RAVG 0x07 /* r channel average */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define REG_REG0C 0x0C /* filp enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define REG0C_IMG_FLIP 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define REG0C_IMG_MIRROR 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define REG_REG0E 0x0E /* blc line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define REG_HAEC 0x0F /* auto exposure cntrl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define REG_AEC 0x10 /* auto exposure cntrl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define REG_CLK 0x11 /* Clock control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define REG_REG55 0x55 /* Clock PLL DIV/PreDiv */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define REG_REG12 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define REG_REG13 0x13 /* auto/manual AGC, AEC, Write Balance*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define REG13_AEC_EN 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define REG13_AGC_EN 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define REG_REG14 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define REG_CTRL15 0x15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define REG15_GAIN_MSB 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define REG_REG16 0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define REG_MIDH 0x1C /* manufacture id byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define REG_MIDL 0x1D /* manufacture id byre */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define REG_PIDH 0x0A /* Product ID MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define REG_PIDL 0x0B /* Product ID LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define REG_84 0x84 /* lots of stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define REG_REG38 0x38 /* sub-addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define REG_AHSTART 0x17 /* Horiz start high bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define REG_AHSIZE 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define REG_AVSTART 0x19 /* Vert start high bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define REG_AVSIZE 0x1A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define REG_PSHFT 0x1b /* Pixel delay after HREF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define REG_HOUTSIZE 0x31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define REG_VOUTSIZE 0x32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define REG_HVSIZEOFF 0x33
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define REG_REG34 0x34 /* DSP output size H/V LSB*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define REG_ISP_CTRL00 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define ISPCTRL00_AWB_EN 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define ISPCTRL00_AWB_GAIN_EN 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define REG_YGAIN 0xE2 /* ygain for contrast control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define REG_YBRIGHT 0xE3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define REG_SGNSET 0xE4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define SGNSET_YBRIGHT_MASK 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define REG_USAT 0xDD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define REG_VSAT 0xDE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct ov7740 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct v4l2_subdev subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct media_pad pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct v4l2_mbus_framefmt format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) const struct ov7740_pixfmt *fmt; /* Current format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) const struct ov7740_framesize *frmsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct clk *xvclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct v4l2_ctrl_handler ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* gain cluster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct v4l2_ctrl *auto_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct v4l2_ctrl *gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct v4l2_ctrl *auto_wb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct v4l2_ctrl *blue_balance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct v4l2_ctrl *red_balance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct v4l2_ctrl *hflip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct v4l2_ctrl *vflip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* exposure cluster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct v4l2_ctrl *auto_exposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct v4l2_ctrl *exposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* saturation/hue cluster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct v4l2_ctrl *saturation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct v4l2_ctrl *hue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct v4l2_ctrl *brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct v4l2_ctrl *contrast;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct mutex mutex; /* To serialize asynchronus callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) bool streaming; /* Streaming on/off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct gpio_desc *resetb_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct gpio_desc *pwdn_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct ov7740_pixfmt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u32 mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) enum v4l2_colorspace colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) const struct reg_sequence *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) u32 reg_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct ov7740_framesize {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) u16 width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u16 height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) const struct reg_sequence *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u32 reg_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static const struct reg_sequence ov7740_vga[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {0x55, 0x40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {0x11, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {0xd5, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {0x0c, 0x12},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {0x0d, 0x34},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {0x17, 0x25},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {0x18, 0xa0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {0x19, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {0x1a, 0xf0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {0x1b, 0x89},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {0x22, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {0x29, 0x18},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {0x2b, 0xf8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {0x2c, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {REG_HOUTSIZE, 0xa0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {REG_VOUTSIZE, 0xf0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {0x33, 0xc4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {REG_OUTSIZE_LSB, 0x0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {0x35, 0x05},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {0x04, 0x60},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {0x27, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {0x3d, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {0x3e, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {0x3f, 0x40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {0x40, 0x7f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {0x41, 0x6a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {0x42, 0x29},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {0x44, 0x22},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {0x45, 0x41},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {0x47, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {0x49, 0x64},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {0x4a, 0xa1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {0x4b, 0x40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {0x4c, 0x1a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {0x4d, 0x50},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {0x4e, 0x13},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {0x64, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {0x67, 0x88},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {0x68, 0x1a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {0x14, 0x28},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {0x24, 0x3c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {0x25, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {0x26, 0x72},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {0x50, 0x97},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {0x51, 0x1f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {0x52, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {0x53, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {0x20, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {0x21, 0xcf},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {0x50, 0x4b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {0x38, 0x14},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {0xe9, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {0x56, 0x55},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {0x57, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {0x58, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {0x59, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {0x5f, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {0xec, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {0x13, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {0x81, 0x3f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {0x82, 0x32},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {0x38, 0x11},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {0x84, 0x70},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {0x85, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {0x86, 0x03},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {0x87, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {0x88, 0x05},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {0x89, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {0x8d, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {0x8f, 0x85},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {0x93, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {0x95, 0x85},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {0x99, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {0x9b, 0x85},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {0x9c, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {0x9d, 0x12},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {0x9e, 0x23},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {0x9f, 0x45},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {0xa0, 0x55},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {0xa1, 0x64},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {0xa2, 0x72},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {0xa3, 0x7f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {0xa4, 0x8b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {0xa5, 0x95},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {0xa6, 0xa7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {0xa7, 0xb5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {0xa8, 0xcb},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {0xa9, 0xdd},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {0xaa, 0xec},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {0xab, 0x1a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {0xce, 0x78},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {0xcf, 0x6e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {0xd0, 0x0a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {0xd1, 0x0c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {0xd2, 0x84},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {0xd3, 0x90},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {0xd4, 0x1e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {0x5a, 0x24},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {0x5b, 0x1f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {0x5c, 0x88},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {0x5d, 0x60},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {0xac, 0x6e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {0xbe, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {0xbf, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {0x0f, 0x1d},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {0x0f, 0x1f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static const struct ov7740_framesize ov7740_framesizes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .width = VGA_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .height = VGA_HEIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .regs = ov7740_vga,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .reg_num = ARRAY_SIZE(ov7740_vga),
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static int ov7740_get_register(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct regmap *regmap = ov7740->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) unsigned int val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) ret = regmap_read(regmap, reg->reg & 0xff, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) reg->val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) reg->size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static int ov7740_set_register(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) const struct v4l2_dbg_register *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct regmap *regmap = ov7740->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) regmap_write(regmap, reg->reg & 0xff, reg->val & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static int ov7740_set_power(struct ov7740 *ov7740, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ret = clk_prepare_enable(ov7740->xvclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (ov7740->pwdn_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) gpiod_direction_output(ov7740->pwdn_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (ov7740->resetb_gpio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) gpiod_set_value(ov7740->resetb_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) usleep_range(500, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) gpiod_set_value(ov7740->resetb_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) usleep_range(3000, 5000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) clk_disable_unprepare(ov7740->xvclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (ov7740->pwdn_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) gpiod_direction_output(ov7740->pwdn_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static const struct v4l2_subdev_core_ops ov7740_subdev_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .log_status = v4l2_ctrl_subdev_log_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) #ifdef CONFIG_VIDEO_ADV_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .g_register = ov7740_get_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .s_register = ov7740_set_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .unsubscribe_event = v4l2_event_subdev_unsubscribe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static int ov7740_set_white_balance(struct ov7740 *ov7740, int awb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct regmap *regmap = ov7740->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) unsigned int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ret = regmap_read(regmap, REG_ISP_CTRL00, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (awb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) value |= (ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) value &= ~(ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) ret = regmap_write(regmap, REG_ISP_CTRL00, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (!awb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ret = regmap_write(regmap, REG_BGAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) ov7740->blue_balance->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) ret = regmap_write(regmap, REG_RGAIN, ov7740->red_balance->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static int ov7740_set_saturation(struct regmap *regmap, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) ret = regmap_write(regmap, REG_USAT, (unsigned char)value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return regmap_write(regmap, REG_VSAT, (unsigned char)value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static int ov7740_set_gain(struct regmap *regmap, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) ret = regmap_write(regmap, REG_GAIN, value & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) ret = regmap_update_bits(regmap, REG_CTRL15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) REG15_GAIN_MSB, (value >> 8) & 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) ret = regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static int ov7740_set_autogain(struct regmap *regmap, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ret = regmap_read(regmap, REG_REG13, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) reg |= REG13_AGC_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) reg &= ~REG13_AGC_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return regmap_write(regmap, REG_REG13, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static int ov7740_set_brightness(struct regmap *regmap, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /* Turn off AEC/AGC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) regmap_update_bits(regmap, REG_REG13, REG13_AEC_EN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (value >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) regmap_write(regmap, REG_YBRIGHT, (unsigned char)value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) } else{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) regmap_write(regmap, REG_YBRIGHT, (unsigned char)(-value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int ov7740_set_contrast(struct regmap *regmap, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return regmap_write(regmap, REG_YGAIN, (unsigned char)value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int ov7740_get_gain(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct regmap *regmap = ov7740->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) unsigned int value0, value1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (!ctrl->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) ret = regmap_read(regmap, REG_GAIN, &value0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ret = regmap_read(regmap, REG_CTRL15, &value1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ov7740->gain->val = (value1 << 8) | (value0 & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return 0;
^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 int ov7740_get_exp(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct regmap *regmap = ov7740->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) unsigned int value0, value1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (ctrl->val == V4L2_EXPOSURE_MANUAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ret = regmap_read(regmap, REG_AEC, &value0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) ret = regmap_read(regmap, REG_HAEC, &value1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ov7740->exposure->val = (value1 << 8) | (value0 & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) static int ov7740_set_exp(struct regmap *regmap, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* Turn off AEC/AGC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) ret = regmap_update_bits(regmap, REG_REG13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) REG13_AEC_EN | REG13_AGC_EN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) ret = regmap_write(regmap, REG_AEC, (unsigned char)value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return regmap_write(regmap, REG_HAEC, (unsigned char)(value >> 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static int ov7740_set_autoexp(struct regmap *regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) enum v4l2_exposure_auto_type value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ret = regmap_read(regmap, REG_REG13, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (value == V4L2_EXPOSURE_AUTO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) reg |= (REG13_AEC_EN | REG13_AGC_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) reg &= ~(REG13_AEC_EN | REG13_AGC_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) ret = regmap_write(regmap, REG_REG13, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) static int ov7740_get_volatile_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) struct ov7740 *ov7740 = container_of(ctrl->handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) struct ov7740, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) case V4L2_CID_AUTOGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) ret = ov7740_get_gain(ov7740, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) case V4L2_CID_EXPOSURE_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ret = ov7740_get_exp(ov7740, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct ov7740 *ov7740 = container_of(ctrl->handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) struct ov7740, ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct regmap *regmap = ov7740->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (!pm_runtime_get_if_in_use(&client->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) case V4L2_CID_AUTO_WHITE_BALANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) ret = ov7740_set_white_balance(ov7740, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) case V4L2_CID_SATURATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) ret = ov7740_set_saturation(regmap, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) ret = ov7740_set_brightness(regmap, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) case V4L2_CID_CONTRAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ret = ov7740_set_contrast(regmap, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) case V4L2_CID_VFLIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) val = ctrl->val ? REG0C_IMG_FLIP : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ret = regmap_update_bits(regmap, REG_REG0C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) REG0C_IMG_FLIP, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) case V4L2_CID_HFLIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) val = ctrl->val ? REG0C_IMG_MIRROR : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) ret = regmap_update_bits(regmap, REG_REG0C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) REG0C_IMG_MIRROR, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) case V4L2_CID_AUTOGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (!ctrl->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ret = ov7740_set_gain(regmap, ov7740->gain->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) ret = ov7740_set_autogain(regmap, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) case V4L2_CID_EXPOSURE_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (ctrl->val == V4L2_EXPOSURE_MANUAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) ret = ov7740_set_exp(regmap, ov7740->exposure->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) ret = ov7740_set_autoexp(regmap, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) break;
^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) pm_runtime_put(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static const struct v4l2_ctrl_ops ov7740_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .g_volatile_ctrl = ov7740_get_volatile_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) .s_ctrl = ov7740_set_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static int ov7740_start_streaming(struct ov7740 *ov7740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (ov7740->fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) ret = regmap_multi_reg_write(ov7740->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) ov7740->fmt->regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) ov7740->fmt->reg_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (ov7740->frmsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) ret = regmap_multi_reg_write(ov7740->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) ov7740->frmsize->regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) ov7740->frmsize->reg_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return __v4l2_ctrl_handler_setup(ov7740->subdev.ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static int ov7740_set_stream(struct v4l2_subdev *sd, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct i2c_client *client = v4l2_get_subdevdata(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) mutex_lock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (ov7740->streaming == enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) mutex_unlock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) ret = pm_runtime_get_sync(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) pm_runtime_put_noidle(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ret = ov7740_start_streaming(ov7740);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) goto err_rpm_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) pm_runtime_put(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) ov7740->streaming = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) mutex_unlock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) err_rpm_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) pm_runtime_put(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) mutex_unlock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) static int ov7740_g_frame_interval(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) struct v4l2_subdev_frame_interval *ival)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) struct v4l2_fract *tpf = &ival->interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) tpf->numerator = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) tpf->denominator = 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static int ov7740_s_frame_interval(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) struct v4l2_subdev_frame_interval *ival)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct v4l2_fract *tpf = &ival->interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) tpf->numerator = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) tpf->denominator = 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static const struct v4l2_subdev_video_ops ov7740_subdev_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) .s_stream = ov7740_set_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) .s_frame_interval = ov7740_s_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) .g_frame_interval = ov7740_g_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static const struct reg_sequence ov7740_format_yuyv[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {0x12, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {0x36, 0x3f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) {0x80, 0x7f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {0x83, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) static const struct reg_sequence ov7740_format_bggr8[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) {0x36, 0x2f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) {0x80, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) {0x83, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static const struct ov7740_pixfmt ov7740_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) .regs = ov7740_format_yuyv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .reg_num = ARRAY_SIZE(ov7740_format_yuyv),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) .colorspace = V4L2_COLORSPACE_SRGB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) .regs = ov7740_format_bggr8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) .reg_num = ARRAY_SIZE(ov7740_format_bggr8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) #define N_OV7740_FMTS ARRAY_SIZE(ov7740_formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) static int ov7740_enum_mbus_code(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) struct v4l2_subdev_mbus_code_enum *code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (code->pad || code->index >= N_OV7740_FMTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) code->code = ov7740_formats[code->index].mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) static int ov7740_enum_frame_interval(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct v4l2_subdev_frame_interval_enum *fie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (fie->pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (fie->index >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if ((fie->width != VGA_WIDTH) || (fie->height != VGA_HEIGHT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) fie->interval.numerator = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) fie->interval.denominator = 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static int ov7740_enum_frame_size(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) struct v4l2_subdev_frame_size_enum *fse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (fse->pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (fse->index > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) fse->min_width = fse->max_width = VGA_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) fse->min_height = fse->max_height = VGA_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) static int ov7740_try_fmt_internal(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) struct v4l2_mbus_framefmt *fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) const struct ov7740_pixfmt **ret_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) const struct ov7740_framesize **ret_frmsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) const struct ov7740_framesize *fsize = &ov7740_framesizes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) int index, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) for (index = 0; index < N_OV7740_FMTS; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (ov7740_formats[index].mbus_code == fmt->code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (index >= N_OV7740_FMTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /* default to first format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) fmt->code = ov7740_formats[0].mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (ret_fmt != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) *ret_fmt = ov7740_formats + index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) for (i = 0; i < ARRAY_SIZE(ov7740_framesizes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if ((fsize->width >= fmt->width) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) (fsize->height >= fmt->height)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) fmt->width = fsize->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) fmt->height = fsize->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) fsize++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (i >= ARRAY_SIZE(ov7740_framesizes)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) fsize = &ov7740_framesizes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) fmt->width = fsize->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) fmt->height = fsize->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (ret_frmsize != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) *ret_frmsize = fsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) fmt->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) fmt->colorspace = ov7740_formats[index].colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) ov7740->format = *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) static int ov7740_set_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) const struct ov7740_pixfmt *ovfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) const struct ov7740_framesize *fsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct v4l2_mbus_framefmt *mbus_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) mutex_lock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (format->pad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ret = ov7740_try_fmt_internal(sd, &format->format, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) *mbus_fmt = format->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) mutex_unlock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) ret = ov7740_try_fmt_internal(sd, &format->format, &ovfmt, &fsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) ov7740->fmt = ovfmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) ov7740->frmsize = fsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) mutex_unlock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) mutex_unlock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) static int ov7740_get_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) struct v4l2_subdev_format *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) struct v4l2_mbus_framefmt *mbus_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) mutex_lock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) format->format = *mbus_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) format->format = ov7740->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) mutex_unlock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) static const struct v4l2_subdev_pad_ops ov7740_subdev_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) .enum_frame_interval = ov7740_enum_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) .enum_frame_size = ov7740_enum_frame_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) .enum_mbus_code = ov7740_enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) .get_fmt = ov7740_get_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) .set_fmt = ov7740_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) static const struct v4l2_subdev_ops ov7740_subdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) .core = &ov7740_subdev_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) .video = &ov7740_subdev_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) .pad = &ov7740_subdev_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static void ov7740_get_default_format(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct v4l2_mbus_framefmt *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) format->width = ov7740->frmsize->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) format->height = ov7740->frmsize->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) format->colorspace = ov7740->fmt->colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) format->code = ov7740->fmt->mbus_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) format->field = V4L2_FIELD_NONE;
^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) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) struct v4l2_mbus_framefmt *format =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) v4l2_subdev_get_try_format(sd, fh->pad, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) mutex_lock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) ov7740_get_default_format(sd, format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) mutex_unlock(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return 0;
^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) static const struct v4l2_subdev_internal_ops ov7740_subdev_internal_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) .open = ov7740_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) static int ov7740_probe_dt(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct ov7740 *ov7740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) ov7740->resetb_gpio = devm_gpiod_get_optional(&client->dev, "reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (IS_ERR(ov7740->resetb_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) dev_info(&client->dev, "can't get %s GPIO\n", "reset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return PTR_ERR(ov7740->resetb_gpio);
^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) ov7740->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (IS_ERR(ov7740->pwdn_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) dev_info(&client->dev, "can't get %s GPIO\n", "powerdown");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return PTR_ERR(ov7740->pwdn_gpio);
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) static int ov7740_detect(struct ov7740 *ov7740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct regmap *regmap = ov7740->regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) unsigned int midh, midl, pidh, pidl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) ret = regmap_read(regmap, REG_MIDH, &midh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (midh != 0x7f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) ret = regmap_read(regmap, REG_MIDL, &midl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (midl != 0xa2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) ret = regmap_read(regmap, REG_PIDH, &pidh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (pidh != 0x77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) ret = regmap_read(regmap, REG_PIDL, &pidl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if ((pidl != 0x40) && (pidl != 0x41) && (pidl != 0x42))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) static int ov7740_init_controls(struct ov7740 *ov7740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) struct v4l2_ctrl_handler *ctrl_hdlr = &ov7740->ctrl_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) ctrl_hdlr->lock = &ov7740->mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) ov7740->auto_wb = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) V4L2_CID_AUTO_WHITE_BALANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) ov7740->blue_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) V4L2_CID_BLUE_BALANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) 0, 0xff, 1, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) ov7740->red_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) V4L2_CID_RED_BALANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) 0, 0xff, 1, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) ov7740->brightness = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) V4L2_CID_BRIGHTNESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) -255, 255, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) ov7740->contrast = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) V4L2_CID_CONTRAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 0, 127, 1, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) ov7740->saturation = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) V4L2_CID_SATURATION, 0, 256, 1, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) ov7740->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) V4L2_CID_HFLIP, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) ov7740->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) V4L2_CID_VFLIP, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) ov7740->gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) V4L2_CID_GAIN, 0, 1023, 1, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) ov7740->auto_gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) ov7740->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) V4L2_CID_EXPOSURE, 0, 65535, 1, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) ov7740->auto_exposure = v4l2_ctrl_new_std_menu(ctrl_hdlr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) &ov7740_ctrl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) V4L2_CID_EXPOSURE_AUTO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) V4L2_EXPOSURE_MANUAL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) V4L2_EXPOSURE_AUTO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) v4l2_ctrl_auto_cluster(3, &ov7740->auto_wb, 0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) V4L2_EXPOSURE_MANUAL, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (ctrl_hdlr->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) ret = ctrl_hdlr->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) dev_err(&client->dev, "controls initialisation failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) ret = v4l2_ctrl_handler_setup(ctrl_hdlr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) dev_err(&client->dev, "%s control init failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) ov7740->subdev.ctrl_handler = ctrl_hdlr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) v4l2_ctrl_handler_free(ctrl_hdlr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) mutex_destroy(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) static void ov7740_free_controls(struct ov7740 *ov7740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) mutex_destroy(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) #define OV7740_MAX_REGISTER 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) static const struct regmap_config ov7740_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) .max_register = OV7740_MAX_REGISTER,
^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 ov7740_probe(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct ov7740 *ov7740;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) ov7740 = devm_kzalloc(&client->dev, sizeof(*ov7740), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (!ov7740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) ov7740->xvclk = devm_clk_get(&client->dev, "xvclk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (IS_ERR(ov7740->xvclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) ret = PTR_ERR(ov7740->xvclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) "OV7740: fail to get xvclk: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) ret = ov7740_probe_dt(client, ov7740);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) ov7740->regmap = devm_regmap_init_sccb(client, &ov7740_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (IS_ERR(ov7740->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) ret = PTR_ERR(ov7740->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) dev_err(&client->dev, "Failed to allocate register map: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) sd = &ov7740->subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) v4l2_i2c_subdev_init(sd, client, &ov7740_subdev_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) sd->internal_ops = &ov7740_subdev_internal_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) #if defined(CONFIG_MEDIA_CONTROLLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) ov7740->pad.flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) ret = media_entity_pads_init(&sd->entity, 1, &ov7740->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) ret = ov7740_set_power(ov7740, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) pm_runtime_set_active(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) pm_runtime_enable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) ret = ov7740_detect(ov7740);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) goto error_detect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) mutex_init(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) ret = ov7740_init_controls(ov7740);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) goto error_init_controls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) v4l_info(client, "chip found @ 0x%02x (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) client->addr << 1, client->adapter->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) ov7740->fmt = &ov7740_formats[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) ov7740->frmsize = &ov7740_framesizes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) ov7740_get_default_format(sd, &ov7740->format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) ret = v4l2_async_register_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) goto error_async_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) pm_runtime_idle(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) error_async_register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) error_init_controls:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) ov7740_free_controls(ov7740);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) error_detect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) pm_runtime_disable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) pm_runtime_set_suspended(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) ov7740_set_power(ov7740, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) media_entity_cleanup(&ov7740->subdev.entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) static int ov7740_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) mutex_destroy(&ov7740->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) media_entity_cleanup(&ov7740->subdev.entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) v4l2_async_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) ov7740_free_controls(ov7740);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) pm_runtime_get_sync(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) pm_runtime_disable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) pm_runtime_set_suspended(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) pm_runtime_put_noidle(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) ov7740_set_power(ov7740, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) static int __maybe_unused ov7740_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ov7740_set_power(ov7740, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) static int __maybe_unused ov7740_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) return ov7740_set_power(ov7740, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) static const struct i2c_device_id ov7740_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) { "ov7740", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) MODULE_DEVICE_TABLE(i2c, ov7740_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) static const struct dev_pm_ops ov7740_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) SET_RUNTIME_PM_OPS(ov7740_runtime_suspend, ov7740_runtime_resume, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) static const struct of_device_id ov7740_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) {.compatible = "ovti,ov7740", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) { /* sentinel */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) MODULE_DEVICE_TABLE(of, ov7740_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) static struct i2c_driver ov7740_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) .name = "ov7740",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) .pm = &ov7740_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) .of_match_table = of_match_ptr(ov7740_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) .probe_new = ov7740_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) .remove = ov7740_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) .id_table = ov7740_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) module_i2c_driver(ov7740_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) MODULE_DESCRIPTION("The V4L2 driver for Omnivision 7740 sensor");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) MODULE_AUTHOR("Songjun Wu <songjun.wu@atmel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) MODULE_LICENSE("GPL v2");