^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Omnivision OV9650/OV9652 CMOS Image Sensor driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2013, Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Register definitions and initial settings based on a driver written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * by Vladimir Fonov.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (c) 2010, Vladimir Fonov
^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/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/gpio.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/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/media.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/ratelimit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <media/media-entity.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <media/v4l2-async.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <media/v4l2-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <media/v4l2-image-sizes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <media/v4l2-subdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <media/v4l2-mediabus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <media/i2c/ov9650.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) MODULE_PARM_DESC(debug, "Debug level (0-2)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define DRIVER_NAME "OV9650"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * OV9650/OV9652 register definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define REG_GAIN 0x00 /* Gain control, AGC[7:0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define REG_BLUE 0x01 /* AWB - Blue channel gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define REG_RED 0x02 /* AWB - Red channel gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define REG_VREF 0x03 /* [7:6] - AGC[9:8], [5:3]/[2:0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define VREF_GAIN_MASK 0xc0 /* - VREF end/start low 3 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define REG_COM1 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define COM1_CCIR656 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define REG_B_AVE 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define REG_GB_AVE 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define REG_GR_AVE 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define REG_R_AVE 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define REG_COM2 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define REG_PID 0x0a /* Product ID MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define REG_VER 0x0b /* Product ID LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define REG_COM3 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define COM3_SWAP 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define COM3_VARIOPIXEL1 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define REG_COM4 0x0d /* Vario Pixels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define COM4_VARIOPIXEL2 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define REG_COM5 0x0e /* System clock options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define COM5_SLAVE_MODE 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define COM5_SYSTEMCLOCK48MHZ 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define REG_COM6 0x0f /* HREF & ADBLC options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define REG_AECH 0x10 /* Exposure value, AEC[9:2] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define REG_CLKRC 0x11 /* Clock control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define CLK_EXT 0x40 /* Use external clock directly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define CLK_SCALE 0x3f /* Mask for internal clock scale */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define REG_COM7 0x12 /* SCCB reset, output format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define COM7_RESET 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define COM7_FMT_MASK 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define COM7_FMT_VGA 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define COM7_FMT_CIF 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define COM7_FMT_QVGA 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define COM7_FMT_QCIF 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define COM7_RGB 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define COM7_YUV 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define COM7_BAYER 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define COM7_PBAYER 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define REG_COM8 0x13 /* AGC/AEC options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define COM8_AECSTEP 0x40 /* Unlimited AEC step size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define COM8_BFILT 0x20 /* Band filter enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define COM8_AGC 0x04 /* Auto gain enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define COM8_AWB 0x02 /* White balance enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define COM8_AEC 0x01 /* Auto exposure enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define REG_COM9 0x14 /* Gain ceiling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define COM9_GAIN_CEIL_MASK 0x70 /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define REG_COM10 0x15 /* PCLK, HREF, HSYNC signals polarity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define COM10_HSYNC 0x40 /* HSYNC instead of HREF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define COM10_PCLK_HB 0x20 /* Suppress PCLK on horiz blank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define COM10_HREF_REV 0x08 /* Reverse HREF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define COM10_VS_NEG 0x02 /* VSYNC negative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define COM10_HS_NEG 0x01 /* HSYNC negative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define REG_HSTART 0x17 /* Horiz start high bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define REG_HSTOP 0x18 /* Horiz stop high bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define REG_VSTART 0x19 /* Vert start high bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define REG_VSTOP 0x1a /* Vert stop high bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define REG_PSHFT 0x1b /* Pixel delay after HREF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define REG_MIDH 0x1c /* Manufacturer ID MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define REG_MIDL 0x1d /* Manufufacturer ID LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define REG_MVFP 0x1e /* Image mirror/flip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define MVFP_MIRROR 0x20 /* Mirror image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define MVFP_FLIP 0x10 /* Vertical flip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define REG_BOS 0x20 /* B channel Offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define REG_GBOS 0x21 /* Gb channel Offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define REG_GROS 0x22 /* Gr channel Offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define REG_ROS 0x23 /* R channel Offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define REG_AEW 0x24 /* AGC upper limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define REG_AEB 0x25 /* AGC lower limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define REG_VPT 0x26 /* AGC/AEC fast mode op region */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define REG_BBIAS 0x27 /* B channel output bias */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define REG_GBBIAS 0x28 /* Gb channel output bias */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define REG_GRCOM 0x29 /* Analog BLC & regulator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define REG_EXHCH 0x2a /* Dummy pixel insert MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define REG_EXHCL 0x2b /* Dummy pixel insert LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define REG_RBIAS 0x2c /* R channel output bias */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define REG_ADVFL 0x2d /* LSB of dummy line insert */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define REG_ADVFH 0x2e /* MSB of dummy line insert */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define REG_YAVE 0x2f /* Y/G channel average value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define REG_HSYST 0x30 /* HSYNC rising edge delay LSB*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define REG_HSYEN 0x31 /* HSYNC falling edge delay LSB*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define REG_HREF 0x32 /* HREF pieces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define REG_CHLF 0x33 /* reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define REG_ADC 0x37 /* reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define REG_ACOM 0x38 /* reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define REG_OFON 0x39 /* Power down register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define OFON_PWRDN 0x08 /* Power down bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define REG_TSLB 0x3a /* YUVU format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define TSLB_YUYV_MASK 0x0c /* UYVY or VYUY - see com13 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define REG_COM11 0x3b /* Night mode, banding filter enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define COM11_NIGHT 0x80 /* Night mode enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define COM11_NMFR 0x60 /* Two bit NM frame rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define COM11_BANDING 0x01 /* Banding filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define COM11_AEC_REF_MASK 0x18 /* AEC reference area selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define REG_COM12 0x3c /* HREF option, UV average */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define COM12_HREF 0x80 /* HREF always */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define REG_COM13 0x3d /* Gamma selection, Color matrix en. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define COM13_GAMMA 0x80 /* Gamma enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define COM13_UVSAT 0x40 /* UV saturation auto adjustment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define COM13_UVSWAP 0x01 /* V before U - w/TSLB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define REG_COM14 0x3e /* Edge enhancement options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define COM14_EDGE_EN 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define COM14_EEF_X2 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define REG_EDGE 0x3f /* Edge enhancement factor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define EDGE_FACTOR_MASK 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define REG_COM15 0x40 /* Output range, RGB 555/565 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define COM15_R10F0 0x00 /* Data range 10 to F0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define COM15_R01FE 0x80 /* 01 to FE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define COM15_R00FF 0xc0 /* 00 to FF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define COM15_RGB565 0x10 /* RGB565 output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define COM15_RGB555 0x30 /* RGB555 output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define COM15_SWAPRB 0x04 /* Swap R&B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define REG_COM16 0x41 /* Color matrix coeff options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #define REG_COM17 0x42 /* Single frame out, banding filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* n = 1...9, 0x4f..0x57 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define REG_MTX(__n) (0x4f + (__n) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define REG_MTXS 0x58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Lens Correction Option 1...5, __n = 0...5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define REG_LCC(__n) (0x62 + (__n) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define LCC5_LCC_ENABLE 0x01 /* LCC5, enable lens correction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define LCC5_LCC_COLOR 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define REG_MANU 0x67 /* Manual U value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define REG_MANV 0x68 /* Manual V value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define REG_HV 0x69 /* Manual banding filter MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define REG_MBD 0x6a /* Manual banding filter value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define REG_DBLV 0x6b /* reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define REG_GSP 0x6c /* Gamma curve */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define GSP_LEN 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define REG_GST 0x7c /* Gamma curve */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define GST_LEN 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #define REG_COM21 0x8b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define REG_COM22 0x8c /* Edge enhancement, denoising */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define COM22_WHTPCOR 0x02 /* White pixel correction enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define COM22_WHTPCOROPT 0x01 /* White pixel correction option */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define COM22_DENOISE 0x10 /* White pixel correction option */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define REG_COM23 0x8d /* Color bar test, color gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define COM23_TEST_MODE 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define REG_DBLC1 0x8f /* Digital BLC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define REG_DBLC_B 0x90 /* Digital BLC B channel offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define REG_DBLC_R 0x91 /* Digital BLC R channel offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define REG_DM_LNL 0x92 /* Dummy line low 8 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define REG_DM_LNH 0x93 /* Dummy line high 8 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #define REG_LCCFB 0x9d /* Lens Correction B channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #define REG_LCCFR 0x9e /* Lens Correction R channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define REG_DBLC_GB 0x9f /* Digital BLC GB chan offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define REG_DBLC_GR 0xa0 /* Digital BLC GR chan offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #define REG_AECHM 0xa1 /* Exposure value - bits AEC[15:10] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #define REG_BD50ST 0xa2 /* Banding filter value for 50Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #define REG_BD60ST 0xa3 /* Banding filter value for 60Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #define REG_NULL 0xff /* Array end token */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) #define DEF_CLKRC 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) #define OV965X_ID(_msb, _lsb) ((_msb) << 8 | (_lsb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #define OV9650_ID 0x9650
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #define OV9652_ID 0x9652
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct ov965x_ctrls {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct v4l2_ctrl_handler handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct v4l2_ctrl *auto_exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct v4l2_ctrl *exposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct v4l2_ctrl *auto_wb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct v4l2_ctrl *blue_balance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct v4l2_ctrl *red_balance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct v4l2_ctrl *hflip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct v4l2_ctrl *vflip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct v4l2_ctrl *auto_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct v4l2_ctrl *gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct v4l2_ctrl *brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct v4l2_ctrl *saturation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct v4l2_ctrl *sharpness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct v4l2_ctrl *light_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) u8 update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct ov965x_framesize {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u16 width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) u16 height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) u16 max_exp_lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) const u8 *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct ov965x_interval {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct v4l2_fract interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* Maximum resolution for this interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct v4l2_frmsize_discrete size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) u8 clkrc_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) enum gpio_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) GPIO_PWDN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) GPIO_RST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) NUM_GPIOS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct ov965x {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct v4l2_subdev sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct media_pad pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) enum v4l2_mbus_type bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct gpio_desc *gpios[NUM_GPIOS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* External master clock frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) unsigned long mclk_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* Protects the struct fields below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /* Exposure row interval in us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) unsigned int exp_row_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) unsigned short id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) const struct ov965x_framesize *frame_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* YUYV sequence (pixel format) control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) u8 tslb_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct v4l2_mbus_framefmt format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct ov965x_ctrls ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* Pointer to frame rate control data structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) const struct ov965x_interval *fiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int streaming;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) int power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u8 apply_frame_fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct i2c_rv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) u8 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) u8 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static const struct i2c_rv ov965x_init_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) { REG_COM2, 0x10 }, /* Set soft sleep mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) { REG_COM5, 0x00 }, /* System clock options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) { REG_COM2, 0x01 }, /* Output drive, soft sleep mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) { REG_COM10, 0x00 }, /* Slave mode, HREF vs HSYNC, signals negate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) { REG_EDGE, 0xa6 }, /* Edge enhancement treshhold and factor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) { REG_COM16, 0x02 }, /* Color matrix coeff double option */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) { REG_COM17, 0x08 }, /* Single frame out, banding filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) { 0x16, 0x06 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) { REG_CHLF, 0xc0 }, /* Reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) { 0x34, 0xbf },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) { 0xa8, 0x80 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) { 0x96, 0x04 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) { 0x8e, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) { REG_COM12, 0x77 }, /* HREF option, UV average */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) { 0x8b, 0x06 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) { 0x35, 0x91 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) { 0x94, 0x88 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) { 0x95, 0x88 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) { REG_COM15, 0xc1 }, /* Output range, RGB 555/565 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) { REG_GRCOM, 0x2f }, /* Analog BLC & regulator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) { REG_COM6, 0x43 }, /* HREF & ADBLC options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) { REG_COM8, 0xe5 }, /* AGC/AEC options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) { REG_COM13, 0x90 }, /* Gamma selection, colour matrix, UV delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) { REG_HV, 0x80 }, /* Manual banding filter MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) { 0x5c, 0x96 }, /* Reserved up to 0xa5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) { 0x5d, 0x96 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) { 0x5e, 0x10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) { 0x59, 0xeb },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) { 0x5a, 0x9c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) { 0x5b, 0x55 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) { 0x43, 0xf0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) { 0x44, 0x10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) { 0x45, 0x55 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) { 0x46, 0x86 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) { 0x47, 0x64 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) { 0x48, 0x86 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) { 0x5f, 0xe0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) { 0x60, 0x8c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) { 0x61, 0x20 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) { 0xa5, 0xd9 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) { 0xa4, 0x74 }, /* reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) { REG_COM23, 0x02 }, /* Color gain analog/_digital_ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) { REG_COM8, 0xe7 }, /* Enable AEC, AWB, AEC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) { REG_COM22, 0x23 }, /* Edge enhancement, denoising */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) { 0xa9, 0xb8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) { 0xaa, 0x92 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) { 0xab, 0x0a },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) { REG_DBLC1, 0xdf }, /* Digital BLC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) { REG_DBLC_B, 0x00 }, /* Digital BLC B chan offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) { REG_DBLC_R, 0x00 }, /* Digital BLC R chan offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) { REG_DBLC_GB, 0x00 }, /* Digital BLC GB chan offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) { REG_DBLC_GR, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) { REG_COM9, 0x3a }, /* Gain ceiling 16x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) { REG_NULL, 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) #define NUM_FMT_REGS 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * COM7, COM3, COM4, HSTART, HSTOP, HREF, VSTART, VSTOP, VREF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * EXHCH, EXHCL, ADC, OCOM, OFON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static const u8 frame_size_reg_addr[NUM_FMT_REGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 0x12, 0x0c, 0x0d, 0x17, 0x18, 0x32, 0x19, 0x1a, 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 0x2a, 0x2b, 0x37, 0x38, 0x39,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static const u8 ov965x_sxga_regs[NUM_FMT_REGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 0x00, 0x00, 0x00, 0x1e, 0xbe, 0xbf, 0x01, 0x81, 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 0x10, 0x34, 0x81, 0x93, 0x51,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static const u8 ov965x_vga_regs[NUM_FMT_REGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 0x40, 0x04, 0x80, 0x26, 0xc6, 0xed, 0x01, 0x3d, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 0x10, 0x40, 0x91, 0x12, 0x43,
^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) /* Determined empirically. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static const u8 ov965x_qvga_regs[NUM_FMT_REGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 0x10, 0x04, 0x80, 0x25, 0xc5, 0xbf, 0x00, 0x80, 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 0x10, 0x40, 0x91, 0x12, 0x43,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static const struct ov965x_framesize ov965x_framesizes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) .width = SXGA_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .height = SXGA_HEIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .regs = ov965x_sxga_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) .max_exp_lines = 1048,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) .width = VGA_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) .height = VGA_HEIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .regs = ov965x_vga_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .max_exp_lines = 498,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .width = QVGA_WIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .height = QVGA_HEIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .regs = ov965x_qvga_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) .max_exp_lines = 248,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct ov965x_pixfmt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) u32 code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) u32 colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* REG_TSLB value, only bits [3:2] may be set. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) u8 tslb_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static const struct ov965x_pixfmt ov965x_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG, 0x0c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * This table specifies possible frame resolution and interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * combinations. Default CLKRC[5:0] divider values are valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * only for 24 MHz external clock frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static struct ov965x_interval ov965x_intervals[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {{ 100, 625 }, { SXGA_WIDTH, SXGA_HEIGHT }, 0 }, /* 6.25 fps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {{ 10, 125 }, { VGA_WIDTH, VGA_HEIGHT }, 1 }, /* 12.5 fps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {{ 10, 125 }, { QVGA_WIDTH, QVGA_HEIGHT }, 3 }, /* 12.5 fps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {{ 1, 25 }, { VGA_WIDTH, VGA_HEIGHT }, 0 }, /* 25 fps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {{ 1, 25 }, { QVGA_WIDTH, QVGA_HEIGHT }, 1 }, /* 25 fps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return &container_of(ctrl->handler, struct ov965x, ctrls.handler)->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static inline struct ov965x *to_ov965x(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return container_of(sd, struct ov965x, sd);
^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 ov965x_read(struct ov965x *ov965x, u8 addr, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) unsigned int buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) ret = regmap_read(ov965x->regmap, addr, &buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) *val = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) *val = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) v4l2_dbg(2, debug, &ov965x->sd, "%s: 0x%02x @ 0x%02x. (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) __func__, *val, addr, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static int ov965x_write(struct ov965x *ov965x, u8 addr, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ret = regmap_write(ov965x->regmap, addr, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) v4l2_dbg(2, debug, &ov965x->sd, "%s: 0x%02x @ 0x%02X (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) __func__, val, addr, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static int ov965x_write_array(struct ov965x *ov965x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) const struct i2c_rv *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ret = ov965x_write(ov965x, regs[i].addr, regs[i].value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static int ov965x_set_default_gamma_curve(struct ov965x *ov965x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static const u8 gamma_curve[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* Values taken from OV application note. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 0x40, 0x30, 0x4b, 0x60, 0x70, 0x70, 0x70, 0x70,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 0x60, 0x60, 0x50, 0x48, 0x3a, 0x2e, 0x28, 0x22,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 0x04, 0x07, 0x10, 0x28, 0x36, 0x44, 0x52, 0x60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 0x6c, 0x78, 0x8c, 0x9e, 0xbb, 0xd2, 0xe6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) u8 addr = REG_GSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) for (i = 0; i < ARRAY_SIZE(gamma_curve); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) int ret = ov965x_write(ov965x, addr, gamma_curve[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) addr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static int ov965x_set_color_matrix(struct ov965x *ov965x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static const u8 mtx[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* MTX1..MTX9, MTXS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 0x3a, 0x3d, 0x03, 0x12, 0x26, 0x38, 0x40, 0x40, 0x40, 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) u8 addr = REG_MTX(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) for (i = 0; i < ARRAY_SIZE(mtx); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) int ret = ov965x_write(ov965x, addr, mtx[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) addr++;
^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) return 0;
^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 __ov965x_set_power(struct ov965x *ov965x, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) int ret = clk_prepare_enable(ov965x->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) gpiod_set_value_cansleep(ov965x->gpios[GPIO_PWDN], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) gpiod_set_value_cansleep(ov965x->gpios[GPIO_RST], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) msleep(25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) gpiod_set_value_cansleep(ov965x->gpios[GPIO_RST], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) gpiod_set_value_cansleep(ov965x->gpios[GPIO_PWDN], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) clk_disable_unprepare(ov965x->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) ov965x->streaming = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static int ov965x_s_power(struct v4l2_subdev *sd, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct ov965x *ov965x = to_ov965x(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) v4l2_dbg(1, debug, sd, "%s: on: %d\n", __func__, on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) mutex_lock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (ov965x->power == !on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) ret = __ov965x_set_power(ov965x, on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (!ret && on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) ret = ov965x_write_array(ov965x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ov965x_init_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ov965x->apply_frame_fmt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) ov965x->ctrls.update = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) ov965x->power += on ? 1 : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) WARN_ON(ov965x->power < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * V4L2 controls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static void ov965x_update_exposure_ctrl(struct ov965x *ov965x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct v4l2_ctrl *ctrl = ov965x->ctrls.exposure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) unsigned long fint, trow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) int min, max, def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) u8 clkrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) mutex_lock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (WARN_ON(!ctrl || !ov965x->frame_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) clkrc = DEF_CLKRC + ov965x->fiv->clkrc_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /* Calculate internal clock frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) fint = ov965x->mclk_frequency * ((clkrc >> 7) + 1) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) ((2 * ((clkrc & 0x3f) + 1)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* and the row interval (in us). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) trow = (2 * 1520 * 1000000UL) / fint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) max = ov965x->frame_size->max_exp_lines * trow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) ov965x->exp_row_interval = trow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) v4l2_dbg(1, debug, &ov965x->sd, "clkrc: %#x, fi: %lu, tr: %lu, %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) clkrc, fint, trow, max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) /* Update exposure time range to match current frame format. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) min = (trow + 100) / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) max = (max - 100) / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) def = min + (max - min) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (v4l2_ctrl_modify_range(ctrl, min, max, 1, def))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) v4l2_err(&ov965x->sd, "Exposure ctrl range update failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) static int ov965x_set_banding_filter(struct ov965x *ov965x, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) unsigned long mbd, light_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) ret = ov965x_read(ov965x, REG_COM8, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (value == V4L2_CID_POWER_LINE_FREQUENCY_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) reg &= ~COM8_BFILT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) reg |= COM8_BFILT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) ret = ov965x_write(ov965x, REG_COM8, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (value == V4L2_CID_POWER_LINE_FREQUENCY_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (WARN_ON(!ov965x->fiv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* Set minimal exposure time for 50/60 HZ lighting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (value == V4L2_CID_POWER_LINE_FREQUENCY_50HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) light_freq = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) light_freq = 60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) mbd = (1000UL * ov965x->fiv->interval.denominator *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ov965x->frame_size->max_exp_lines) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) ov965x->fiv->interval.numerator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) mbd = ((mbd / (light_freq * 2)) + 500) / 1000UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return ov965x_write(ov965x, REG_MBD, mbd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static int ov965x_set_white_balance(struct ov965x *ov965x, int awb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) ret = ov965x_read(ov965x, REG_COM8, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) reg = awb ? reg | REG_COM8 : reg & ~REG_COM8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ret = ov965x_write(ov965x, REG_COM8, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (!ret && !awb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) ret = ov965x_write(ov965x, REG_BLUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ov965x->ctrls.blue_balance->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) ret = ov965x_write(ov965x, REG_RED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) ov965x->ctrls.red_balance->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) #define NUM_BR_LEVELS 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) #define NUM_BR_REGS 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static int ov965x_set_brightness(struct ov965x *ov965x, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) static const u8 regs[NUM_BR_LEVELS + 1][NUM_BR_REGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) { REG_AEW, REG_AEB, REG_VPT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) { 0x1c, 0x12, 0x50 }, /* -3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) { 0x3d, 0x30, 0x71 }, /* -2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) { 0x50, 0x44, 0x92 }, /* -1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) { 0x70, 0x64, 0xc3 }, /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) { 0x90, 0x84, 0xd4 }, /* +1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) { 0xc4, 0xbf, 0xf9 }, /* +2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) { 0xd8, 0xd0, 0xfa }, /* +3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) val += (NUM_BR_LEVELS / 2 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (val > NUM_BR_LEVELS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) for (i = 0; i < NUM_BR_REGS && !ret; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) ret = ov965x_write(ov965x, regs[0][i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) regs[val][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct ov965x_ctrls *ctrls = &ov965x->ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * For manual mode we need to disable AGC first, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * gain value in REG_VREF, REG_GAIN is not overwritten.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (ctrls->auto_gain->is_new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ret = ov965x_read(ov965x, REG_COM8, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (ctrls->auto_gain->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) reg |= COM8_AGC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) reg &= ~COM8_AGC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) ret = ov965x_write(ov965x, REG_COM8, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return ret;
^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) if (ctrls->gain->is_new && !auto_gain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) unsigned int gain = ctrls->gain->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) unsigned int rgain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) int m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * Convert gain control value to the sensor's gain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * registers (VREF[7:6], GAIN[7:0]) format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) for (m = 6; m >= 0; m--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (gain >= (1 << m) * 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) /* Sanity check: don't adjust the gain with a negative value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (m < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) rgain = (gain - ((1 << m) * 16)) / (1 << m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) rgain |= (((1 << m) - 1) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ret = ov965x_write(ov965x, REG_GAIN, rgain & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) ret = ov965x_read(ov965x, REG_VREF, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) reg &= ~VREF_GAIN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) reg |= (((rgain >> 8) & 0x3) << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) ret = ov965x_write(ov965x, REG_VREF, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /* Return updated control's value to userspace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) ctrls->gain->val = (1 << m) * (16 + (rgain & 0xf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) static int ov965x_set_sharpness(struct ov965x *ov965x, unsigned int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) u8 com14, edge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) ret = ov965x_read(ov965x, REG_COM14, &com14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) ret = ov965x_read(ov965x, REG_EDGE, &edge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) com14 = value ? com14 | COM14_EDGE_EN : com14 & ~COM14_EDGE_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) value--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (value > 0x0f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) com14 |= COM14_EEF_X2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) value >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) com14 &= ~COM14_EEF_X2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) ret = ov965x_write(ov965x, REG_COM14, com14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) edge &= ~EDGE_FACTOR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) edge |= ((u8)value & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) return ov965x_write(ov965x, REG_EDGE, edge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static int ov965x_set_exposure(struct ov965x *ov965x, int exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct ov965x_ctrls *ctrls = &ov965x->ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) bool auto_exposure = (exp == V4L2_EXPOSURE_AUTO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (ctrls->auto_exp->is_new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) ret = ov965x_read(ov965x, REG_COM8, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (auto_exposure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) reg |= (COM8_AEC | COM8_AGC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) reg &= ~(COM8_AEC | COM8_AGC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) ret = ov965x_write(ov965x, REG_COM8, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (!auto_exposure && ctrls->exposure->is_new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) unsigned int exposure = (ctrls->exposure->val * 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) / ov965x->exp_row_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * Manual exposure value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) * [b15:b0] - AECHM (b15:b10), AECH (b9:b2), COM1 (b1:b0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) ret = ov965x_write(ov965x, REG_COM1, exposure & 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) ret = ov965x_write(ov965x, REG_AECH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) (exposure >> 2) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) ret = ov965x_write(ov965x, REG_AECHM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) (exposure >> 10) & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /* Update the value to minimize rounding errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) ctrls->exposure->val = ((exposure * ov965x->exp_row_interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) + 50) / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) v4l2_ctrl_activate(ov965x->ctrls.brightness, !exp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) static int ov965x_set_flip(struct ov965x *ov965x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) u8 mvfp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (ov965x->ctrls.hflip->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) mvfp |= MVFP_MIRROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (ov965x->ctrls.vflip->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) mvfp |= MVFP_FLIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return ov965x_write(ov965x, REG_MVFP, mvfp);
^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) #define NUM_SAT_LEVELS 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) #define NUM_SAT_REGS 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) static int ov965x_set_saturation(struct ov965x *ov965x, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) static const u8 regs[NUM_SAT_LEVELS][NUM_SAT_REGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) /* MTX(1)...MTX(6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) { 0x1d, 0x1f, 0x02, 0x09, 0x13, 0x1c }, /* -2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) { 0x2e, 0x31, 0x02, 0x0e, 0x1e, 0x2d }, /* -1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) { 0x3a, 0x3d, 0x03, 0x12, 0x26, 0x38 }, /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) { 0x46, 0x49, 0x04, 0x16, 0x2e, 0x43 }, /* +1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) { 0x57, 0x5c, 0x05, 0x1b, 0x39, 0x54 }, /* +2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) u8 addr = REG_MTX(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) val += (NUM_SAT_LEVELS / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (val >= NUM_SAT_LEVELS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) for (i = 0; i < NUM_SAT_REGS && !ret; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) ret = ov965x_write(ov965x, addr + i, regs[val][i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) static int ov965x_set_test_pattern(struct ov965x *ov965x, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) ret = ov965x_read(ov965x, REG_COM23, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) reg = value ? reg | COM23_TEST_MODE : reg & ~COM23_TEST_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return ov965x_write(ov965x, REG_COM23, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) unsigned int exposure, gain, m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) u8 reg0, reg1, reg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (!ov965x->power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) case V4L2_CID_AUTOGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (!ctrl->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) ret = ov965x_read(ov965x, REG_GAIN, ®0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) ret = ov965x_read(ov965x, REG_VREF, ®1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) gain = ((reg1 >> 6) << 8) | reg0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) m = 0x01 << fls(gain >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) ov965x->ctrls.gain->val = m * (16 + (gain & 0xf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) case V4L2_CID_EXPOSURE_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (ctrl->val == V4L2_EXPOSURE_MANUAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) ret = ov965x_read(ov965x, REG_COM1, ®0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) ret = ov965x_read(ov965x, REG_AECH, ®1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) ret = ov965x_read(ov965x, REG_AECHM, ®2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) exposure = ((reg2 & 0x3f) << 10) | (reg1 << 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) (reg0 & 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) ov965x->ctrls.exposure->val = ((exposure *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) ov965x->exp_row_interval) + 50) / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) static int ov965x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct ov965x *ov965x = to_ov965x(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) v4l2_dbg(1, debug, sd, "g_ctrl: %s\n", ctrl->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) mutex_lock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) ret = __g_volatile_ctrl(ov965x, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return ret;
^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 int ov965x_s_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct ov965x *ov965x = to_ov965x(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) v4l2_dbg(1, debug, sd, "s_ctrl: %s, value: %d. power: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) ctrl->name, ctrl->val, ov965x->power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) mutex_lock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * If the device is not powered up now postpone applying control's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * value to the hardware, until it is ready to accept commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (ov965x->power == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) switch (ctrl->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) case V4L2_CID_AUTO_WHITE_BALANCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) ret = ov965x_set_white_balance(ov965x, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case V4L2_CID_BRIGHTNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) ret = ov965x_set_brightness(ov965x, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) case V4L2_CID_EXPOSURE_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) ret = ov965x_set_exposure(ov965x, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) case V4L2_CID_AUTOGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) ret = ov965x_set_gain(ov965x, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) case V4L2_CID_HFLIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) ret = ov965x_set_flip(ov965x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) case V4L2_CID_POWER_LINE_FREQUENCY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) ret = ov965x_set_banding_filter(ov965x, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) case V4L2_CID_SATURATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) ret = ov965x_set_saturation(ov965x, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) case V4L2_CID_SHARPNESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) ret = ov965x_set_sharpness(ov965x, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) case V4L2_CID_TEST_PATTERN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) ret = ov965x_set_test_pattern(ov965x, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) static const struct v4l2_ctrl_ops ov965x_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) .g_volatile_ctrl = ov965x_g_volatile_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) .s_ctrl = ov965x_s_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) static const char * const test_pattern_menu[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) "Disabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) "Color bars",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) static int ov965x_initialize_controls(struct ov965x *ov965x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) const struct v4l2_ctrl_ops *ops = &ov965x_ctrl_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) struct ov965x_ctrls *ctrls = &ov965x->ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) struct v4l2_ctrl_handler *hdl = &ctrls->handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) ret = v4l2_ctrl_handler_init(hdl, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) /* Auto/manual white balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) V4L2_CID_AUTO_WHITE_BALANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) ctrls->blue_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BLUE_BALANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 0, 0xff, 1, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) ctrls->red_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_RED_BALANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 0, 0xff, 1, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /* Auto/manual exposure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) ctrls->auto_exp =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) v4l2_ctrl_new_std_menu(hdl, ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) V4L2_CID_EXPOSURE_AUTO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) V4L2_EXPOSURE_MANUAL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) V4L2_EXPOSURE_AUTO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) /* Exposure time, in 100 us units. min/max is updated dynamically. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) ctrls->exposure = v4l2_ctrl_new_std(hdl, ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) V4L2_CID_EXPOSURE_ABSOLUTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 2, 1500, 1, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) /* Auto/manual gain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 0, 1, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 16, 64 * (16 + 15), 1, 64 * 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) ctrls->saturation = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) -2, 2, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) ctrls->brightness = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) -3, 3, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) ctrls->sharpness = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 0, 32, 1, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) ctrls->light_freq =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) v4l2_ctrl_new_std_menu(hdl, ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) V4L2_CID_POWER_LINE_FREQUENCY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) V4L2_CID_POWER_LINE_FREQUENCY_60HZ, ~0x7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) ARRAY_SIZE(test_pattern_menu) - 1, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) test_pattern_menu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (hdl->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) ret = hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) v4l2_ctrl_handler_free(hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) v4l2_ctrl_cluster(2, &ctrls->hflip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) ov965x->sd.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * V4L2 subdev video and pad level operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) static void ov965x_get_default_format(struct v4l2_mbus_framefmt *mf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) mf->width = ov965x_framesizes[0].width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) mf->height = ov965x_framesizes[0].height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) mf->colorspace = ov965x_formats[0].colorspace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) mf->code = ov965x_formats[0].code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) mf->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) static int ov965x_enum_mbus_code(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) struct v4l2_subdev_mbus_code_enum *code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (code->index >= ARRAY_SIZE(ov965x_formats))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) code->code = ov965x_formats[code->index].code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return 0;
^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) static int ov965x_enum_frame_sizes(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) struct v4l2_subdev_frame_size_enum *fse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) int i = ARRAY_SIZE(ov965x_formats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (fse->index >= ARRAY_SIZE(ov965x_framesizes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) while (--i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (fse->code == ov965x_formats[i].code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) fse->code = ov965x_formats[i].code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) fse->min_width = ov965x_framesizes[fse->index].width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) fse->max_width = fse->min_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) fse->max_height = ov965x_framesizes[fse->index].height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) fse->min_height = fse->max_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) static int ov965x_g_frame_interval(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) struct v4l2_subdev_frame_interval *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) struct ov965x *ov965x = to_ov965x(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) mutex_lock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) fi->interval = ov965x->fiv->interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) static int __ov965x_set_frame_interval(struct ov965x *ov965x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) struct v4l2_subdev_frame_interval *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) struct v4l2_mbus_framefmt *mbus_fmt = &ov965x->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) const struct ov965x_interval *fiv = &ov965x_intervals[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) u64 req_int, err, min_err = ~0ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (fi->interval.denominator == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) req_int = (u64)fi->interval.numerator * 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) do_div(req_int, fi->interval.denominator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) for (i = 0; i < ARRAY_SIZE(ov965x_intervals); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) const struct ov965x_interval *iv = &ov965x_intervals[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (mbus_fmt->width != iv->size.width ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) mbus_fmt->height != iv->size.height)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) err = abs((u64)(iv->interval.numerator * 10000) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) iv->interval.denominator - req_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (err < min_err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) fiv = iv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) min_err = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) ov965x->fiv = fiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) v4l2_dbg(1, debug, &ov965x->sd, "Changed frame interval to %u us\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) fiv->interval.numerator * 1000000 / fiv->interval.denominator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) static int ov965x_s_frame_interval(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) struct v4l2_subdev_frame_interval *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) struct ov965x *ov965x = to_ov965x(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) v4l2_dbg(1, debug, sd, "Setting %d/%d frame interval\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) fi->interval.numerator, fi->interval.denominator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) mutex_lock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) ret = __ov965x_set_frame_interval(ov965x, fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) ov965x->apply_frame_fmt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) static int ov965x_get_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) struct v4l2_subdev_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) struct ov965x *ov965x = to_ov965x(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) struct v4l2_mbus_framefmt *mf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) mf = v4l2_subdev_get_try_format(sd, cfg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) fmt->format = *mf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) mutex_lock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) fmt->format = ov965x->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static void __ov965x_try_frame_size(struct v4l2_mbus_framefmt *mf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) const struct ov965x_framesize **size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) const struct ov965x_framesize *fsize = &ov965x_framesizes[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) *match = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) int i = ARRAY_SIZE(ov965x_framesizes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) unsigned int min_err = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) while (i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) int err = abs(fsize->width - mf->width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) + abs(fsize->height - mf->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (err < min_err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) min_err = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) match = fsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) fsize++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (!match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) match = &ov965x_framesizes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) mf->width = match->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) mf->height = match->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) if (size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) *size = match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) static int ov965x_set_fmt(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) struct v4l2_subdev_format *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) unsigned int index = ARRAY_SIZE(ov965x_formats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) struct v4l2_mbus_framefmt *mf = &fmt->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) struct ov965x *ov965x = to_ov965x(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) const struct ov965x_framesize *size = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) __ov965x_try_frame_size(mf, &size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) while (--index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) if (ov965x_formats[index].code == mf->code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) mf->colorspace = V4L2_COLORSPACE_JPEG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) mf->code = ov965x_formats[index].code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) mf->field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) mutex_lock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) if (cfg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) *mf = fmt->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (ov965x->streaming) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) ov965x->frame_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) ov965x->format = fmt->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) ov965x->tslb_reg = ov965x_formats[index].tslb_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) ov965x->apply_frame_fmt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) if (!ret && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) struct v4l2_subdev_frame_interval fiv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) .interval = { 0, 1 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /* Reset to minimum possible frame interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) __ov965x_set_frame_interval(ov965x, &fiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) ov965x_update_exposure_ctrl(ov965x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) static int ov965x_set_frame_size(struct ov965x *ov965x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) for (i = 0; ret == 0 && i < NUM_FMT_REGS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) ret = ov965x_write(ov965x, frame_size_reg_addr[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) ov965x->frame_size->regs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) static int __ov965x_set_params(struct ov965x *ov965x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) struct ov965x_ctrls *ctrls = &ov965x->ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (ov965x->apply_frame_fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) reg = DEF_CLKRC + ov965x->fiv->clkrc_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) ret = ov965x_write(ov965x, REG_CLKRC, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) ret = ov965x_set_frame_size(ov965x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) ret = ov965x_read(ov965x, REG_TSLB, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) reg &= ~TSLB_YUYV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) reg |= ov965x->tslb_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) ret = ov965x_write(ov965x, REG_TSLB, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) ret = ov965x_set_default_gamma_curve(ov965x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) ret = ov965x_set_color_matrix(ov965x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) * Select manual banding filter, the filter will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) * be enabled further if required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) ret = ov965x_read(ov965x, REG_COM11, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) reg |= COM11_BANDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) ret = ov965x_write(ov965x, REG_COM11, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) * Banding filter (REG_MBD value) needs to match selected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) * resolution and frame rate, so it's always updated here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) return ov965x_set_banding_filter(ov965x, ctrls->light_freq->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) static int ov965x_s_stream(struct v4l2_subdev *sd, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) struct ov965x *ov965x = to_ov965x(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) struct ov965x_ctrls *ctrls = &ov965x->ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) v4l2_dbg(1, debug, sd, "%s: on: %d\n", __func__, on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) mutex_lock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) if (ov965x->streaming == !on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) if (on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) ret = __ov965x_set_params(ov965x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (!ret && ctrls->update) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * ov965x_s_ctrl callback takes the mutex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) * so it needs to be released here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) ret = v4l2_ctrl_handler_setup(&ctrls->handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) mutex_lock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) ctrls->update = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) ret = ov965x_write(ov965x, REG_COM2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) on ? 0x01 : 0x11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) ov965x->streaming += on ? 1 : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) WARN_ON(ov965x->streaming < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) * V4L2 subdev internal operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) static int ov965x_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) struct v4l2_mbus_framefmt *mf =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) v4l2_subdev_get_try_format(sd, fh->pad, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) ov965x_get_default_format(mf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) static const struct v4l2_subdev_pad_ops ov965x_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) .enum_mbus_code = ov965x_enum_mbus_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) .enum_frame_size = ov965x_enum_frame_sizes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) .get_fmt = ov965x_get_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) .set_fmt = ov965x_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) static const struct v4l2_subdev_video_ops ov965x_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) .s_stream = ov965x_s_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) .g_frame_interval = ov965x_g_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) .s_frame_interval = ov965x_s_frame_interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) static const struct v4l2_subdev_internal_ops ov965x_sd_internal_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) .open = ov965x_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) static const struct v4l2_subdev_core_ops ov965x_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) .s_power = ov965x_s_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) .log_status = v4l2_ctrl_subdev_log_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) .unsubscribe_event = v4l2_event_subdev_unsubscribe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) static const struct v4l2_subdev_ops ov965x_subdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) .core = &ov965x_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) .pad = &ov965x_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) .video = &ov965x_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) * Reset and power down GPIOs configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) static int ov965x_configure_gpios_pdata(struct ov965x *ov965x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) const struct ov9650_platform_data *pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) int gpios[NUM_GPIOS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) struct device *dev = regmap_get_device(ov965x->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) gpios[GPIO_PWDN] = pdata->gpio_pwdn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) gpios[GPIO_RST] = pdata->gpio_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) for (i = 0; i < ARRAY_SIZE(ov965x->gpios); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) int gpio = gpios[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) if (!gpio_is_valid(gpio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) ret = devm_gpio_request_one(dev, gpio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) GPIOF_OUT_INIT_HIGH, "OV965X");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) v4l2_dbg(1, debug, &ov965x->sd, "set gpio %d to 1\n", gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) gpio_set_value_cansleep(gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) gpio_export(gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) ov965x->gpios[i] = gpio_to_desc(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) static int ov965x_configure_gpios(struct ov965x *ov965x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) struct device *dev = regmap_get_device(ov965x->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) ov965x->gpios[GPIO_PWDN] = devm_gpiod_get_optional(dev, "powerdown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (IS_ERR(ov965x->gpios[GPIO_PWDN])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) dev_info(dev, "can't get %s GPIO\n", "powerdown");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) return PTR_ERR(ov965x->gpios[GPIO_PWDN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) ov965x->gpios[GPIO_RST] = devm_gpiod_get_optional(dev, "reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) if (IS_ERR(ov965x->gpios[GPIO_RST])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) dev_info(dev, "can't get %s GPIO\n", "reset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) return PTR_ERR(ov965x->gpios[GPIO_RST]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) static int ov965x_detect_sensor(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) struct ov965x *ov965x = to_ov965x(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) u8 pid, ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) mutex_lock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) ret = __ov965x_set_power(ov965x, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) msleep(25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) /* Check sensor revision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) ret = ov965x_read(ov965x, REG_PID, &pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) ret = ov965x_read(ov965x, REG_VER, &ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) __ov965x_set_power(ov965x, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) ov965x->id = OV965X_ID(pid, ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) if (ov965x->id == OV9650_ID || ov965x->id == OV9652_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) v4l2_info(sd, "Found OV%04X sensor\n", ov965x->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) v4l2_err(sd, "Sensor detection failed (%04X, %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) ov965x->id, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) mutex_unlock(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) static int ov965x_probe(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) const struct ov9650_platform_data *pdata = client->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) struct ov965x *ov965x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) static const struct regmap_config ov965x_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) .max_register = 0xab,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) ov965x = devm_kzalloc(&client->dev, sizeof(*ov965x), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) if (!ov965x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) ov965x->regmap = devm_regmap_init_sccb(client, &ov965x_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) if (IS_ERR(ov965x->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) dev_err(&client->dev, "Failed to allocate register map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) return PTR_ERR(ov965x->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) if (pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) if (pdata->mclk_frequency == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) dev_err(&client->dev, "MCLK frequency not specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) ov965x->mclk_frequency = pdata->mclk_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) ret = ov965x_configure_gpios_pdata(ov965x, pdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) } else if (dev_fwnode(&client->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) ov965x->clk = devm_clk_get(&client->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) if (IS_ERR(ov965x->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) return PTR_ERR(ov965x->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) ov965x->mclk_frequency = clk_get_rate(ov965x->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) ret = ov965x_configure_gpios(ov965x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) "Neither platform data nor device property specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) mutex_init(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) sd = &ov965x->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) v4l2_i2c_subdev_init(sd, client, &ov965x_subdev_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) strscpy(sd->name, DRIVER_NAME, sizeof(sd->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) sd->internal_ops = &ov965x_sd_internal_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) V4L2_SUBDEV_FL_HAS_EVENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) ov965x->pad.flags = MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) ret = media_entity_pads_init(&sd->entity, 1, &ov965x->pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) goto err_mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) ret = ov965x_initialize_controls(ov965x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) goto err_me;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) ov965x_get_default_format(&ov965x->format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) ov965x->frame_size = &ov965x_framesizes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) ov965x->fiv = &ov965x_intervals[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) ret = ov965x_detect_sensor(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) goto err_ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) /* Update exposure time min/max to match frame format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) ov965x_update_exposure_ctrl(ov965x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) ret = v4l2_async_register_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) goto err_ctrls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) err_ctrls:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) v4l2_ctrl_handler_free(sd->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) err_me:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) media_entity_cleanup(&sd->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) err_mutex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) mutex_destroy(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) static int ov965x_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) struct v4l2_subdev *sd = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) struct ov965x *ov965x = to_ov965x(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) v4l2_async_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) v4l2_ctrl_handler_free(sd->ctrl_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) media_entity_cleanup(&sd->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) mutex_destroy(&ov965x->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) static const struct i2c_device_id ov965x_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) { "OV9650", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) { "OV9652", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) MODULE_DEVICE_TABLE(i2c, ov965x_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) #if IS_ENABLED(CONFIG_OF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) static const struct of_device_id ov965x_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) { .compatible = "ovti,ov9650", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) { .compatible = "ovti,ov9652", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) MODULE_DEVICE_TABLE(of, ov965x_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) static struct i2c_driver ov965x_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) .of_match_table = of_match_ptr(ov965x_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) .probe_new = ov965x_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) .remove = ov965x_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) .id_table = ov965x_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) module_i2c_driver(ov965x_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) MODULE_AUTHOR("Sylwester Nawrocki <sylvester.nawrocki@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) MODULE_DESCRIPTION("OV9650/OV9652 CMOS Image Sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) MODULE_LICENSE("GPL");