3178 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright 2020 Kévin L'hôpital <kevin.lhopital@bootlin.com>4 * Copyright 2020 Bootlin5 * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com>6 */7 8#include <linux/clk.h>9#include <linux/delay.h>10#include <linux/device.h>11#include <linux/i2c.h>12#include <linux/mod_devicetable.h>13#include <linux/module.h>14#include <linux/of_graph.h>15#include <linux/pm_runtime.h>16#include <linux/regulator/consumer.h>17#include <linux/videodev2.h>18#include <media/v4l2-ctrls.h>19#include <media/v4l2-device.h>20#include <media/v4l2-fwnode.h>21#include <media/v4l2-image-sizes.h>22#include <media/v4l2-mediabus.h>23 24/* Register definitions */25 26/* System */27 28#define OV8865_SW_STANDBY_REG 0x10029#define OV8865_SW_STANDBY_STREAM_ON BIT(0)30 31#define OV8865_SW_RESET_REG 0x10332#define OV8865_SW_RESET_RESET BIT(0)33 34#define OV8865_PLL_CTRL0_REG 0x30035#define OV8865_PLL_CTRL0_PRE_DIV(v) ((v) & GENMASK(2, 0))36#define OV8865_PLL_CTRL1_REG 0x30137#define OV8865_PLL_CTRL1_MUL_H(v) (((v) & GENMASK(9, 8)) >> 8)38#define OV8865_PLL_CTRL2_REG 0x30239#define OV8865_PLL_CTRL2_MUL_L(v) ((v) & GENMASK(7, 0))40#define OV8865_PLL_CTRL3_REG 0x30341#define OV8865_PLL_CTRL3_M_DIV(v) (((v) - 1) & GENMASK(3, 0))42#define OV8865_PLL_CTRL4_REG 0x30443#define OV8865_PLL_CTRL4_MIPI_DIV(v) ((v) & GENMASK(1, 0))44#define OV8865_PLL_CTRL5_REG 0x30545#define OV8865_PLL_CTRL5_SYS_PRE_DIV(v) ((v) & GENMASK(1, 0))46#define OV8865_PLL_CTRL6_REG 0x30647#define OV8865_PLL_CTRL6_SYS_DIV(v) (((v) - 1) & BIT(0))48 49#define OV8865_PLL_CTRL8_REG 0x30850#define OV8865_PLL_CTRL9_REG 0x30951#define OV8865_PLL_CTRLA_REG 0x30a52#define OV8865_PLL_CTRLA_PRE_DIV_HALF(v) (((v) - 1) & BIT(0))53#define OV8865_PLL_CTRLB_REG 0x30b54#define OV8865_PLL_CTRLB_PRE_DIV(v) ((v) & GENMASK(2, 0))55#define OV8865_PLL_CTRLC_REG 0x30c56#define OV8865_PLL_CTRLC_MUL_H(v) (((v) & GENMASK(9, 8)) >> 8)57#define OV8865_PLL_CTRLD_REG 0x30d58#define OV8865_PLL_CTRLD_MUL_L(v) ((v) & GENMASK(7, 0))59#define OV8865_PLL_CTRLE_REG 0x30e60#define OV8865_PLL_CTRLE_SYS_DIV(v) ((v) & GENMASK(2, 0))61#define OV8865_PLL_CTRLF_REG 0x30f62#define OV8865_PLL_CTRLF_SYS_PRE_DIV(v) (((v) - 1) & GENMASK(3, 0))63#define OV8865_PLL_CTRL10_REG 0x31064#define OV8865_PLL_CTRL11_REG 0x31165#define OV8865_PLL_CTRL12_REG 0x31266#define OV8865_PLL_CTRL12_PRE_DIV_HALF(v) ((((v) - 1) << 4) & BIT(4))67#define OV8865_PLL_CTRL12_DAC_DIV(v) (((v) - 1) & GENMASK(3, 0))68 69#define OV8865_PLL_CTRL1B_REG 0x31b70#define OV8865_PLL_CTRL1C_REG 0x31c71 72#define OV8865_PLL_CTRL1E_REG 0x31e73#define OV8865_PLL_CTRL1E_PLL1_NO_LAT BIT(3)74 75#define OV8865_PAD_OEN0_REG 0x300076 77#define OV8865_PAD_OEN2_REG 0x300278 79#define OV8865_CLK_RST5_REG 0x300580 81#define OV8865_CHIP_ID_HH_REG 0x300a82#define OV8865_CHIP_ID_HH_VALUE 0x0083#define OV8865_CHIP_ID_H_REG 0x300b84#define OV8865_CHIP_ID_H_VALUE 0x8885#define OV8865_CHIP_ID_L_REG 0x300c86#define OV8865_CHIP_ID_L_VALUE 0x6587#define OV8865_PAD_OUT2_REG 0x300d88 89#define OV8865_PAD_SEL2_REG 0x301090#define OV8865_PAD_PK_REG 0x301191#define OV8865_PAD_PK_DRIVE_STRENGTH_1X (0 << 5)92#define OV8865_PAD_PK_DRIVE_STRENGTH_2X (1 << 5)93#define OV8865_PAD_PK_DRIVE_STRENGTH_3X (2 << 5)94#define OV8865_PAD_PK_DRIVE_STRENGTH_4X (3 << 5)95 96#define OV8865_PUMP_CLK_DIV_REG 0x301597#define OV8865_PUMP_CLK_DIV_PUMP_N(v) (((v) << 4) & GENMASK(6, 4))98#define OV8865_PUMP_CLK_DIV_PUMP_P(v) ((v) & GENMASK(2, 0))99 100#define OV8865_MIPI_SC_CTRL0_REG 0x3018101#define OV8865_MIPI_SC_CTRL0_LANES(v) ((((v) - 1) << 5) & \102 GENMASK(7, 5))103#define OV8865_MIPI_SC_CTRL0_MIPI_EN BIT(4)104#define OV8865_MIPI_SC_CTRL0_UNKNOWN BIT(1)105#define OV8865_MIPI_SC_CTRL0_LANES_PD_MIPI BIT(0)106#define OV8865_MIPI_SC_CTRL1_REG 0x3019107#define OV8865_CLK_RST0_REG 0x301a108#define OV8865_CLK_RST1_REG 0x301b109#define OV8865_CLK_RST2_REG 0x301c110#define OV8865_CLK_RST3_REG 0x301d111#define OV8865_CLK_RST4_REG 0x301e112 113#define OV8865_PCLK_SEL_REG 0x3020114#define OV8865_PCLK_SEL_PCLK_DIV_MASK BIT(3)115#define OV8865_PCLK_SEL_PCLK_DIV(v) ((((v) - 1) << 3) & BIT(3))116 117#define OV8865_MISC_CTRL_REG 0x3021118#define OV8865_MIPI_SC_CTRL2_REG 0x3022119#define OV8865_MIPI_SC_CTRL2_CLK_LANES_PD_MIPI BIT(1)120#define OV8865_MIPI_SC_CTRL2_PD_MIPI_RST_SYNC BIT(0)121 122#define OV8865_MIPI_BIT_SEL_REG 0x3031123#define OV8865_MIPI_BIT_SEL(v) (((v) << 0) & GENMASK(4, 0))124#define OV8865_CLK_SEL0_REG 0x3032125#define OV8865_CLK_SEL0_PLL1_SYS_SEL(v) (((v) << 7) & BIT(7))126#define OV8865_CLK_SEL1_REG 0x3033127#define OV8865_CLK_SEL1_MIPI_EOF BIT(5)128#define OV8865_CLK_SEL1_UNKNOWN BIT(2)129#define OV8865_CLK_SEL1_PLL_SCLK_SEL_MASK BIT(1)130#define OV8865_CLK_SEL1_PLL_SCLK_SEL(v) (((v) << 1) & BIT(1))131 132#define OV8865_SCLK_CTRL_REG 0x3106133#define OV8865_SCLK_CTRL_SCLK_DIV(v) (((v) << 4) & GENMASK(7, 4))134#define OV8865_SCLK_CTRL_SCLK_PRE_DIV(v) (((v) << 2) & GENMASK(3, 2))135#define OV8865_SCLK_CTRL_UNKNOWN BIT(0)136 137/* Exposure/gain */138 139#define OV8865_EXPOSURE_CTRL_HH_REG 0x3500140#define OV8865_EXPOSURE_CTRL_HH(v) (((v) & GENMASK(19, 16)) >> 16)141#define OV8865_EXPOSURE_CTRL_H_REG 0x3501142#define OV8865_EXPOSURE_CTRL_H(v) (((v) & GENMASK(15, 8)) >> 8)143#define OV8865_EXPOSURE_CTRL_L_REG 0x3502144#define OV8865_EXPOSURE_CTRL_L(v) ((v) & GENMASK(7, 0))145#define OV8865_EXPOSURE_GAIN_MANUAL_REG 0x3503146#define OV8865_INTEGRATION_TIME_MARGIN 8147 148#define OV8865_GAIN_CTRL_H_REG 0x3508149#define OV8865_GAIN_CTRL_H(v) (((v) & GENMASK(12, 8)) >> 8)150#define OV8865_GAIN_CTRL_L_REG 0x3509151#define OV8865_GAIN_CTRL_L(v) ((v) & GENMASK(7, 0))152 153/* Timing */154 155#define OV8865_CROP_START_X_H_REG 0x3800156#define OV8865_CROP_START_X_H(v) (((v) & GENMASK(11, 8)) >> 8)157#define OV8865_CROP_START_X_L_REG 0x3801158#define OV8865_CROP_START_X_L(v) ((v) & GENMASK(7, 0))159#define OV8865_CROP_START_Y_H_REG 0x3802160#define OV8865_CROP_START_Y_H(v) (((v) & GENMASK(11, 8)) >> 8)161#define OV8865_CROP_START_Y_L_REG 0x3803162#define OV8865_CROP_START_Y_L(v) ((v) & GENMASK(7, 0))163#define OV8865_CROP_END_X_H_REG 0x3804164#define OV8865_CROP_END_X_H(v) (((v) & GENMASK(11, 8)) >> 8)165#define OV8865_CROP_END_X_L_REG 0x3805166#define OV8865_CROP_END_X_L(v) ((v) & GENMASK(7, 0))167#define OV8865_CROP_END_Y_H_REG 0x3806168#define OV8865_CROP_END_Y_H(v) (((v) & GENMASK(11, 8)) >> 8)169#define OV8865_CROP_END_Y_L_REG 0x3807170#define OV8865_CROP_END_Y_L(v) ((v) & GENMASK(7, 0))171#define OV8865_OUTPUT_SIZE_X_H_REG 0x3808172#define OV8865_OUTPUT_SIZE_X_H(v) (((v) & GENMASK(11, 8)) >> 8)173#define OV8865_OUTPUT_SIZE_X_L_REG 0x3809174#define OV8865_OUTPUT_SIZE_X_L(v) ((v) & GENMASK(7, 0))175#define OV8865_OUTPUT_SIZE_Y_H_REG 0x380a176#define OV8865_OUTPUT_SIZE_Y_H(v) (((v) & GENMASK(11, 8)) >> 8)177#define OV8865_OUTPUT_SIZE_Y_L_REG 0x380b178#define OV8865_OUTPUT_SIZE_Y_L(v) ((v) & GENMASK(7, 0))179#define OV8865_HTS_H_REG 0x380c180#define OV8865_HTS_H(v) (((v) & GENMASK(11, 8)) >> 8)181#define OV8865_HTS_L_REG 0x380d182#define OV8865_HTS_L(v) ((v) & GENMASK(7, 0))183#define OV8865_VTS_H_REG 0x380e184#define OV8865_VTS_H(v) (((v) & GENMASK(11, 8)) >> 8)185#define OV8865_VTS_L_REG 0x380f186#define OV8865_VTS_L(v) ((v) & GENMASK(7, 0))187#define OV8865_TIMING_MAX_VTS 0xffff188#define OV8865_TIMING_MIN_VTS 0x04189#define OV8865_OFFSET_X_H_REG 0x3810190#define OV8865_OFFSET_X_H(v) (((v) & GENMASK(15, 8)) >> 8)191#define OV8865_OFFSET_X_L_REG 0x3811192#define OV8865_OFFSET_X_L(v) ((v) & GENMASK(7, 0))193#define OV8865_OFFSET_Y_H_REG 0x3812194#define OV8865_OFFSET_Y_H(v) (((v) & GENMASK(14, 8)) >> 8)195#define OV8865_OFFSET_Y_L_REG 0x3813196#define OV8865_OFFSET_Y_L(v) ((v) & GENMASK(7, 0))197#define OV8865_INC_X_ODD_REG 0x3814198#define OV8865_INC_X_ODD(v) ((v) & GENMASK(4, 0))199#define OV8865_INC_X_EVEN_REG 0x3815200#define OV8865_INC_X_EVEN(v) ((v) & GENMASK(4, 0))201#define OV8865_VSYNC_START_H_REG 0x3816202#define OV8865_VSYNC_START_H(v) (((v) & GENMASK(15, 8)) >> 8)203#define OV8865_VSYNC_START_L_REG 0x3817204#define OV8865_VSYNC_START_L(v) ((v) & GENMASK(7, 0))205#define OV8865_VSYNC_END_H_REG 0x3818206#define OV8865_VSYNC_END_H(v) (((v) & GENMASK(15, 8)) >> 8)207#define OV8865_VSYNC_END_L_REG 0x3819208#define OV8865_VSYNC_END_L(v) ((v) & GENMASK(7, 0))209#define OV8865_HSYNC_FIRST_H_REG 0x381a210#define OV8865_HSYNC_FIRST_H(v) (((v) & GENMASK(15, 8)) >> 8)211#define OV8865_HSYNC_FIRST_L_REG 0x381b212#define OV8865_HSYNC_FIRST_L(v) ((v) & GENMASK(7, 0))213 214#define OV8865_FORMAT1_REG 0x3820215#define OV8865_FORMAT1_FLIP_VERT_ISP_EN BIT(2)216#define OV8865_FORMAT1_FLIP_VERT_SENSOR_EN BIT(1)217#define OV8865_FORMAT2_REG 0x3821218#define OV8865_FORMAT2_HSYNC_EN BIT(6)219#define OV8865_FORMAT2_FST_VBIN_EN BIT(5)220#define OV8865_FORMAT2_FST_HBIN_EN BIT(4)221#define OV8865_FORMAT2_ISP_HORZ_VAR2_EN BIT(3)222#define OV8865_FORMAT2_FLIP_HORZ_ISP_EN BIT(2)223#define OV8865_FORMAT2_FLIP_HORZ_SENSOR_EN BIT(1)224#define OV8865_FORMAT2_SYNC_HBIN_EN BIT(0)225 226#define OV8865_INC_Y_ODD_REG 0x382a227#define OV8865_INC_Y_ODD(v) ((v) & GENMASK(4, 0))228#define OV8865_INC_Y_EVEN_REG 0x382b229#define OV8865_INC_Y_EVEN(v) ((v) & GENMASK(4, 0))230 231#define OV8865_ABLC_NUM_REG 0x3830232#define OV8865_ABLC_NUM(v) ((v) & GENMASK(4, 0))233 234#define OV8865_ZLINE_NUM_REG 0x3836235#define OV8865_ZLINE_NUM(v) ((v) & GENMASK(4, 0))236 237#define OV8865_AUTO_SIZE_CTRL_REG 0x3841238#define OV8865_AUTO_SIZE_CTRL_OFFSET_Y_REG BIT(5)239#define OV8865_AUTO_SIZE_CTRL_OFFSET_X_REG BIT(4)240#define OV8865_AUTO_SIZE_CTRL_CROP_END_Y_REG BIT(3)241#define OV8865_AUTO_SIZE_CTRL_CROP_END_X_REG BIT(2)242#define OV8865_AUTO_SIZE_CTRL_CROP_START_Y_REG BIT(1)243#define OV8865_AUTO_SIZE_CTRL_CROP_START_X_REG BIT(0)244#define OV8865_AUTO_SIZE_X_OFFSET_H_REG 0x3842245#define OV8865_AUTO_SIZE_X_OFFSET_L_REG 0x3843246#define OV8865_AUTO_SIZE_Y_OFFSET_H_REG 0x3844247#define OV8865_AUTO_SIZE_Y_OFFSET_L_REG 0x3845248#define OV8865_AUTO_SIZE_BOUNDARIES_REG 0x3846249#define OV8865_AUTO_SIZE_BOUNDARIES_Y(v) (((v) << 4) & GENMASK(7, 4))250#define OV8865_AUTO_SIZE_BOUNDARIES_X(v) ((v) & GENMASK(3, 0))251 252/* PSRAM */253 254#define OV8865_PSRAM_CTRL8_REG 0x3f08255 256/* Black Level */257 258#define OV8865_BLC_CTRL0_REG 0x4000259#define OV8865_BLC_CTRL0_TRIG_RANGE_EN BIT(7)260#define OV8865_BLC_CTRL0_TRIG_FORMAT_EN BIT(6)261#define OV8865_BLC_CTRL0_TRIG_GAIN_EN BIT(5)262#define OV8865_BLC_CTRL0_TRIG_EXPOSURE_EN BIT(4)263#define OV8865_BLC_CTRL0_TRIG_MANUAL_EN BIT(3)264#define OV8865_BLC_CTRL0_FREEZE_EN BIT(2)265#define OV8865_BLC_CTRL0_ALWAYS_EN BIT(1)266#define OV8865_BLC_CTRL0_FILTER_EN BIT(0)267#define OV8865_BLC_CTRL1_REG 0x4001268#define OV8865_BLC_CTRL1_DITHER_EN BIT(7)269#define OV8865_BLC_CTRL1_ZERO_LINE_DIFF_EN BIT(6)270#define OV8865_BLC_CTRL1_COL_SHIFT_256 (0 << 4)271#define OV8865_BLC_CTRL1_COL_SHIFT_128 (1 << 4)272#define OV8865_BLC_CTRL1_COL_SHIFT_64 (2 << 4)273#define OV8865_BLC_CTRL1_COL_SHIFT_32 (3 << 4)274#define OV8865_BLC_CTRL1_OFFSET_LIMIT_EN BIT(2)275#define OV8865_BLC_CTRL1_COLUMN_CANCEL_EN BIT(1)276#define OV8865_BLC_CTRL2_REG 0x4002277#define OV8865_BLC_CTRL3_REG 0x4003278#define OV8865_BLC_CTRL4_REG 0x4004279#define OV8865_BLC_CTRL5_REG 0x4005280#define OV8865_BLC_CTRL6_REG 0x4006281#define OV8865_BLC_CTRL7_REG 0x4007282#define OV8865_BLC_CTRL8_REG 0x4008283#define OV8865_BLC_CTRL9_REG 0x4009284#define OV8865_BLC_CTRLA_REG 0x400a285#define OV8865_BLC_CTRLB_REG 0x400b286#define OV8865_BLC_CTRLC_REG 0x400c287#define OV8865_BLC_CTRLD_REG 0x400d288#define OV8865_BLC_CTRLD_OFFSET_TRIGGER(v) ((v) & GENMASK(7, 0))289 290#define OV8865_BLC_CTRL1F_REG 0x401f291#define OV8865_BLC_CTRL1F_RB_REVERSE BIT(3)292#define OV8865_BLC_CTRL1F_INTERPOL_X_EN BIT(2)293#define OV8865_BLC_CTRL1F_INTERPOL_Y_EN BIT(1)294 295#define OV8865_BLC_ANCHOR_LEFT_START_H_REG 0x4020296#define OV8865_BLC_ANCHOR_LEFT_START_H(v) (((v) & GENMASK(11, 8)) >> 8)297#define OV8865_BLC_ANCHOR_LEFT_START_L_REG 0x4021298#define OV8865_BLC_ANCHOR_LEFT_START_L(v) ((v) & GENMASK(7, 0))299#define OV8865_BLC_ANCHOR_LEFT_END_H_REG 0x4022300#define OV8865_BLC_ANCHOR_LEFT_END_H(v) (((v) & GENMASK(11, 8)) >> 8)301#define OV8865_BLC_ANCHOR_LEFT_END_L_REG 0x4023302#define OV8865_BLC_ANCHOR_LEFT_END_L(v) ((v) & GENMASK(7, 0))303#define OV8865_BLC_ANCHOR_RIGHT_START_H_REG 0x4024304#define OV8865_BLC_ANCHOR_RIGHT_START_H(v) (((v) & GENMASK(11, 8)) >> 8)305#define OV8865_BLC_ANCHOR_RIGHT_START_L_REG 0x4025306#define OV8865_BLC_ANCHOR_RIGHT_START_L(v) ((v) & GENMASK(7, 0))307#define OV8865_BLC_ANCHOR_RIGHT_END_H_REG 0x4026308#define OV8865_BLC_ANCHOR_RIGHT_END_H(v) (((v) & GENMASK(11, 8)) >> 8)309#define OV8865_BLC_ANCHOR_RIGHT_END_L_REG 0x4027310#define OV8865_BLC_ANCHOR_RIGHT_END_L(v) ((v) & GENMASK(7, 0))311 312#define OV8865_BLC_TOP_ZLINE_START_REG 0x4028313#define OV8865_BLC_TOP_ZLINE_START(v) ((v) & GENMASK(5, 0))314#define OV8865_BLC_TOP_ZLINE_NUM_REG 0x4029315#define OV8865_BLC_TOP_ZLINE_NUM(v) ((v) & GENMASK(4, 0))316#define OV8865_BLC_TOP_BLKLINE_START_REG 0x402a317#define OV8865_BLC_TOP_BLKLINE_START(v) ((v) & GENMASK(5, 0))318#define OV8865_BLC_TOP_BLKLINE_NUM_REG 0x402b319#define OV8865_BLC_TOP_BLKLINE_NUM(v) ((v) & GENMASK(4, 0))320#define OV8865_BLC_BOT_ZLINE_START_REG 0x402c321#define OV8865_BLC_BOT_ZLINE_START(v) ((v) & GENMASK(5, 0))322#define OV8865_BLC_BOT_ZLINE_NUM_REG 0x402d323#define OV8865_BLC_BOT_ZLINE_NUM(v) ((v) & GENMASK(4, 0))324#define OV8865_BLC_BOT_BLKLINE_START_REG 0x402e325#define OV8865_BLC_BOT_BLKLINE_START(v) ((v) & GENMASK(5, 0))326#define OV8865_BLC_BOT_BLKLINE_NUM_REG 0x402f327#define OV8865_BLC_BOT_BLKLINE_NUM(v) ((v) & GENMASK(4, 0))328 329#define OV8865_BLC_OFFSET_LIMIT_REG 0x4034330#define OV8865_BLC_OFFSET_LIMIT(v) ((v) & GENMASK(7, 0))331 332/* VFIFO */333 334#define OV8865_VFIFO_READ_START_H_REG 0x4600335#define OV8865_VFIFO_READ_START_H(v) (((v) & GENMASK(15, 8)) >> 8)336#define OV8865_VFIFO_READ_START_L_REG 0x4601337#define OV8865_VFIFO_READ_START_L(v) ((v) & GENMASK(7, 0))338 339/* MIPI */340 341#define OV8865_MIPI_CTRL0_REG 0x4800342#define OV8865_MIPI_CTRL1_REG 0x4801343#define OV8865_MIPI_CTRL2_REG 0x4802344#define OV8865_MIPI_CTRL3_REG 0x4803345#define OV8865_MIPI_CTRL4_REG 0x4804346#define OV8865_MIPI_CTRL5_REG 0x4805347#define OV8865_MIPI_CTRL6_REG 0x4806348#define OV8865_MIPI_CTRL7_REG 0x4807349#define OV8865_MIPI_CTRL8_REG 0x4808350 351#define OV8865_MIPI_FCNT_MAX_H_REG 0x4810352#define OV8865_MIPI_FCNT_MAX_L_REG 0x4811353 354#define OV8865_MIPI_CTRL13_REG 0x4813355#define OV8865_MIPI_CTRL14_REG 0x4814356#define OV8865_MIPI_CTRL15_REG 0x4815357#define OV8865_MIPI_EMBEDDED_DT_REG 0x4816358 359#define OV8865_MIPI_HS_ZERO_MIN_H_REG 0x4818360#define OV8865_MIPI_HS_ZERO_MIN_L_REG 0x4819361#define OV8865_MIPI_HS_TRAIL_MIN_H_REG 0x481a362#define OV8865_MIPI_HS_TRAIL_MIN_L_REG 0x481b363#define OV8865_MIPI_CLK_ZERO_MIN_H_REG 0x481c364#define OV8865_MIPI_CLK_ZERO_MIN_L_REG 0x481d365#define OV8865_MIPI_CLK_PREPARE_MAX_REG 0x481e366#define OV8865_MIPI_CLK_PREPARE_MIN_REG 0x481f367#define OV8865_MIPI_CLK_POST_MIN_H_REG 0x4820368#define OV8865_MIPI_CLK_POST_MIN_L_REG 0x4821369#define OV8865_MIPI_CLK_TRAIL_MIN_H_REG 0x4822370#define OV8865_MIPI_CLK_TRAIL_MIN_L_REG 0x4823371#define OV8865_MIPI_LPX_P_MIN_H_REG 0x4824372#define OV8865_MIPI_LPX_P_MIN_L_REG 0x4825373#define OV8865_MIPI_HS_PREPARE_MIN_REG 0x4826374#define OV8865_MIPI_HS_PREPARE_MAX_REG 0x4827375#define OV8865_MIPI_HS_EXIT_MIN_H_REG 0x4828376#define OV8865_MIPI_HS_EXIT_MIN_L_REG 0x4829377#define OV8865_MIPI_UI_HS_ZERO_MIN_REG 0x482a378#define OV8865_MIPI_UI_HS_TRAIL_MIN_REG 0x482b379#define OV8865_MIPI_UI_CLK_ZERO_MIN_REG 0x482c380#define OV8865_MIPI_UI_CLK_PREPARE_REG 0x482d381#define OV8865_MIPI_UI_CLK_POST_MIN_REG 0x482e382#define OV8865_MIPI_UI_CLK_TRAIL_MIN_REG 0x482f383#define OV8865_MIPI_UI_LPX_P_MIN_REG 0x4830384#define OV8865_MIPI_UI_HS_PREPARE_REG 0x4831385#define OV8865_MIPI_UI_HS_EXIT_MIN_REG 0x4832386#define OV8865_MIPI_PKT_START_SIZE_REG 0x4833387 388#define OV8865_MIPI_PCLK_PERIOD_REG 0x4837389#define OV8865_MIPI_LP_GPIO0_REG 0x4838390#define OV8865_MIPI_LP_GPIO1_REG 0x4839391 392#define OV8865_MIPI_CTRL3C_REG 0x483c393#define OV8865_MIPI_LP_GPIO4_REG 0x483d394 395#define OV8865_MIPI_CTRL4A_REG 0x484a396#define OV8865_MIPI_CTRL4B_REG 0x484b397#define OV8865_MIPI_CTRL4C_REG 0x484c398#define OV8865_MIPI_LANE_TEST_PATTERN_REG 0x484d399#define OV8865_MIPI_FRAME_END_DELAY_REG 0x484e400#define OV8865_MIPI_CLOCK_TEST_PATTERN_REG 0x484f401#define OV8865_MIPI_LANE_SEL01_REG 0x4850402#define OV8865_MIPI_LANE_SEL01_LANE0(v) (((v) << 0) & GENMASK(2, 0))403#define OV8865_MIPI_LANE_SEL01_LANE1(v) (((v) << 4) & GENMASK(6, 4))404#define OV8865_MIPI_LANE_SEL23_REG 0x4851405#define OV8865_MIPI_LANE_SEL23_LANE2(v) (((v) << 0) & GENMASK(2, 0))406#define OV8865_MIPI_LANE_SEL23_LANE3(v) (((v) << 4) & GENMASK(6, 4))407 408/* ISP */409 410#define OV8865_ISP_CTRL0_REG 0x5000411#define OV8865_ISP_CTRL0_LENC_EN BIT(7)412#define OV8865_ISP_CTRL0_WHITE_BALANCE_EN BIT(4)413#define OV8865_ISP_CTRL0_DPC_BLACK_EN BIT(2)414#define OV8865_ISP_CTRL0_DPC_WHITE_EN BIT(1)415#define OV8865_ISP_CTRL1_REG 0x5001416#define OV8865_ISP_CTRL1_BLC_EN BIT(0)417#define OV8865_ISP_CTRL2_REG 0x5002418#define OV8865_ISP_CTRL2_DEBUG BIT(3)419#define OV8865_ISP_CTRL2_VARIOPIXEL_EN BIT(2)420#define OV8865_ISP_CTRL2_VSYNC_LATCH_EN BIT(0)421#define OV8865_ISP_CTRL3_REG 0x5003422 423#define OV8865_ISP_GAIN_RED_H_REG 0x5018424#define OV8865_ISP_GAIN_RED_H(v) (((v) & GENMASK(13, 6)) >> 6)425#define OV8865_ISP_GAIN_RED_L_REG 0x5019426#define OV8865_ISP_GAIN_RED_L(v) ((v) & GENMASK(5, 0))427#define OV8865_ISP_GAIN_GREEN_H_REG 0x501a428#define OV8865_ISP_GAIN_GREEN_H(v) (((v) & GENMASK(13, 6)) >> 6)429#define OV8865_ISP_GAIN_GREEN_L_REG 0x501b430#define OV8865_ISP_GAIN_GREEN_L(v) ((v) & GENMASK(5, 0))431#define OV8865_ISP_GAIN_BLUE_H_REG 0x501c432#define OV8865_ISP_GAIN_BLUE_H(v) (((v) & GENMASK(13, 6)) >> 6)433#define OV8865_ISP_GAIN_BLUE_L_REG 0x501d434#define OV8865_ISP_GAIN_BLUE_L(v) ((v) & GENMASK(5, 0))435 436/* VarioPixel */437 438#define OV8865_VAP_CTRL0_REG 0x5900439#define OV8865_VAP_CTRL1_REG 0x5901440#define OV8865_VAP_CTRL1_HSUB_COEF(v) ((((v) - 1) << 2) & \441 GENMASK(3, 2))442#define OV8865_VAP_CTRL1_VSUB_COEF(v) (((v) - 1) & GENMASK(1, 0))443 444/* Pre-DSP */445 446#define OV8865_PRE_CTRL0_REG 0x5e00447#define OV8865_PRE_CTRL0_PATTERN_EN BIT(7)448#define OV8865_PRE_CTRL0_ROLLING_BAR_EN BIT(6)449#define OV8865_PRE_CTRL0_TRANSPARENT_MODE BIT(5)450#define OV8865_PRE_CTRL0_SQUARES_BW_MODE BIT(4)451#define OV8865_PRE_CTRL0_PATTERN_COLOR_BARS 0452#define OV8865_PRE_CTRL0_PATTERN_RANDOM_DATA 1453#define OV8865_PRE_CTRL0_PATTERN_COLOR_SQUARES 2454#define OV8865_PRE_CTRL0_PATTERN_BLACK 3455 456/* Pixel Array */457 458#define OV8865_NATIVE_WIDTH 3296459#define OV8865_NATIVE_HEIGHT 2528460#define OV8865_ACTIVE_START_LEFT 16461#define OV8865_ACTIVE_START_TOP 40462#define OV8865_ACTIVE_WIDTH 3264463#define OV8865_ACTIVE_HEIGHT 2448464 465/* Macros */466 467#define ov8865_subdev_sensor(s) \468 container_of(s, struct ov8865_sensor, subdev)469 470#define ov8865_ctrl_subdev(c) \471 (&container_of((c)->handler, struct ov8865_sensor, \472 ctrls.handler)->subdev)473 474/* Data structures */475 476struct ov8865_register_value {477 u16 address;478 u8 value;479 unsigned int delay_ms;480};481 482/*483 * PLL1 Clock Tree:484 *485 * +-< EXTCLK486 * |487 * +-+ pll_pre_div_half (0x30a [0])488 * |489 * +-+ pll_pre_div (0x300 [2:0], special values:490 * | 0: 1, 1: 1.5, 3: 2.5, 4: 3, 5: 4, 7: 8)491 * +-+ pll_mul (0x301 [1:0], 0x302 [7:0])492 * |493 * +-+ m_div (0x303 [3:0])494 * | |495 * | +-> PHY_SCLK496 * | |497 * | +-+ mipi_div (0x304 [1:0], special values: 0: 4, 1: 5, 2: 6, 3: 8)498 * | |499 * | +-+ pclk_div (0x3020 [3])500 * | |501 * | +-> PCLK502 * |503 * +-+ sys_pre_div (0x305 [1:0], special values: 0: 3, 1: 4, 2: 5, 3: 6)504 * |505 * +-+ sys_div (0x306 [0])506 * |507 * +-+ sys_sel (0x3032 [7], 0: PLL1, 1: PLL2)508 * |509 * +-+ sclk_sel (0x3033 [1], 0: sys_sel, 1: PLL2 DAC_CLK)510 * |511 * +-+ sclk_pre_div (0x3106 [3:2], special values:512 * | 0: 1, 1: 2, 2: 4, 3: 1)513 * |514 * +-+ sclk_div (0x3106 [7:4], special values: 0: 1)515 * |516 * +-> SCLK517 */518 519struct ov8865_pll1_config {520 unsigned int pll_pre_div_half;521 unsigned int pll_pre_div;522 unsigned int pll_mul;523 unsigned int m_div;524 unsigned int mipi_div;525 unsigned int pclk_div;526 unsigned int sys_pre_div;527 unsigned int sys_div;528};529 530/*531 * PLL2 Clock Tree:532 *533 * +-< EXTCLK534 * |535 * +-+ pll_pre_div_half (0x312 [4])536 * |537 * +-+ pll_pre_div (0x30b [2:0], special values:538 * | 0: 1, 1: 1.5, 3: 2.5, 4: 3, 5: 4, 7: 8)539 * +-+ pll_mul (0x30c [1:0], 0x30d [7:0])540 * |541 * +-+ dac_div (0x312 [3:0])542 * | |543 * | +-> DAC_CLK544 * |545 * +-+ sys_pre_div (0x30f [3:0])546 * |547 * +-+ sys_div (0x30e [2:0], special values:548 * | 0: 1, 1: 1.5, 3: 2.5, 4: 3, 5: 3.5, 6: 4, 7:5)549 * |550 * +-+ sys_sel (0x3032 [7], 0: PLL1, 1: PLL2)551 * |552 * +-+ sclk_sel (0x3033 [1], 0: sys_sel, 1: PLL2 DAC_CLK)553 * |554 * +-+ sclk_pre_div (0x3106 [3:2], special values:555 * | 0: 1, 1: 2, 2: 4, 3: 1)556 * |557 * +-+ sclk_div (0x3106 [7:4], special values: 0: 1)558 * |559 * +-> SCLK560 */561 562struct ov8865_pll2_config {563 unsigned int pll_pre_div_half;564 unsigned int pll_pre_div;565 unsigned int pll_mul;566 unsigned int dac_div;567 unsigned int sys_pre_div;568 unsigned int sys_div;569};570 571struct ov8865_sclk_config {572 unsigned int sys_sel;573 unsigned int sclk_sel;574 unsigned int sclk_pre_div;575 unsigned int sclk_div;576};577 578struct ov8865_pll_configs {579 const struct ov8865_pll1_config *pll1_config;580 const struct ov8865_pll2_config *pll2_config_native;581 const struct ov8865_pll2_config *pll2_config_binning;582};583 584/* Clock rate */585 586enum extclk_rate {587 OV8865_19_2_MHZ,588 OV8865_24_MHZ,589 OV8865_NUM_SUPPORTED_RATES590};591 592static const unsigned long supported_extclk_rates[] = {593 [OV8865_19_2_MHZ] = 19200000,594 [OV8865_24_MHZ] = 24000000,595};596 597/*598 * General formulas for (array-centered) mode calculation:599 * - photo_array_width = 3296600 * - crop_start_x = (photo_array_width - output_size_x) / 2601 * - crop_end_x = crop_start_x + offset_x + output_size_x - 1602 *603 * - photo_array_height = 2480604 * - crop_start_y = (photo_array_height - output_size_y) / 2605 * - crop_end_y = crop_start_y + offset_y + output_size_y - 1606 */607 608struct ov8865_mode {609 unsigned int crop_start_x;610 unsigned int offset_x;611 unsigned int output_size_x;612 unsigned int crop_end_x;613 unsigned int hts;614 615 unsigned int crop_start_y;616 unsigned int offset_y;617 unsigned int output_size_y;618 unsigned int crop_end_y;619 unsigned int vts;620 621 /* With auto size, only output and total sizes need to be set. */622 bool size_auto;623 unsigned int size_auto_boundary_x;624 unsigned int size_auto_boundary_y;625 626 bool binning_x;627 bool binning_y;628 bool variopixel;629 unsigned int variopixel_hsub_coef;630 unsigned int variopixel_vsub_coef;631 632 /* Bits for the format register, used for binning. */633 bool sync_hbin;634 bool horz_var2;635 636 unsigned int inc_x_odd;637 unsigned int inc_x_even;638 unsigned int inc_y_odd;639 unsigned int inc_y_even;640 641 unsigned int vfifo_read_start;642 643 unsigned int ablc_num;644 unsigned int zline_num;645 646 unsigned int blc_top_zero_line_start;647 unsigned int blc_top_zero_line_num;648 unsigned int blc_top_black_line_start;649 unsigned int blc_top_black_line_num;650 651 unsigned int blc_bottom_zero_line_start;652 unsigned int blc_bottom_zero_line_num;653 unsigned int blc_bottom_black_line_start;654 unsigned int blc_bottom_black_line_num;655 656 u8 blc_col_shift_mask;657 658 unsigned int blc_anchor_left_start;659 unsigned int blc_anchor_left_end;660 unsigned int blc_anchor_right_start;661 unsigned int blc_anchor_right_end;662 663 bool pll2_binning;664 665 const struct ov8865_register_value *register_values;666 unsigned int register_values_count;667};668 669struct ov8865_state {670 const struct ov8865_mode *mode;671 u32 mbus_code;672 673 bool streaming;674};675 676struct ov8865_ctrls {677 struct v4l2_ctrl *link_freq;678 struct v4l2_ctrl *pixel_rate;679 struct v4l2_ctrl *hblank;680 struct v4l2_ctrl *vblank;681 struct v4l2_ctrl *exposure;682 683 struct v4l2_ctrl_handler handler;684};685 686struct ov8865_sensor {687 struct device *dev;688 struct i2c_client *i2c_client;689 struct gpio_desc *reset;690 struct gpio_desc *powerdown;691 struct regulator *avdd;692 struct regulator *dvdd;693 struct regulator *dovdd;694 695 unsigned long extclk_rate;696 const struct ov8865_pll_configs *pll_configs;697 struct clk *extclk;698 699 struct v4l2_fwnode_endpoint endpoint;700 struct v4l2_subdev subdev;701 struct media_pad pad;702 703 struct mutex mutex;704 705 struct ov8865_state state;706 struct ov8865_ctrls ctrls;707};708 709/* Static definitions */710 711/*712 * PHY_SCLK = 720 MHz713 * MIPI_PCLK = 90 MHz714 */715 716static const struct ov8865_pll1_config ov8865_pll1_config_native_19_2mhz = {717 .pll_pre_div_half = 1,718 .pll_pre_div = 2,719 .pll_mul = 75,720 .m_div = 1,721 .mipi_div = 3,722 .pclk_div = 1,723 .sys_pre_div = 1,724 .sys_div = 2,725};726 727static const struct ov8865_pll1_config ov8865_pll1_config_native_24mhz = {728 .pll_pre_div_half = 1,729 .pll_pre_div = 0,730 .pll_mul = 30,731 .m_div = 1,732 .mipi_div = 3,733 .pclk_div = 1,734 .sys_pre_div = 1,735 .sys_div = 2,736};737 738/*739 * DAC_CLK = 360 MHz740 * SCLK = 144 MHz741 */742 743static const struct ov8865_pll2_config ov8865_pll2_config_native_19_2mhz = {744 .pll_pre_div_half = 1,745 .pll_pre_div = 5,746 .pll_mul = 75,747 .dac_div = 1,748 .sys_pre_div = 1,749 .sys_div = 3,750};751 752static const struct ov8865_pll2_config ov8865_pll2_config_native_24mhz = {753 .pll_pre_div_half = 1,754 .pll_pre_div = 0,755 .pll_mul = 30,756 .dac_div = 2,757 .sys_pre_div = 5,758 .sys_div = 0,759};760 761/*762 * DAC_CLK = 360 MHz763 * SCLK = 72 MHz764 */765 766static const struct ov8865_pll2_config ov8865_pll2_config_binning_19_2mhz = {767 .pll_pre_div_half = 1,768 .pll_pre_div = 2,769 .pll_mul = 75,770 .dac_div = 2,771 .sys_pre_div = 10,772 .sys_div = 0,773};774 775static const struct ov8865_pll2_config ov8865_pll2_config_binning_24mhz = {776 .pll_pre_div_half = 1,777 .pll_pre_div = 0,778 .pll_mul = 30,779 .dac_div = 2,780 .sys_pre_div = 10,781 .sys_div = 0,782};783 784static const struct ov8865_pll_configs ov8865_pll_configs_19_2mhz = {785 .pll1_config = &ov8865_pll1_config_native_19_2mhz,786 .pll2_config_native = &ov8865_pll2_config_native_19_2mhz,787 .pll2_config_binning = &ov8865_pll2_config_binning_19_2mhz,788};789 790static const struct ov8865_pll_configs ov8865_pll_configs_24mhz = {791 .pll1_config = &ov8865_pll1_config_native_24mhz,792 .pll2_config_native = &ov8865_pll2_config_native_24mhz,793 .pll2_config_binning = &ov8865_pll2_config_binning_24mhz,794};795 796static const struct ov8865_pll_configs *ov8865_pll_configs[] = {797 &ov8865_pll_configs_19_2mhz,798 &ov8865_pll_configs_24mhz,799};800 801static const struct ov8865_sclk_config ov8865_sclk_config_native = {802 .sys_sel = 1,803 .sclk_sel = 0,804 .sclk_pre_div = 0,805 .sclk_div = 0,806};807 808static const struct ov8865_register_value ov8865_register_values_native[] = {809 /* Sensor */810 811 { 0x3700, 0x48 },812 { 0x3701, 0x18 },813 { 0x3702, 0x50 },814 { 0x3703, 0x32 },815 { 0x3704, 0x28 },816 { 0x3706, 0x70 },817 { 0x3707, 0x08 },818 { 0x3708, 0x48 },819 { 0x3709, 0x80 },820 { 0x370a, 0x01 },821 { 0x370b, 0x70 },822 { 0x370c, 0x07 },823 { 0x3718, 0x14 },824 { 0x3712, 0x44 },825 { 0x371e, 0x31 },826 { 0x371f, 0x7f },827 { 0x3720, 0x0a },828 { 0x3721, 0x0a },829 { 0x3724, 0x04 },830 { 0x3725, 0x04 },831 { 0x3726, 0x0c },832 { 0x3728, 0x0a },833 { 0x3729, 0x03 },834 { 0x372a, 0x06 },835 { 0x372b, 0xa6 },836 { 0x372c, 0xa6 },837 { 0x372d, 0xa6 },838 { 0x372e, 0x0c },839 { 0x372f, 0x20 },840 { 0x3730, 0x02 },841 { 0x3731, 0x0c },842 { 0x3732, 0x28 },843 { 0x3736, 0x30 },844 { 0x373a, 0x04 },845 { 0x373b, 0x18 },846 { 0x373c, 0x14 },847 { 0x373e, 0x06 },848 { 0x375a, 0x0c },849 { 0x375b, 0x26 },850 { 0x375d, 0x04 },851 { 0x375f, 0x28 },852 { 0x3767, 0x1e },853 { 0x3772, 0x46 },854 { 0x3773, 0x04 },855 { 0x3774, 0x2c },856 { 0x3775, 0x13 },857 { 0x3776, 0x10 },858 { 0x37a0, 0x88 },859 { 0x37a1, 0x7a },860 { 0x37a2, 0x7a },861 { 0x37a3, 0x02 },862 { 0x37a5, 0x09 },863 { 0x37a7, 0x88 },864 { 0x37a8, 0xb0 },865 { 0x37a9, 0xb0 },866 { 0x37aa, 0x88 },867 { 0x37ab, 0x5c },868 { 0x37ac, 0x5c },869 { 0x37ad, 0x55 },870 { 0x37ae, 0x19 },871 { 0x37af, 0x19 },872 { 0x37b3, 0x84 },873 { 0x37b4, 0x84 },874 { 0x37b5, 0x66 },875 876 /* PSRAM */877 878 { OV8865_PSRAM_CTRL8_REG, 0x16 },879 880 /* ADC Sync */881 882 { 0x4500, 0x68 },883};884 885static const struct ov8865_register_value ov8865_register_values_binning[] = {886 /* Sensor */887 888 { 0x3700, 0x24 },889 { 0x3701, 0x0c },890 { 0x3702, 0x28 },891 { 0x3703, 0x19 },892 { 0x3704, 0x14 },893 { 0x3706, 0x38 },894 { 0x3707, 0x04 },895 { 0x3708, 0x24 },896 { 0x3709, 0x40 },897 { 0x370a, 0x00 },898 { 0x370b, 0xb8 },899 { 0x370c, 0x04 },900 { 0x3718, 0x12 },901 { 0x3712, 0x42 },902 { 0x371e, 0x19 },903 { 0x371f, 0x40 },904 { 0x3720, 0x05 },905 { 0x3721, 0x05 },906 { 0x3724, 0x02 },907 { 0x3725, 0x02 },908 { 0x3726, 0x06 },909 { 0x3728, 0x05 },910 { 0x3729, 0x02 },911 { 0x372a, 0x03 },912 { 0x372b, 0x53 },913 { 0x372c, 0xa3 },914 { 0x372d, 0x53 },915 { 0x372e, 0x06 },916 { 0x372f, 0x10 },917 { 0x3730, 0x01 },918 { 0x3731, 0x06 },919 { 0x3732, 0x14 },920 { 0x3736, 0x20 },921 { 0x373a, 0x02 },922 { 0x373b, 0x0c },923 { 0x373c, 0x0a },924 { 0x373e, 0x03 },925 { 0x375a, 0x06 },926 { 0x375b, 0x13 },927 { 0x375d, 0x02 },928 { 0x375f, 0x14 },929 { 0x3767, 0x1c },930 { 0x3772, 0x23 },931 { 0x3773, 0x02 },932 { 0x3774, 0x16 },933 { 0x3775, 0x12 },934 { 0x3776, 0x08 },935 { 0x37a0, 0x44 },936 { 0x37a1, 0x3d },937 { 0x37a2, 0x3d },938 { 0x37a3, 0x01 },939 { 0x37a5, 0x08 },940 { 0x37a7, 0x44 },941 { 0x37a8, 0x58 },942 { 0x37a9, 0x58 },943 { 0x37aa, 0x44 },944 { 0x37ab, 0x2e },945 { 0x37ac, 0x2e },946 { 0x37ad, 0x33 },947 { 0x37ae, 0x0d },948 { 0x37af, 0x0d },949 { 0x37b3, 0x42 },950 { 0x37b4, 0x42 },951 { 0x37b5, 0x33 },952 953 /* PSRAM */954 955 { OV8865_PSRAM_CTRL8_REG, 0x0b },956 957 /* ADC Sync */958 959 { 0x4500, 0x40 },960};961 962static const struct ov8865_mode ov8865_modes[] = {963 /* 3264x2448 */964 {965 /* Horizontal */966 .output_size_x = 3264,967 .hts = 3888,968 969 /* Vertical */970 .output_size_y = 2448,971 .vts = 2470,972 973 .size_auto = true,974 .size_auto_boundary_x = 8,975 .size_auto_boundary_y = 4,976 977 /* Subsample increase */978 .inc_x_odd = 1,979 .inc_x_even = 1,980 .inc_y_odd = 1,981 .inc_y_even = 1,982 983 /* VFIFO */984 .vfifo_read_start = 16,985 986 .ablc_num = 4,987 .zline_num = 1,988 989 /* Black Level */990 991 .blc_top_zero_line_start = 0,992 .blc_top_zero_line_num = 2,993 .blc_top_black_line_start = 4,994 .blc_top_black_line_num = 4,995 996 .blc_bottom_zero_line_start = 2,997 .blc_bottom_zero_line_num = 2,998 .blc_bottom_black_line_start = 8,999 .blc_bottom_black_line_num = 2,1000 1001 .blc_anchor_left_start = 576,1002 .blc_anchor_left_end = 831,1003 .blc_anchor_right_start = 1984,1004 .blc_anchor_right_end = 2239,1005 1006 /* PLL */1007 .pll2_binning = false,1008 1009 /* Registers */1010 .register_values = ov8865_register_values_native,1011 .register_values_count =1012 ARRAY_SIZE(ov8865_register_values_native),1013 },1014 /* 3264x1836 */1015 {1016 /* Horizontal */1017 .output_size_x = 3264,1018 .hts = 3888,1019 1020 /* Vertical */1021 .output_size_y = 1836,1022 .vts = 2470,1023 1024 .size_auto = true,1025 .size_auto_boundary_x = 8,1026 .size_auto_boundary_y = 4,1027 1028 /* Subsample increase */1029 .inc_x_odd = 1,1030 .inc_x_even = 1,1031 .inc_y_odd = 1,1032 .inc_y_even = 1,1033 1034 /* VFIFO */1035 .vfifo_read_start = 16,1036 1037 .ablc_num = 4,1038 .zline_num = 1,1039 1040 /* Black Level */1041 1042 .blc_top_zero_line_start = 0,1043 .blc_top_zero_line_num = 2,1044 .blc_top_black_line_start = 4,1045 .blc_top_black_line_num = 4,1046 1047 .blc_bottom_zero_line_start = 2,1048 .blc_bottom_zero_line_num = 2,1049 .blc_bottom_black_line_start = 8,1050 .blc_bottom_black_line_num = 2,1051 1052 .blc_anchor_left_start = 576,1053 .blc_anchor_left_end = 831,1054 .blc_anchor_right_start = 1984,1055 .blc_anchor_right_end = 2239,1056 1057 /* PLL */1058 .pll2_binning = false,1059 1060 /* Registers */1061 .register_values = ov8865_register_values_native,1062 .register_values_count =1063 ARRAY_SIZE(ov8865_register_values_native),1064 },1065 /* 1632x1224 */1066 {1067 /* Horizontal */1068 .output_size_x = 1632,1069 .hts = 1923,1070 1071 /* Vertical */1072 .output_size_y = 1224,1073 .vts = 1248,1074 1075 .size_auto = true,1076 .size_auto_boundary_x = 8,1077 .size_auto_boundary_y = 8,1078 1079 /* Subsample increase */1080 .inc_x_odd = 3,1081 .inc_x_even = 1,1082 .inc_y_odd = 3,1083 .inc_y_even = 1,1084 1085 /* Binning */1086 .binning_y = true,1087 .sync_hbin = true,1088 1089 /* VFIFO */1090 .vfifo_read_start = 116,1091 1092 .ablc_num = 8,1093 .zline_num = 2,1094 1095 /* Black Level */1096 1097 .blc_top_zero_line_start = 0,1098 .blc_top_zero_line_num = 2,1099 .blc_top_black_line_start = 4,1100 .blc_top_black_line_num = 4,1101 1102 .blc_bottom_zero_line_start = 2,1103 .blc_bottom_zero_line_num = 2,1104 .blc_bottom_black_line_start = 8,1105 .blc_bottom_black_line_num = 2,1106 1107 .blc_anchor_left_start = 288,1108 .blc_anchor_left_end = 415,1109 .blc_anchor_right_start = 992,1110 .blc_anchor_right_end = 1119,1111 1112 /* PLL */1113 .pll2_binning = true,1114 1115 /* Registers */1116 .register_values = ov8865_register_values_binning,1117 .register_values_count =1118 ARRAY_SIZE(ov8865_register_values_binning),1119 },1120 /* 800x600 (SVGA) */1121 {1122 /* Horizontal */1123 .output_size_x = 800,1124 .hts = 1250,1125 1126 /* Vertical */1127 .output_size_y = 600,1128 .vts = 640,1129 1130 .size_auto = true,1131 .size_auto_boundary_x = 8,1132 .size_auto_boundary_y = 8,1133 1134 /* Subsample increase */1135 .inc_x_odd = 3,1136 .inc_x_even = 1,1137 .inc_y_odd = 5,1138 .inc_y_even = 3,1139 1140 /* Binning */1141 .binning_y = true,1142 .variopixel = true,1143 .variopixel_hsub_coef = 2,1144 .variopixel_vsub_coef = 1,1145 .sync_hbin = true,1146 .horz_var2 = true,1147 1148 /* VFIFO */1149 .vfifo_read_start = 80,1150 1151 .ablc_num = 8,1152 .zline_num = 2,1153 1154 /* Black Level */1155 1156 .blc_top_zero_line_start = 0,1157 .blc_top_zero_line_num = 2,1158 .blc_top_black_line_start = 2,1159 .blc_top_black_line_num = 2,1160 1161 .blc_bottom_zero_line_start = 0,1162 .blc_bottom_zero_line_num = 0,1163 .blc_bottom_black_line_start = 4,1164 .blc_bottom_black_line_num = 2,1165 1166 .blc_col_shift_mask = OV8865_BLC_CTRL1_COL_SHIFT_128,1167 1168 .blc_anchor_left_start = 288,1169 .blc_anchor_left_end = 415,1170 .blc_anchor_right_start = 992,1171 .blc_anchor_right_end = 1119,1172 1173 /* PLL */1174 .pll2_binning = true,1175 1176 /* Registers */1177 .register_values = ov8865_register_values_binning,1178 .register_values_count =1179 ARRAY_SIZE(ov8865_register_values_binning),1180 },1181};1182 1183static const u32 ov8865_mbus_codes[] = {1184 MEDIA_BUS_FMT_SBGGR10_1X10,1185};1186 1187static const struct ov8865_register_value ov8865_init_sequence[] = {1188 /* Analog */1189 1190 { 0x3604, 0x04 },1191 { 0x3602, 0x30 },1192 { 0x3605, 0x00 },1193 { 0x3607, 0x20 },1194 { 0x3608, 0x11 },1195 { 0x3609, 0x68 },1196 { 0x360a, 0x40 },1197 { 0x360c, 0xdd },1198 { 0x360e, 0x0c },1199 { 0x3610, 0x07 },1200 { 0x3612, 0x86 },1201 { 0x3613, 0x58 },1202 { 0x3614, 0x28 },1203 { 0x3617, 0x40 },1204 { 0x3618, 0x5a },1205 { 0x3619, 0x9b },1206 { 0x361c, 0x00 },1207 { 0x361d, 0x60 },1208 { 0x3631, 0x60 },1209 { 0x3633, 0x10 },1210 { 0x3634, 0x10 },1211 { 0x3635, 0x10 },1212 { 0x3636, 0x10 },1213 { 0x3638, 0xff },1214 { 0x3641, 0x55 },1215 { 0x3646, 0x86 },1216 { 0x3647, 0x27 },1217 { 0x364a, 0x1b },1218 1219 /* Sensor */1220 1221 { 0x3700, 0x24 },1222 { 0x3701, 0x0c },1223 { 0x3702, 0x28 },1224 { 0x3703, 0x19 },1225 { 0x3704, 0x14 },1226 { 0x3705, 0x00 },1227 { 0x3706, 0x38 },1228 { 0x3707, 0x04 },1229 { 0x3708, 0x24 },1230 { 0x3709, 0x40 },1231 { 0x370a, 0x00 },1232 { 0x370b, 0xb8 },1233 { 0x370c, 0x04 },1234 { 0x3718, 0x12 },1235 { 0x3719, 0x31 },1236 { 0x3712, 0x42 },1237 { 0x3714, 0x12 },1238 { 0x371e, 0x19 },1239 { 0x371f, 0x40 },1240 { 0x3720, 0x05 },1241 { 0x3721, 0x05 },1242 { 0x3724, 0x02 },1243 { 0x3725, 0x02 },1244 { 0x3726, 0x06 },1245 { 0x3728, 0x05 },1246 { 0x3729, 0x02 },1247 { 0x372a, 0x03 },1248 { 0x372b, 0x53 },1249 { 0x372c, 0xa3 },1250 { 0x372d, 0x53 },1251 { 0x372e, 0x06 },1252 { 0x372f, 0x10 },1253 { 0x3730, 0x01 },1254 { 0x3731, 0x06 },1255 { 0x3732, 0x14 },1256 { 0x3733, 0x10 },1257 { 0x3734, 0x40 },1258 { 0x3736, 0x20 },1259 { 0x373a, 0x02 },1260 { 0x373b, 0x0c },1261 { 0x373c, 0x0a },1262 { 0x373e, 0x03 },1263 { 0x3755, 0x40 },1264 { 0x3758, 0x00 },1265 { 0x3759, 0x4c },1266 { 0x375a, 0x06 },1267 { 0x375b, 0x13 },1268 { 0x375c, 0x40 },1269 { 0x375d, 0x02 },1270 { 0x375e, 0x00 },1271 { 0x375f, 0x14 },1272 { 0x3767, 0x1c },1273 { 0x3768, 0x04 },1274 { 0x3769, 0x20 },1275 { 0x376c, 0xc0 },1276 { 0x376d, 0xc0 },1277 { 0x376a, 0x08 },1278 { 0x3761, 0x00 },1279 { 0x3762, 0x00 },1280 { 0x3763, 0x00 },1281 { 0x3766, 0xff },1282 { 0x376b, 0x42 },1283 { 0x3772, 0x23 },1284 { 0x3773, 0x02 },1285 { 0x3774, 0x16 },1286 { 0x3775, 0x12 },1287 { 0x3776, 0x08 },1288 { 0x37a0, 0x44 },1289 { 0x37a1, 0x3d },1290 { 0x37a2, 0x3d },1291 { 0x37a3, 0x01 },1292 { 0x37a4, 0x00 },1293 { 0x37a5, 0x08 },1294 { 0x37a6, 0x00 },1295 { 0x37a7, 0x44 },1296 { 0x37a8, 0x58 },1297 { 0x37a9, 0x58 },1298 { 0x3760, 0x00 },1299 { 0x376f, 0x01 },1300 { 0x37aa, 0x44 },1301 { 0x37ab, 0x2e },1302 { 0x37ac, 0x2e },1303 { 0x37ad, 0x33 },1304 { 0x37ae, 0x0d },1305 { 0x37af, 0x0d },1306 { 0x37b0, 0x00 },1307 { 0x37b1, 0x00 },1308 { 0x37b2, 0x00 },1309 { 0x37b3, 0x42 },1310 { 0x37b4, 0x42 },1311 { 0x37b5, 0x33 },1312 { 0x37b6, 0x00 },1313 { 0x37b7, 0x00 },1314 { 0x37b8, 0x00 },1315 { 0x37b9, 0xff },1316 1317 /* ADC Sync */1318 1319 { 0x4503, 0x10 },1320};1321 1322static const s64 ov8865_link_freq_menu[] = {1323 360000000,1324};1325 1326static const char *const ov8865_test_pattern_menu[] = {1327 "Disabled",1328 "Random data",1329 "Color bars",1330 "Color bars with rolling bar",1331 "Color squares",1332 "Color squares with rolling bar"1333};1334 1335static const u8 ov8865_test_pattern_bits[] = {1336 0,1337 OV8865_PRE_CTRL0_PATTERN_EN | OV8865_PRE_CTRL0_PATTERN_RANDOM_DATA,1338 OV8865_PRE_CTRL0_PATTERN_EN | OV8865_PRE_CTRL0_PATTERN_COLOR_BARS,1339 OV8865_PRE_CTRL0_PATTERN_EN | OV8865_PRE_CTRL0_ROLLING_BAR_EN |1340 OV8865_PRE_CTRL0_PATTERN_COLOR_BARS,1341 OV8865_PRE_CTRL0_PATTERN_EN | OV8865_PRE_CTRL0_PATTERN_COLOR_SQUARES,1342 OV8865_PRE_CTRL0_PATTERN_EN | OV8865_PRE_CTRL0_ROLLING_BAR_EN |1343 OV8865_PRE_CTRL0_PATTERN_COLOR_SQUARES,1344};1345 1346/* Input/Output */1347 1348static int ov8865_read(struct ov8865_sensor *sensor, u16 address, u8 *value)1349{1350 unsigned char data[2] = { address >> 8, address & 0xff };1351 struct i2c_client *client = sensor->i2c_client;1352 int ret;1353 1354 ret = i2c_master_send(client, data, sizeof(data));1355 if (ret < 0) {1356 dev_dbg(&client->dev, "i2c send error at address %#04x\n",1357 address);1358 return ret;1359 }1360 1361 ret = i2c_master_recv(client, value, 1);1362 if (ret < 0) {1363 dev_dbg(&client->dev, "i2c recv error at address %#04x\n",1364 address);1365 return ret;1366 }1367 1368 return 0;1369}1370 1371static int ov8865_write(struct ov8865_sensor *sensor, u16 address, u8 value)1372{1373 unsigned char data[3] = { address >> 8, address & 0xff, value };1374 struct i2c_client *client = sensor->i2c_client;1375 int ret;1376 1377 ret = i2c_master_send(client, data, sizeof(data));1378 if (ret < 0) {1379 dev_dbg(&client->dev, "i2c send error at address %#04x\n",1380 address);1381 return ret;1382 }1383 1384 return 0;1385}1386 1387static int ov8865_write_sequence(struct ov8865_sensor *sensor,1388 const struct ov8865_register_value *sequence,1389 unsigned int sequence_count)1390{1391 unsigned int i;1392 int ret = 0;1393 1394 for (i = 0; i < sequence_count; i++) {1395 ret = ov8865_write(sensor, sequence[i].address,1396 sequence[i].value);1397 if (ret)1398 break;1399 1400 if (sequence[i].delay_ms)1401 msleep(sequence[i].delay_ms);1402 }1403 1404 return ret;1405}1406 1407static int ov8865_update_bits(struct ov8865_sensor *sensor, u16 address,1408 u8 mask, u8 bits)1409{1410 u8 value = 0;1411 int ret;1412 1413 ret = ov8865_read(sensor, address, &value);1414 if (ret)1415 return ret;1416 1417 value &= ~mask;1418 value |= bits;1419 1420 return ov8865_write(sensor, address, value);1421}1422 1423/* Sensor */1424 1425static int ov8865_sw_reset(struct ov8865_sensor *sensor)1426{1427 return ov8865_write(sensor, OV8865_SW_RESET_REG, OV8865_SW_RESET_RESET);1428}1429 1430static int ov8865_sw_standby(struct ov8865_sensor *sensor, int standby)1431{1432 u8 value = 0;1433 1434 if (!standby)1435 value = OV8865_SW_STANDBY_STREAM_ON;1436 1437 return ov8865_write(sensor, OV8865_SW_STANDBY_REG, value);1438}1439 1440static int ov8865_chip_id_check(struct ov8865_sensor *sensor)1441{1442 u16 regs[] = { OV8865_CHIP_ID_HH_REG, OV8865_CHIP_ID_H_REG,1443 OV8865_CHIP_ID_L_REG };1444 u8 values[] = { OV8865_CHIP_ID_HH_VALUE, OV8865_CHIP_ID_H_VALUE,1445 OV8865_CHIP_ID_L_VALUE };1446 unsigned int i;1447 u8 value;1448 int ret;1449 1450 for (i = 0; i < ARRAY_SIZE(regs); i++) {1451 ret = ov8865_read(sensor, regs[i], &value);1452 if (ret < 0)1453 return ret;1454 1455 if (value != values[i]) {1456 dev_err(sensor->dev,1457 "chip id value mismatch: %#x instead of %#x\n",1458 value, values[i]);1459 return -EINVAL;1460 }1461 }1462 1463 return 0;1464}1465 1466static int ov8865_charge_pump_configure(struct ov8865_sensor *sensor)1467{1468 return ov8865_write(sensor, OV8865_PUMP_CLK_DIV_REG,1469 OV8865_PUMP_CLK_DIV_PUMP_P(1));1470}1471 1472static int ov8865_mipi_configure(struct ov8865_sensor *sensor)1473{1474 struct v4l2_mbus_config_mipi_csi2 *bus_mipi_csi2 =1475 &sensor->endpoint.bus.mipi_csi2;1476 unsigned int lanes_count = bus_mipi_csi2->num_data_lanes;1477 int ret;1478 1479 ret = ov8865_write(sensor, OV8865_MIPI_SC_CTRL0_REG,1480 OV8865_MIPI_SC_CTRL0_LANES(lanes_count) |1481 OV8865_MIPI_SC_CTRL0_MIPI_EN |1482 OV8865_MIPI_SC_CTRL0_UNKNOWN);1483 if (ret)1484 return ret;1485 1486 ret = ov8865_write(sensor, OV8865_MIPI_SC_CTRL2_REG,1487 OV8865_MIPI_SC_CTRL2_PD_MIPI_RST_SYNC);1488 if (ret)1489 return ret;1490 1491 if (lanes_count >= 2) {1492 ret = ov8865_write(sensor, OV8865_MIPI_LANE_SEL01_REG,1493 OV8865_MIPI_LANE_SEL01_LANE0(0) |1494 OV8865_MIPI_LANE_SEL01_LANE1(1));1495 if (ret)1496 return ret;1497 }1498 1499 if (lanes_count >= 4) {1500 ret = ov8865_write(sensor, OV8865_MIPI_LANE_SEL23_REG,1501 OV8865_MIPI_LANE_SEL23_LANE2(2) |1502 OV8865_MIPI_LANE_SEL23_LANE3(3));1503 if (ret)1504 return ret;1505 }1506 1507 ret = ov8865_update_bits(sensor, OV8865_CLK_SEL1_REG,1508 OV8865_CLK_SEL1_MIPI_EOF,1509 OV8865_CLK_SEL1_MIPI_EOF);1510 if (ret)1511 return ret;1512 1513 /*1514 * This value might need to change depending on PCLK rate,1515 * but it's unclear how. This value seems to generally work1516 * while the default value was found to cause transmission errors.1517 */1518 return ov8865_write(sensor, OV8865_MIPI_PCLK_PERIOD_REG, 0x16);1519}1520 1521static int ov8865_black_level_configure(struct ov8865_sensor *sensor)1522{1523 int ret;1524 1525 /* Trigger BLC on relevant events and enable filter. */1526 ret = ov8865_write(sensor, OV8865_BLC_CTRL0_REG,1527 OV8865_BLC_CTRL0_TRIG_RANGE_EN |1528 OV8865_BLC_CTRL0_TRIG_FORMAT_EN |1529 OV8865_BLC_CTRL0_TRIG_GAIN_EN |1530 OV8865_BLC_CTRL0_TRIG_EXPOSURE_EN |1531 OV8865_BLC_CTRL0_FILTER_EN);1532 if (ret)1533 return ret;1534 1535 /* Lower BLC offset trigger threshold. */1536 ret = ov8865_write(sensor, OV8865_BLC_CTRLD_REG,1537 OV8865_BLC_CTRLD_OFFSET_TRIGGER(16));1538 if (ret)1539 return ret;1540 1541 ret = ov8865_write(sensor, OV8865_BLC_CTRL1F_REG, 0);1542 if (ret)1543 return ret;1544 1545 /* Increase BLC offset maximum limit. */1546 return ov8865_write(sensor, OV8865_BLC_OFFSET_LIMIT_REG,1547 OV8865_BLC_OFFSET_LIMIT(63));1548}1549 1550static int ov8865_isp_configure(struct ov8865_sensor *sensor)1551{1552 int ret;1553 1554 /* Disable lens correction. */1555 ret = ov8865_write(sensor, OV8865_ISP_CTRL0_REG,1556 OV8865_ISP_CTRL0_WHITE_BALANCE_EN |1557 OV8865_ISP_CTRL0_DPC_BLACK_EN |1558 OV8865_ISP_CTRL0_DPC_WHITE_EN);1559 if (ret)1560 return ret;1561 1562 return ov8865_write(sensor, OV8865_ISP_CTRL1_REG,1563 OV8865_ISP_CTRL1_BLC_EN);1564}1565 1566static unsigned long ov8865_mode_pll1_rate(struct ov8865_sensor *sensor,1567 const struct ov8865_mode *mode)1568{1569 const struct ov8865_pll1_config *config;1570 unsigned long pll1_rate;1571 1572 config = sensor->pll_configs->pll1_config;1573 pll1_rate = sensor->extclk_rate * config->pll_mul / config->pll_pre_div_half;1574 1575 switch (config->pll_pre_div) {1576 case 0:1577 break;1578 case 1:1579 pll1_rate *= 3;1580 pll1_rate /= 2;1581 break;1582 case 3:1583 pll1_rate *= 5;1584 pll1_rate /= 2;1585 break;1586 case 4:1587 pll1_rate /= 3;1588 break;1589 case 5:1590 pll1_rate /= 4;1591 break;1592 case 7:1593 pll1_rate /= 8;1594 break;1595 default:1596 pll1_rate /= config->pll_pre_div;1597 break;1598 }1599 1600 return pll1_rate;1601}1602 1603static int ov8865_mode_pll1_configure(struct ov8865_sensor *sensor,1604 const struct ov8865_mode *mode,1605 u32 mbus_code)1606{1607 const struct ov8865_pll1_config *config;1608 u8 value;1609 int ret;1610 1611 config = sensor->pll_configs->pll1_config;1612 1613 switch (mbus_code) {1614 case MEDIA_BUS_FMT_SBGGR10_1X10:1615 value = OV8865_MIPI_BIT_SEL(10);1616 break;1617 default:1618 return -EINVAL;1619 }1620 1621 ret = ov8865_write(sensor, OV8865_MIPI_BIT_SEL_REG, value);1622 if (ret)1623 return ret;1624 1625 ret = ov8865_write(sensor, OV8865_PLL_CTRLA_REG,1626 OV8865_PLL_CTRLA_PRE_DIV_HALF(config->pll_pre_div_half));1627 if (ret)1628 return ret;1629 1630 ret = ov8865_write(sensor, OV8865_PLL_CTRL0_REG,1631 OV8865_PLL_CTRL0_PRE_DIV(config->pll_pre_div));1632 if (ret)1633 return ret;1634 1635 ret = ov8865_write(sensor, OV8865_PLL_CTRL1_REG,1636 OV8865_PLL_CTRL1_MUL_H(config->pll_mul));1637 if (ret)1638 return ret;1639 1640 ret = ov8865_write(sensor, OV8865_PLL_CTRL2_REG,1641 OV8865_PLL_CTRL2_MUL_L(config->pll_mul));1642 if (ret)1643 return ret;1644 1645 ret = ov8865_write(sensor, OV8865_PLL_CTRL3_REG,1646 OV8865_PLL_CTRL3_M_DIV(config->m_div));1647 if (ret)1648 return ret;1649 1650 ret = ov8865_write(sensor, OV8865_PLL_CTRL4_REG,1651 OV8865_PLL_CTRL4_MIPI_DIV(config->mipi_div));1652 if (ret)1653 return ret;1654 1655 ret = ov8865_update_bits(sensor, OV8865_PCLK_SEL_REG,1656 OV8865_PCLK_SEL_PCLK_DIV_MASK,1657 OV8865_PCLK_SEL_PCLK_DIV(config->pclk_div));1658 if (ret)1659 return ret;1660 1661 ret = ov8865_write(sensor, OV8865_PLL_CTRL5_REG,1662 OV8865_PLL_CTRL5_SYS_PRE_DIV(config->sys_pre_div));1663 if (ret)1664 return ret;1665 1666 ret = ov8865_write(sensor, OV8865_PLL_CTRL6_REG,1667 OV8865_PLL_CTRL6_SYS_DIV(config->sys_div));1668 if (ret)1669 return ret;1670 1671 return ov8865_update_bits(sensor, OV8865_PLL_CTRL1E_REG,1672 OV8865_PLL_CTRL1E_PLL1_NO_LAT,1673 OV8865_PLL_CTRL1E_PLL1_NO_LAT);1674}1675 1676static int ov8865_mode_pll2_configure(struct ov8865_sensor *sensor,1677 const struct ov8865_mode *mode)1678{1679 const struct ov8865_pll2_config *config;1680 int ret;1681 1682 config = mode->pll2_binning ? sensor->pll_configs->pll2_config_binning :1683 sensor->pll_configs->pll2_config_native;1684 1685 ret = ov8865_write(sensor, OV8865_PLL_CTRL12_REG,1686 OV8865_PLL_CTRL12_PRE_DIV_HALF(config->pll_pre_div_half) |1687 OV8865_PLL_CTRL12_DAC_DIV(config->dac_div));1688 if (ret)1689 return ret;1690 1691 ret = ov8865_write(sensor, OV8865_PLL_CTRLB_REG,1692 OV8865_PLL_CTRLB_PRE_DIV(config->pll_pre_div));1693 if (ret)1694 return ret;1695 1696 ret = ov8865_write(sensor, OV8865_PLL_CTRLC_REG,1697 OV8865_PLL_CTRLC_MUL_H(config->pll_mul));1698 if (ret)1699 return ret;1700 1701 ret = ov8865_write(sensor, OV8865_PLL_CTRLD_REG,1702 OV8865_PLL_CTRLD_MUL_L(config->pll_mul));1703 if (ret)1704 return ret;1705 1706 ret = ov8865_write(sensor, OV8865_PLL_CTRLF_REG,1707 OV8865_PLL_CTRLF_SYS_PRE_DIV(config->sys_pre_div));1708 if (ret)1709 return ret;1710 1711 return ov8865_write(sensor, OV8865_PLL_CTRLE_REG,1712 OV8865_PLL_CTRLE_SYS_DIV(config->sys_div));1713}1714 1715static int ov8865_mode_sclk_configure(struct ov8865_sensor *sensor,1716 const struct ov8865_mode *mode)1717{1718 const struct ov8865_sclk_config *config = &ov8865_sclk_config_native;1719 int ret;1720 1721 ret = ov8865_write(sensor, OV8865_CLK_SEL0_REG,1722 OV8865_CLK_SEL0_PLL1_SYS_SEL(config->sys_sel));1723 if (ret)1724 return ret;1725 1726 ret = ov8865_update_bits(sensor, OV8865_CLK_SEL1_REG,1727 OV8865_CLK_SEL1_PLL_SCLK_SEL_MASK,1728 OV8865_CLK_SEL1_PLL_SCLK_SEL(config->sclk_sel));1729 if (ret)1730 return ret;1731 1732 return ov8865_write(sensor, OV8865_SCLK_CTRL_REG,1733 OV8865_SCLK_CTRL_UNKNOWN |1734 OV8865_SCLK_CTRL_SCLK_DIV(config->sclk_div) |1735 OV8865_SCLK_CTRL_SCLK_PRE_DIV(config->sclk_pre_div));1736}1737 1738static int ov8865_mode_binning_configure(struct ov8865_sensor *sensor,1739 const struct ov8865_mode *mode)1740{1741 unsigned int variopixel_hsub_coef, variopixel_vsub_coef;1742 u8 value;1743 int ret;1744 1745 ret = ov8865_write(sensor, OV8865_FORMAT1_REG, 0);1746 if (ret)1747 return ret;1748 1749 value = OV8865_FORMAT2_HSYNC_EN;1750 1751 if (mode->binning_x)1752 value |= OV8865_FORMAT2_FST_HBIN_EN;1753 1754 if (mode->binning_y)1755 value |= OV8865_FORMAT2_FST_VBIN_EN;1756 1757 if (mode->sync_hbin)1758 value |= OV8865_FORMAT2_SYNC_HBIN_EN;1759 1760 if (mode->horz_var2)1761 value |= OV8865_FORMAT2_ISP_HORZ_VAR2_EN;1762 1763 ret = ov8865_write(sensor, OV8865_FORMAT2_REG, value);1764 if (ret)1765 return ret;1766 1767 ret = ov8865_update_bits(sensor, OV8865_ISP_CTRL2_REG,1768 OV8865_ISP_CTRL2_VARIOPIXEL_EN,1769 mode->variopixel ?1770 OV8865_ISP_CTRL2_VARIOPIXEL_EN : 0);1771 if (ret)1772 return ret;1773 1774 if (mode->variopixel) {1775 /* VarioPixel coefs needs to be > 1. */1776 variopixel_hsub_coef = mode->variopixel_hsub_coef;1777 variopixel_vsub_coef = mode->variopixel_vsub_coef;1778 } else {1779 variopixel_hsub_coef = 1;1780 variopixel_vsub_coef = 1;1781 }1782 1783 ret = ov8865_write(sensor, OV8865_VAP_CTRL1_REG,1784 OV8865_VAP_CTRL1_HSUB_COEF(variopixel_hsub_coef) |1785 OV8865_VAP_CTRL1_VSUB_COEF(variopixel_vsub_coef));1786 if (ret)1787 return ret;1788 1789 ret = ov8865_write(sensor, OV8865_INC_X_ODD_REG,1790 OV8865_INC_X_ODD(mode->inc_x_odd));1791 if (ret)1792 return ret;1793 1794 ret = ov8865_write(sensor, OV8865_INC_X_EVEN_REG,1795 OV8865_INC_X_EVEN(mode->inc_x_even));1796 if (ret)1797 return ret;1798 1799 ret = ov8865_write(sensor, OV8865_INC_Y_ODD_REG,1800 OV8865_INC_Y_ODD(mode->inc_y_odd));1801 if (ret)1802 return ret;1803 1804 return ov8865_write(sensor, OV8865_INC_Y_EVEN_REG,1805 OV8865_INC_Y_EVEN(mode->inc_y_even));1806}1807 1808static int ov8865_mode_black_level_configure(struct ov8865_sensor *sensor,1809 const struct ov8865_mode *mode)1810{1811 int ret;1812 1813 /* Note that a zero value for blc_col_shift_mask is the default 256. */1814 ret = ov8865_write(sensor, OV8865_BLC_CTRL1_REG,1815 mode->blc_col_shift_mask |1816 OV8865_BLC_CTRL1_OFFSET_LIMIT_EN);1817 if (ret)1818 return ret;1819 1820 /* BLC top zero line */1821 1822 ret = ov8865_write(sensor, OV8865_BLC_TOP_ZLINE_START_REG,1823 OV8865_BLC_TOP_ZLINE_START(mode->blc_top_zero_line_start));1824 if (ret)1825 return ret;1826 1827 ret = ov8865_write(sensor, OV8865_BLC_TOP_ZLINE_NUM_REG,1828 OV8865_BLC_TOP_ZLINE_NUM(mode->blc_top_zero_line_num));1829 if (ret)1830 return ret;1831 1832 /* BLC top black line */1833 1834 ret = ov8865_write(sensor, OV8865_BLC_TOP_BLKLINE_START_REG,1835 OV8865_BLC_TOP_BLKLINE_START(mode->blc_top_black_line_start));1836 if (ret)1837 return ret;1838 1839 ret = ov8865_write(sensor, OV8865_BLC_TOP_BLKLINE_NUM_REG,1840 OV8865_BLC_TOP_BLKLINE_NUM(mode->blc_top_black_line_num));1841 if (ret)1842 return ret;1843 1844 /* BLC bottom zero line */1845 1846 ret = ov8865_write(sensor, OV8865_BLC_BOT_ZLINE_START_REG,1847 OV8865_BLC_BOT_ZLINE_START(mode->blc_bottom_zero_line_start));1848 if (ret)1849 return ret;1850 1851 ret = ov8865_write(sensor, OV8865_BLC_BOT_ZLINE_NUM_REG,1852 OV8865_BLC_BOT_ZLINE_NUM(mode->blc_bottom_zero_line_num));1853 if (ret)1854 return ret;1855 1856 /* BLC bottom black line */1857 1858 ret = ov8865_write(sensor, OV8865_BLC_BOT_BLKLINE_START_REG,1859 OV8865_BLC_BOT_BLKLINE_START(mode->blc_bottom_black_line_start));1860 if (ret)1861 return ret;1862 1863 ret = ov8865_write(sensor, OV8865_BLC_BOT_BLKLINE_NUM_REG,1864 OV8865_BLC_BOT_BLKLINE_NUM(mode->blc_bottom_black_line_num));1865 if (ret)1866 return ret;1867 1868 /* BLC anchor */1869 1870 ret = ov8865_write(sensor, OV8865_BLC_ANCHOR_LEFT_START_H_REG,1871 OV8865_BLC_ANCHOR_LEFT_START_H(mode->blc_anchor_left_start));1872 if (ret)1873 return ret;1874 1875 ret = ov8865_write(sensor, OV8865_BLC_ANCHOR_LEFT_START_L_REG,1876 OV8865_BLC_ANCHOR_LEFT_START_L(mode->blc_anchor_left_start));1877 if (ret)1878 return ret;1879 1880 ret = ov8865_write(sensor, OV8865_BLC_ANCHOR_LEFT_END_H_REG,1881 OV8865_BLC_ANCHOR_LEFT_END_H(mode->blc_anchor_left_end));1882 if (ret)1883 return ret;1884 1885 ret = ov8865_write(sensor, OV8865_BLC_ANCHOR_LEFT_END_L_REG,1886 OV8865_BLC_ANCHOR_LEFT_END_L(mode->blc_anchor_left_end));1887 if (ret)1888 return ret;1889 1890 ret = ov8865_write(sensor, OV8865_BLC_ANCHOR_RIGHT_START_H_REG,1891 OV8865_BLC_ANCHOR_RIGHT_START_H(mode->blc_anchor_right_start));1892 if (ret)1893 return ret;1894 1895 ret = ov8865_write(sensor, OV8865_BLC_ANCHOR_RIGHT_START_L_REG,1896 OV8865_BLC_ANCHOR_RIGHT_START_L(mode->blc_anchor_right_start));1897 if (ret)1898 return ret;1899 1900 ret = ov8865_write(sensor, OV8865_BLC_ANCHOR_RIGHT_END_H_REG,1901 OV8865_BLC_ANCHOR_RIGHT_END_H(mode->blc_anchor_right_end));1902 if (ret)1903 return ret;1904 1905 return ov8865_write(sensor, OV8865_BLC_ANCHOR_RIGHT_END_L_REG,1906 OV8865_BLC_ANCHOR_RIGHT_END_L(mode->blc_anchor_right_end));1907}1908 1909static int ov8865_mode_configure(struct ov8865_sensor *sensor,1910 const struct ov8865_mode *mode, u32 mbus_code)1911{1912 int ret;1913 1914 /* Output Size X */1915 1916 ret = ov8865_write(sensor, OV8865_OUTPUT_SIZE_X_H_REG,1917 OV8865_OUTPUT_SIZE_X_H(mode->output_size_x));1918 if (ret)1919 return ret;1920 1921 ret = ov8865_write(sensor, OV8865_OUTPUT_SIZE_X_L_REG,1922 OV8865_OUTPUT_SIZE_X_L(mode->output_size_x));1923 if (ret)1924 return ret;1925 1926 /* Horizontal Total Size */1927 1928 ret = ov8865_write(sensor, OV8865_HTS_H_REG, OV8865_HTS_H(mode->hts));1929 if (ret)1930 return ret;1931 1932 ret = ov8865_write(sensor, OV8865_HTS_L_REG, OV8865_HTS_L(mode->hts));1933 if (ret)1934 return ret;1935 1936 /* Output Size Y */1937 1938 ret = ov8865_write(sensor, OV8865_OUTPUT_SIZE_Y_H_REG,1939 OV8865_OUTPUT_SIZE_Y_H(mode->output_size_y));1940 if (ret)1941 return ret;1942 1943 ret = ov8865_write(sensor, OV8865_OUTPUT_SIZE_Y_L_REG,1944 OV8865_OUTPUT_SIZE_Y_L(mode->output_size_y));1945 if (ret)1946 return ret;1947 1948 /* Vertical Total Size */1949 1950 ret = ov8865_write(sensor, OV8865_VTS_H_REG, OV8865_VTS_H(mode->vts));1951 if (ret)1952 return ret;1953 1954 ret = ov8865_write(sensor, OV8865_VTS_L_REG, OV8865_VTS_L(mode->vts));1955 if (ret)1956 return ret;1957 1958 if (mode->size_auto) {1959 /* Auto Size */1960 1961 ret = ov8865_write(sensor, OV8865_AUTO_SIZE_CTRL_REG,1962 OV8865_AUTO_SIZE_CTRL_OFFSET_Y_REG |1963 OV8865_AUTO_SIZE_CTRL_OFFSET_X_REG |1964 OV8865_AUTO_SIZE_CTRL_CROP_END_Y_REG |1965 OV8865_AUTO_SIZE_CTRL_CROP_END_X_REG |1966 OV8865_AUTO_SIZE_CTRL_CROP_START_Y_REG |1967 OV8865_AUTO_SIZE_CTRL_CROP_START_X_REG);1968 if (ret)1969 return ret;1970 1971 ret = ov8865_write(sensor, OV8865_AUTO_SIZE_BOUNDARIES_REG,1972 OV8865_AUTO_SIZE_BOUNDARIES_Y(mode->size_auto_boundary_y) |1973 OV8865_AUTO_SIZE_BOUNDARIES_X(mode->size_auto_boundary_x));1974 if (ret)1975 return ret;1976 } else {1977 /* Crop Start X */1978 1979 ret = ov8865_write(sensor, OV8865_CROP_START_X_H_REG,1980 OV8865_CROP_START_X_H(mode->crop_start_x));1981 if (ret)1982 return ret;1983 1984 ret = ov8865_write(sensor, OV8865_CROP_START_X_L_REG,1985 OV8865_CROP_START_X_L(mode->crop_start_x));1986 if (ret)1987 return ret;1988 1989 /* Offset X */1990 1991 ret = ov8865_write(sensor, OV8865_OFFSET_X_H_REG,1992 OV8865_OFFSET_X_H(mode->offset_x));1993 if (ret)1994 return ret;1995 1996 ret = ov8865_write(sensor, OV8865_OFFSET_X_L_REG,1997 OV8865_OFFSET_X_L(mode->offset_x));1998 if (ret)1999 return ret;2000 2001 /* Crop End X */2002 2003 ret = ov8865_write(sensor, OV8865_CROP_END_X_H_REG,2004 OV8865_CROP_END_X_H(mode->crop_end_x));2005 if (ret)2006 return ret;2007 2008 ret = ov8865_write(sensor, OV8865_CROP_END_X_L_REG,2009 OV8865_CROP_END_X_L(mode->crop_end_x));2010 if (ret)2011 return ret;2012 2013 /* Crop Start Y */2014 2015 ret = ov8865_write(sensor, OV8865_CROP_START_Y_H_REG,2016 OV8865_CROP_START_Y_H(mode->crop_start_y));2017 if (ret)2018 return ret;2019 2020 ret = ov8865_write(sensor, OV8865_CROP_START_Y_L_REG,2021 OV8865_CROP_START_Y_L(mode->crop_start_y));2022 if (ret)2023 return ret;2024 2025 /* Offset Y */2026 2027 ret = ov8865_write(sensor, OV8865_OFFSET_Y_H_REG,2028 OV8865_OFFSET_Y_H(mode->offset_y));2029 if (ret)2030 return ret;2031 2032 ret = ov8865_write(sensor, OV8865_OFFSET_Y_L_REG,2033 OV8865_OFFSET_Y_L(mode->offset_y));2034 if (ret)2035 return ret;2036 2037 /* Crop End Y */2038 2039 ret = ov8865_write(sensor, OV8865_CROP_END_Y_H_REG,2040 OV8865_CROP_END_Y_H(mode->crop_end_y));2041 if (ret)2042 return ret;2043 2044 ret = ov8865_write(sensor, OV8865_CROP_END_Y_L_REG,2045 OV8865_CROP_END_Y_L(mode->crop_end_y));2046 if (ret)2047 return ret;2048 }2049 2050 /* VFIFO */2051 2052 ret = ov8865_write(sensor, OV8865_VFIFO_READ_START_H_REG,2053 OV8865_VFIFO_READ_START_H(mode->vfifo_read_start));2054 if (ret)2055 return ret;2056 2057 ret = ov8865_write(sensor, OV8865_VFIFO_READ_START_L_REG,2058 OV8865_VFIFO_READ_START_L(mode->vfifo_read_start));2059 if (ret)2060 return ret;2061 2062 ret = ov8865_write(sensor, OV8865_ABLC_NUM_REG,2063 OV8865_ABLC_NUM(mode->ablc_num));2064 if (ret)2065 return ret;2066 2067 ret = ov8865_write(sensor, OV8865_ZLINE_NUM_REG,2068 OV8865_ZLINE_NUM(mode->zline_num));2069 if (ret)2070 return ret;2071 2072 /* Binning */2073 2074 ret = ov8865_mode_binning_configure(sensor, mode);2075 if (ret)2076 return ret;2077 2078 /* Black Level */2079 2080 ret = ov8865_mode_black_level_configure(sensor, mode);2081 if (ret)2082 return ret;2083 2084 /* PLLs */2085 2086 ret = ov8865_mode_pll1_configure(sensor, mode, mbus_code);2087 if (ret)2088 return ret;2089 2090 ret = ov8865_mode_pll2_configure(sensor, mode);2091 if (ret)2092 return ret;2093 2094 ret = ov8865_mode_sclk_configure(sensor, mode);2095 if (ret)2096 return ret;2097 2098 /* Extra registers */2099 2100 if (mode->register_values) {2101 ret = ov8865_write_sequence(sensor, mode->register_values,2102 mode->register_values_count);2103 if (ret)2104 return ret;2105 }2106 2107 return 0;2108}2109 2110static unsigned long ov8865_mode_mipi_clk_rate(struct ov8865_sensor *sensor,2111 const struct ov8865_mode *mode)2112{2113 const struct ov8865_pll1_config *config;2114 unsigned long pll1_rate;2115 2116 config = sensor->pll_configs->pll1_config;2117 2118 pll1_rate = ov8865_mode_pll1_rate(sensor, mode);2119 2120 return pll1_rate / config->m_div / 2;2121}2122 2123/* Exposure */2124 2125static int ov8865_exposure_configure(struct ov8865_sensor *sensor, u32 exposure)2126{2127 int ret;2128 2129 /* The sensor stores exposure in units of 1/16th of a line */2130 exposure *= 16;2131 2132 ret = ov8865_write(sensor, OV8865_EXPOSURE_CTRL_HH_REG,2133 OV8865_EXPOSURE_CTRL_HH(exposure));2134 if (ret)2135 return ret;2136 2137 ret = ov8865_write(sensor, OV8865_EXPOSURE_CTRL_H_REG,2138 OV8865_EXPOSURE_CTRL_H(exposure));2139 if (ret)2140 return ret;2141 2142 return ov8865_write(sensor, OV8865_EXPOSURE_CTRL_L_REG,2143 OV8865_EXPOSURE_CTRL_L(exposure));2144}2145 2146/* Gain */2147 2148static int ov8865_analog_gain_configure(struct ov8865_sensor *sensor, u32 gain)2149{2150 int ret;2151 2152 ret = ov8865_write(sensor, OV8865_GAIN_CTRL_H_REG,2153 OV8865_GAIN_CTRL_H(gain));2154 if (ret)2155 return ret;2156 2157 return ov8865_write(sensor, OV8865_GAIN_CTRL_L_REG,2158 OV8865_GAIN_CTRL_L(gain));2159}2160 2161/* White Balance */2162 2163static int ov8865_red_balance_configure(struct ov8865_sensor *sensor,2164 u32 red_balance)2165{2166 int ret;2167 2168 ret = ov8865_write(sensor, OV8865_ISP_GAIN_RED_H_REG,2169 OV8865_ISP_GAIN_RED_H(red_balance));2170 if (ret)2171 return ret;2172 2173 return ov8865_write(sensor, OV8865_ISP_GAIN_RED_L_REG,2174 OV8865_ISP_GAIN_RED_L(red_balance));2175}2176 2177static int ov8865_blue_balance_configure(struct ov8865_sensor *sensor,2178 u32 blue_balance)2179{2180 int ret;2181 2182 ret = ov8865_write(sensor, OV8865_ISP_GAIN_BLUE_H_REG,2183 OV8865_ISP_GAIN_BLUE_H(blue_balance));2184 if (ret)2185 return ret;2186 2187 return ov8865_write(sensor, OV8865_ISP_GAIN_BLUE_L_REG,2188 OV8865_ISP_GAIN_BLUE_L(blue_balance));2189}2190 2191/* Flip */2192 2193static int ov8865_flip_vert_configure(struct ov8865_sensor *sensor, bool enable)2194{2195 u8 bits = OV8865_FORMAT1_FLIP_VERT_ISP_EN |2196 OV8865_FORMAT1_FLIP_VERT_SENSOR_EN;2197 2198 return ov8865_update_bits(sensor, OV8865_FORMAT1_REG, bits,2199 enable ? bits : 0);2200}2201 2202static int ov8865_flip_horz_configure(struct ov8865_sensor *sensor, bool enable)2203{2204 u8 bits = OV8865_FORMAT2_FLIP_HORZ_ISP_EN |2205 OV8865_FORMAT2_FLIP_HORZ_SENSOR_EN;2206 2207 return ov8865_update_bits(sensor, OV8865_FORMAT2_REG, bits,2208 enable ? bits : 0);2209}2210 2211/* Test Pattern */2212 2213static int ov8865_test_pattern_configure(struct ov8865_sensor *sensor,2214 unsigned int index)2215{2216 if (index >= ARRAY_SIZE(ov8865_test_pattern_bits))2217 return -EINVAL;2218 2219 return ov8865_write(sensor, OV8865_PRE_CTRL0_REG,2220 ov8865_test_pattern_bits[index]);2221}2222 2223/* Blanking */2224 2225static int ov8865_vts_configure(struct ov8865_sensor *sensor, u32 vblank)2226{2227 u16 vts = sensor->state.mode->output_size_y + vblank;2228 int ret;2229 2230 ret = ov8865_write(sensor, OV8865_VTS_H_REG, OV8865_VTS_H(vts));2231 if (ret)2232 return ret;2233 2234 return ov8865_write(sensor, OV8865_VTS_L_REG, OV8865_VTS_L(vts));2235}2236 2237/* State */2238 2239static int ov8865_state_mipi_configure(struct ov8865_sensor *sensor,2240 const struct ov8865_mode *mode,2241 u32 mbus_code)2242{2243 struct ov8865_ctrls *ctrls = &sensor->ctrls;2244 struct v4l2_mbus_config_mipi_csi2 *bus_mipi_csi2 =2245 &sensor->endpoint.bus.mipi_csi2;2246 unsigned long mipi_clk_rate;2247 unsigned int bits_per_sample;2248 unsigned int lanes_count;2249 unsigned int i, j;2250 s64 mipi_pixel_rate;2251 2252 mipi_clk_rate = ov8865_mode_mipi_clk_rate(sensor, mode);2253 if (!mipi_clk_rate)2254 return -EINVAL;2255 2256 for (i = 0; i < ARRAY_SIZE(ov8865_link_freq_menu); i++) {2257 s64 freq = ov8865_link_freq_menu[i];2258 2259 if (freq == mipi_clk_rate)2260 break;2261 }2262 2263 for (j = 0; j < sensor->endpoint.nr_of_link_frequencies; j++) {2264 u64 freq = sensor->endpoint.link_frequencies[j];2265 2266 if (freq == mipi_clk_rate)2267 break;2268 }2269 2270 if (i == ARRAY_SIZE(ov8865_link_freq_menu)) {2271 dev_err(sensor->dev,2272 "failed to find %lu clk rate in link freq\n",2273 mipi_clk_rate);2274 } else if (j == sensor->endpoint.nr_of_link_frequencies) {2275 dev_err(sensor->dev,2276 "failed to find %lu clk rate in endpoint link-frequencies\n",2277 mipi_clk_rate);2278 } else {2279 __v4l2_ctrl_s_ctrl(ctrls->link_freq, i);2280 }2281 2282 switch (mbus_code) {2283 case MEDIA_BUS_FMT_SBGGR10_1X10:2284 bits_per_sample = 10;2285 break;2286 default:2287 return -EINVAL;2288 }2289 2290 lanes_count = bus_mipi_csi2->num_data_lanes;2291 mipi_pixel_rate = mipi_clk_rate * 2 * lanes_count / bits_per_sample;2292 2293 __v4l2_ctrl_s_ctrl_int64(ctrls->pixel_rate, mipi_pixel_rate);2294 2295 return 0;2296}2297 2298static int ov8865_state_configure(struct ov8865_sensor *sensor,2299 const struct ov8865_mode *mode,2300 u32 mbus_code)2301{2302 int ret;2303 2304 if (sensor->state.streaming)2305 return -EBUSY;2306 2307 /* State will be configured at first power on otherwise. */2308 if (pm_runtime_enabled(sensor->dev) &&2309 !pm_runtime_suspended(sensor->dev)) {2310 ret = ov8865_mode_configure(sensor, mode, mbus_code);2311 if (ret)2312 return ret;2313 }2314 2315 ret = ov8865_state_mipi_configure(sensor, mode, mbus_code);2316 if (ret)2317 return ret;2318 2319 sensor->state.mode = mode;2320 sensor->state.mbus_code = mbus_code;2321 2322 return 0;2323}2324 2325static int ov8865_state_init(struct ov8865_sensor *sensor)2326{2327 return ov8865_state_configure(sensor, &ov8865_modes[0],2328 ov8865_mbus_codes[0]);2329}2330 2331/* Sensor Base */2332 2333static int ov8865_sensor_init(struct ov8865_sensor *sensor)2334{2335 int ret;2336 2337 ret = ov8865_sw_reset(sensor);2338 if (ret) {2339 dev_err(sensor->dev, "failed to perform sw reset\n");2340 return ret;2341 }2342 2343 ret = ov8865_sw_standby(sensor, 1);2344 if (ret) {2345 dev_err(sensor->dev, "failed to set sensor standby\n");2346 return ret;2347 }2348 2349 ret = ov8865_chip_id_check(sensor);2350 if (ret) {2351 dev_err(sensor->dev, "failed to check sensor chip id\n");2352 return ret;2353 }2354 2355 ret = ov8865_write_sequence(sensor, ov8865_init_sequence,2356 ARRAY_SIZE(ov8865_init_sequence));2357 if (ret) {2358 dev_err(sensor->dev, "failed to write init sequence\n");2359 return ret;2360 }2361 2362 ret = ov8865_charge_pump_configure(sensor);2363 if (ret) {2364 dev_err(sensor->dev, "failed to configure pad\n");2365 return ret;2366 }2367 2368 ret = ov8865_mipi_configure(sensor);2369 if (ret) {2370 dev_err(sensor->dev, "failed to configure MIPI\n");2371 return ret;2372 }2373 2374 ret = ov8865_isp_configure(sensor);2375 if (ret) {2376 dev_err(sensor->dev, "failed to configure ISP\n");2377 return ret;2378 }2379 2380 ret = ov8865_black_level_configure(sensor);2381 if (ret) {2382 dev_err(sensor->dev, "failed to configure black level\n");2383 return ret;2384 }2385 2386 /* Configure current mode. */2387 ret = ov8865_state_configure(sensor, sensor->state.mode,2388 sensor->state.mbus_code);2389 if (ret) {2390 dev_err(sensor->dev, "failed to configure state\n");2391 return ret;2392 }2393 2394 return 0;2395}2396 2397static int ov8865_sensor_power(struct ov8865_sensor *sensor, bool on)2398{2399 /* Keep initialized to zero for disable label. */2400 int ret = 0;2401 2402 if (on) {2403 gpiod_set_value_cansleep(sensor->reset, 1);2404 gpiod_set_value_cansleep(sensor->powerdown, 1);2405 2406 ret = regulator_enable(sensor->dovdd);2407 if (ret) {2408 dev_err(sensor->dev,2409 "failed to enable DOVDD regulator\n");2410 return ret;2411 }2412 2413 ret = regulator_enable(sensor->avdd);2414 if (ret) {2415 dev_err(sensor->dev,2416 "failed to enable AVDD regulator\n");2417 goto disable_dovdd;2418 }2419 2420 ret = regulator_enable(sensor->dvdd);2421 if (ret) {2422 dev_err(sensor->dev,2423 "failed to enable DVDD regulator\n");2424 goto disable_avdd;2425 }2426 2427 ret = clk_prepare_enable(sensor->extclk);2428 if (ret) {2429 dev_err(sensor->dev, "failed to enable EXTCLK clock\n");2430 goto disable_dvdd;2431 }2432 2433 gpiod_set_value_cansleep(sensor->reset, 0);2434 gpiod_set_value_cansleep(sensor->powerdown, 0);2435 2436 /* Time to enter streaming mode according to power timings. */2437 usleep_range(10000, 12000);2438 } else {2439 gpiod_set_value_cansleep(sensor->powerdown, 1);2440 gpiod_set_value_cansleep(sensor->reset, 1);2441 2442 clk_disable_unprepare(sensor->extclk);2443 2444disable_dvdd:2445 regulator_disable(sensor->dvdd);2446disable_avdd:2447 regulator_disable(sensor->avdd);2448disable_dovdd:2449 regulator_disable(sensor->dovdd);2450 }2451 2452 return ret;2453}2454 2455/* Controls */2456 2457static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl)2458{2459 struct v4l2_subdev *subdev = ov8865_ctrl_subdev(ctrl);2460 struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);2461 unsigned int index;2462 int ret;2463 2464 /* If VBLANK is altered we need to update exposure to compensate */2465 if (ctrl->id == V4L2_CID_VBLANK) {2466 int exposure_max;2467 2468 exposure_max = sensor->state.mode->output_size_y + ctrl->val -2469 OV8865_INTEGRATION_TIME_MARGIN;2470 __v4l2_ctrl_modify_range(sensor->ctrls.exposure,2471 sensor->ctrls.exposure->minimum,2472 exposure_max,2473 sensor->ctrls.exposure->step,2474 min(sensor->ctrls.exposure->val,2475 exposure_max));2476 }2477 2478 /* Wait for the sensor to be on before setting controls. */2479 if (pm_runtime_suspended(sensor->dev))2480 return 0;2481 2482 switch (ctrl->id) {2483 case V4L2_CID_EXPOSURE:2484 ret = ov8865_exposure_configure(sensor, ctrl->val);2485 if (ret)2486 return ret;2487 break;2488 case V4L2_CID_ANALOGUE_GAIN:2489 ret = ov8865_analog_gain_configure(sensor, ctrl->val);2490 if (ret)2491 return ret;2492 break;2493 case V4L2_CID_RED_BALANCE:2494 return ov8865_red_balance_configure(sensor, ctrl->val);2495 case V4L2_CID_BLUE_BALANCE:2496 return ov8865_blue_balance_configure(sensor, ctrl->val);2497 case V4L2_CID_HFLIP:2498 return ov8865_flip_horz_configure(sensor, !!ctrl->val);2499 case V4L2_CID_VFLIP:2500 return ov8865_flip_vert_configure(sensor, !!ctrl->val);2501 case V4L2_CID_TEST_PATTERN:2502 index = (unsigned int)ctrl->val;2503 return ov8865_test_pattern_configure(sensor, index);2504 case V4L2_CID_VBLANK:2505 return ov8865_vts_configure(sensor, ctrl->val);2506 default:2507 return -EINVAL;2508 }2509 2510 return 0;2511}2512 2513static const struct v4l2_ctrl_ops ov8865_ctrl_ops = {2514 .s_ctrl = ov8865_s_ctrl,2515};2516 2517static int ov8865_ctrls_init(struct ov8865_sensor *sensor)2518{2519 struct ov8865_ctrls *ctrls = &sensor->ctrls;2520 struct v4l2_ctrl_handler *handler = &ctrls->handler;2521 const struct v4l2_ctrl_ops *ops = &ov8865_ctrl_ops;2522 const struct ov8865_mode *mode = &ov8865_modes[0];2523 struct v4l2_fwnode_device_properties props;2524 unsigned int vblank_max, vblank_def;2525 unsigned int hblank;2526 int ret;2527 2528 v4l2_ctrl_handler_init(handler, 32);2529 2530 /* Use our mutex for ctrl locking. */2531 handler->lock = &sensor->mutex;2532 2533 /* Exposure */2534 2535 ctrls->exposure = v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 2,2536 65535, 1, 32);2537 2538 /* Gain */2539 2540 v4l2_ctrl_new_std(handler, ops, V4L2_CID_ANALOGUE_GAIN, 128, 2048, 128,2541 128);2542 2543 /* White Balance */2544 2545 v4l2_ctrl_new_std(handler, ops, V4L2_CID_RED_BALANCE, 1, 32767, 1,2546 1024);2547 2548 v4l2_ctrl_new_std(handler, ops, V4L2_CID_BLUE_BALANCE, 1, 32767, 1,2549 1024);2550 2551 /* Flip */2552 2553 v4l2_ctrl_new_std(handler, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);2554 v4l2_ctrl_new_std(handler, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);2555 2556 /* Test Pattern */2557 2558 v4l2_ctrl_new_std_menu_items(handler, ops, V4L2_CID_TEST_PATTERN,2559 ARRAY_SIZE(ov8865_test_pattern_menu) - 1,2560 0, 0, ov8865_test_pattern_menu);2561 2562 /* Blanking */2563 hblank = mode->hts - mode->output_size_x;2564 ctrls->hblank = v4l2_ctrl_new_std(handler, ops, V4L2_CID_HBLANK, hblank,2565 hblank, 1, hblank);2566 2567 if (ctrls->hblank)2568 ctrls->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;2569 2570 vblank_max = OV8865_TIMING_MAX_VTS - mode->output_size_y;2571 vblank_def = mode->vts - mode->output_size_y;2572 ctrls->vblank = v4l2_ctrl_new_std(handler, ops, V4L2_CID_VBLANK,2573 OV8865_TIMING_MIN_VTS, vblank_max, 1,2574 vblank_def);2575 2576 /* MIPI CSI-2 */2577 2578 ctrls->link_freq =2579 v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,2580 ARRAY_SIZE(ov8865_link_freq_menu) - 1,2581 0, ov8865_link_freq_menu);2582 2583 ctrls->pixel_rate =2584 v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 1,2585 INT_MAX, 1, 1);2586 2587 /* set properties from fwnode (e.g. rotation, orientation) */2588 ret = v4l2_fwnode_device_parse(sensor->dev, &props);2589 if (ret)2590 goto error_ctrls;2591 2592 ret = v4l2_ctrl_new_fwnode_properties(handler, ops, &props);2593 if (ret)2594 goto error_ctrls;2595 2596 if (handler->error) {2597 ret = handler->error;2598 goto error_ctrls;2599 }2600 2601 ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;2602 ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;2603 2604 sensor->subdev.ctrl_handler = handler;2605 2606 return 0;2607 2608error_ctrls:2609 v4l2_ctrl_handler_free(handler);2610 2611 return ret;2612}2613 2614/* Subdev Video Operations */2615 2616static int ov8865_s_stream(struct v4l2_subdev *subdev, int enable)2617{2618 struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);2619 struct ov8865_state *state = &sensor->state;2620 int ret;2621 2622 if (enable) {2623 ret = pm_runtime_resume_and_get(sensor->dev);2624 if (ret < 0)2625 return ret;2626 }2627 2628 mutex_lock(&sensor->mutex);2629 ret = ov8865_sw_standby(sensor, !enable);2630 mutex_unlock(&sensor->mutex);2631 2632 if (ret)2633 return ret;2634 2635 state->streaming = !!enable;2636 2637 if (!enable)2638 pm_runtime_put(sensor->dev);2639 2640 return 0;2641}2642 2643static const struct v4l2_subdev_video_ops ov8865_subdev_video_ops = {2644 .s_stream = ov8865_s_stream,2645};2646 2647/* Subdev Pad Operations */2648 2649static int ov8865_enum_mbus_code(struct v4l2_subdev *subdev,2650 struct v4l2_subdev_state *sd_state,2651 struct v4l2_subdev_mbus_code_enum *code_enum)2652{2653 if (code_enum->index >= ARRAY_SIZE(ov8865_mbus_codes))2654 return -EINVAL;2655 2656 code_enum->code = ov8865_mbus_codes[code_enum->index];2657 2658 return 0;2659}2660 2661static void ov8865_mbus_format_fill(struct v4l2_mbus_framefmt *mbus_format,2662 u32 mbus_code,2663 const struct ov8865_mode *mode)2664{2665 mbus_format->width = mode->output_size_x;2666 mbus_format->height = mode->output_size_y;2667 mbus_format->code = mbus_code;2668 2669 mbus_format->field = V4L2_FIELD_NONE;2670 mbus_format->colorspace = V4L2_COLORSPACE_RAW;2671 mbus_format->ycbcr_enc =2672 V4L2_MAP_YCBCR_ENC_DEFAULT(mbus_format->colorspace);2673 mbus_format->quantization = V4L2_QUANTIZATION_FULL_RANGE;2674 mbus_format->xfer_func =2675 V4L2_MAP_XFER_FUNC_DEFAULT(mbus_format->colorspace);2676}2677 2678static int ov8865_get_fmt(struct v4l2_subdev *subdev,2679 struct v4l2_subdev_state *sd_state,2680 struct v4l2_subdev_format *format)2681{2682 struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);2683 struct v4l2_mbus_framefmt *mbus_format = &format->format;2684 2685 mutex_lock(&sensor->mutex);2686 2687 if (format->which == V4L2_SUBDEV_FORMAT_TRY)2688 *mbus_format = *v4l2_subdev_state_get_format(sd_state,2689 format->pad);2690 else2691 ov8865_mbus_format_fill(mbus_format, sensor->state.mbus_code,2692 sensor->state.mode);2693 2694 mutex_unlock(&sensor->mutex);2695 2696 return 0;2697}2698 2699static int ov8865_set_fmt(struct v4l2_subdev *subdev,2700 struct v4l2_subdev_state *sd_state,2701 struct v4l2_subdev_format *format)2702{2703 struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);2704 struct v4l2_mbus_framefmt *mbus_format = &format->format;2705 const struct ov8865_mode *mode;2706 u32 mbus_code = 0;2707 unsigned int hblank;2708 unsigned int index;2709 int exposure_max;2710 int ret = 0;2711 2712 mutex_lock(&sensor->mutex);2713 2714 if (sensor->state.streaming) {2715 ret = -EBUSY;2716 goto complete;2717 }2718 2719 /* Try to find requested mbus code. */2720 for (index = 0; index < ARRAY_SIZE(ov8865_mbus_codes); index++) {2721 if (ov8865_mbus_codes[index] == mbus_format->code) {2722 mbus_code = mbus_format->code;2723 break;2724 }2725 }2726 2727 /* Fallback to default. */2728 if (!mbus_code)2729 mbus_code = ov8865_mbus_codes[0];2730 2731 /* Find the mode with nearest dimensions. */2732 mode = v4l2_find_nearest_size(ov8865_modes, ARRAY_SIZE(ov8865_modes),2733 output_size_x, output_size_y,2734 mbus_format->width, mbus_format->height);2735 if (!mode) {2736 ret = -EINVAL;2737 goto complete;2738 }2739 2740 ov8865_mbus_format_fill(mbus_format, mbus_code, mode);2741 2742 if (format->which == V4L2_SUBDEV_FORMAT_TRY)2743 *v4l2_subdev_state_get_format(sd_state, format->pad) =2744 *mbus_format;2745 else if (sensor->state.mode != mode ||2746 sensor->state.mbus_code != mbus_code)2747 ret = ov8865_state_configure(sensor, mode, mbus_code);2748 2749 __v4l2_ctrl_modify_range(sensor->ctrls.vblank, OV8865_TIMING_MIN_VTS,2750 OV8865_TIMING_MAX_VTS - mode->output_size_y,2751 1, mode->vts - mode->output_size_y);2752 2753 hblank = mode->hts - mode->output_size_x;2754 __v4l2_ctrl_modify_range(sensor->ctrls.hblank, hblank, hblank, 1,2755 hblank);2756 2757 exposure_max = mode->vts - OV8865_INTEGRATION_TIME_MARGIN;2758 __v4l2_ctrl_modify_range(sensor->ctrls.exposure,2759 sensor->ctrls.exposure->minimum, exposure_max,2760 sensor->ctrls.exposure->step,2761 min(sensor->ctrls.exposure->val,2762 exposure_max));2763 2764complete:2765 mutex_unlock(&sensor->mutex);2766 2767 return ret;2768}2769 2770static int ov8865_enum_frame_size(struct v4l2_subdev *subdev,2771 struct v4l2_subdev_state *sd_state,2772 struct v4l2_subdev_frame_size_enum *size_enum)2773{2774 const struct ov8865_mode *mode;2775 2776 if (size_enum->index >= ARRAY_SIZE(ov8865_modes))2777 return -EINVAL;2778 2779 mode = &ov8865_modes[size_enum->index];2780 2781 size_enum->min_width = size_enum->max_width = mode->output_size_x;2782 size_enum->min_height = size_enum->max_height = mode->output_size_y;2783 2784 return 0;2785}2786 2787static void2788__ov8865_get_pad_crop(struct ov8865_sensor *sensor,2789 struct v4l2_subdev_state *state, unsigned int pad,2790 enum v4l2_subdev_format_whence which, struct v4l2_rect *r)2791{2792 const struct ov8865_mode *mode = sensor->state.mode;2793 2794 switch (which) {2795 case V4L2_SUBDEV_FORMAT_TRY:2796 *r = *v4l2_subdev_state_get_crop(state, pad);2797 break;2798 case V4L2_SUBDEV_FORMAT_ACTIVE:2799 r->height = mode->output_size_y;2800 r->width = mode->output_size_x;2801 r->top = (OV8865_NATIVE_HEIGHT - mode->output_size_y) / 2;2802 r->left = (OV8865_NATIVE_WIDTH - mode->output_size_x) / 2;2803 break;2804 }2805}2806 2807static int ov8865_get_selection(struct v4l2_subdev *subdev,2808 struct v4l2_subdev_state *state,2809 struct v4l2_subdev_selection *sel)2810{2811 struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);2812 2813 switch (sel->target) {2814 case V4L2_SEL_TGT_CROP:2815 mutex_lock(&sensor->mutex);2816 __ov8865_get_pad_crop(sensor, state, sel->pad,2817 sel->which, &sel->r);2818 mutex_unlock(&sensor->mutex);2819 break;2820 case V4L2_SEL_TGT_NATIVE_SIZE:2821 sel->r.top = 0;2822 sel->r.left = 0;2823 sel->r.width = OV8865_NATIVE_WIDTH;2824 sel->r.height = OV8865_NATIVE_HEIGHT;2825 break;2826 case V4L2_SEL_TGT_CROP_BOUNDS:2827 case V4L2_SEL_TGT_CROP_DEFAULT:2828 sel->r.top = OV8865_ACTIVE_START_TOP;2829 sel->r.left = OV8865_ACTIVE_START_LEFT;2830 sel->r.width = OV8865_ACTIVE_WIDTH;2831 sel->r.height = OV8865_ACTIVE_HEIGHT;2832 break;2833 default:2834 return -EINVAL;2835 }2836 2837 return 0;2838}2839 2840static int ov8865_get_frame_interval(struct v4l2_subdev *subdev,2841 struct v4l2_subdev_state *sd_state,2842 struct v4l2_subdev_frame_interval *interval)2843{2844 struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);2845 const struct ov8865_mode *mode;2846 unsigned int framesize;2847 unsigned int fps;2848 2849 /*2850 * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L22851 * subdev active state API.2852 */2853 if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE)2854 return -EINVAL;2855 2856 mutex_lock(&sensor->mutex);2857 2858 mode = sensor->state.mode;2859 framesize = mode->hts * (mode->output_size_y +2860 sensor->ctrls.vblank->val);2861 fps = DIV_ROUND_CLOSEST(sensor->ctrls.pixel_rate->val, framesize);2862 2863 interval->interval.numerator = 1;2864 interval->interval.denominator = fps;2865 2866 mutex_unlock(&sensor->mutex);2867 2868 return 0;2869}2870 2871static const struct v4l2_subdev_pad_ops ov8865_subdev_pad_ops = {2872 .enum_mbus_code = ov8865_enum_mbus_code,2873 .get_fmt = ov8865_get_fmt,2874 .set_fmt = ov8865_set_fmt,2875 .enum_frame_size = ov8865_enum_frame_size,2876 .get_selection = ov8865_get_selection,2877 .set_selection = ov8865_get_selection,2878 .get_frame_interval = ov8865_get_frame_interval,2879 .set_frame_interval = ov8865_get_frame_interval,2880};2881 2882static const struct v4l2_subdev_ops ov8865_subdev_ops = {2883 .video = &ov8865_subdev_video_ops,2884 .pad = &ov8865_subdev_pad_ops,2885};2886 2887static int ov8865_suspend(struct device *dev)2888{2889 struct i2c_client *client = to_i2c_client(dev);2890 struct v4l2_subdev *subdev = i2c_get_clientdata(client);2891 struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);2892 struct ov8865_state *state = &sensor->state;2893 int ret = 0;2894 2895 mutex_lock(&sensor->mutex);2896 2897 if (state->streaming) {2898 ret = ov8865_sw_standby(sensor, true);2899 if (ret)2900 goto complete;2901 }2902 2903 ret = ov8865_sensor_power(sensor, false);2904 if (ret)2905 ov8865_sw_standby(sensor, false);2906 2907complete:2908 mutex_unlock(&sensor->mutex);2909 2910 return ret;2911}2912 2913static int ov8865_resume(struct device *dev)2914{2915 struct i2c_client *client = to_i2c_client(dev);2916 struct v4l2_subdev *subdev = i2c_get_clientdata(client);2917 struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);2918 struct ov8865_state *state = &sensor->state;2919 int ret = 0;2920 2921 mutex_lock(&sensor->mutex);2922 2923 ret = ov8865_sensor_power(sensor, true);2924 if (ret)2925 goto complete;2926 2927 ret = ov8865_sensor_init(sensor);2928 if (ret)2929 goto error_power;2930 2931 ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler);2932 if (ret)2933 goto error_power;2934 2935 if (state->streaming) {2936 ret = ov8865_sw_standby(sensor, false);2937 if (ret)2938 goto error_power;2939 }2940 2941 goto complete;2942 2943error_power:2944 ov8865_sensor_power(sensor, false);2945 2946complete:2947 mutex_unlock(&sensor->mutex);2948 2949 return ret;2950}2951 2952static int ov8865_probe(struct i2c_client *client)2953{2954 struct device *dev = &client->dev;2955 struct fwnode_handle *handle;2956 struct ov8865_sensor *sensor;2957 struct v4l2_subdev *subdev;2958 struct media_pad *pad;2959 unsigned int rate = 0;2960 unsigned int i;2961 int ret;2962 2963 sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);2964 if (!sensor)2965 return -ENOMEM;2966 2967 sensor->dev = dev;2968 sensor->i2c_client = client;2969 2970 /* Regulators */2971 2972 /* DVDD: digital core */2973 sensor->dvdd = devm_regulator_get(dev, "dvdd");2974 if (IS_ERR(sensor->dvdd))2975 return dev_err_probe(dev, PTR_ERR(sensor->dvdd),2976 "cannot get DVDD regulator\n");2977 2978 /* DOVDD: digital I/O */2979 sensor->dovdd = devm_regulator_get(dev, "dovdd");2980 if (IS_ERR(sensor->dovdd))2981 return dev_err_probe(dev, PTR_ERR(sensor->dovdd),2982 "cannot get DOVDD regulator\n");2983 2984 /* AVDD: analog */2985 sensor->avdd = devm_regulator_get(dev, "avdd");2986 if (IS_ERR(sensor->avdd))2987 return dev_err_probe(dev, PTR_ERR(sensor->avdd),2988 "cannot get AVDD (analog) regulator\n");2989 2990 /* Graph Endpoint */2991 2992 handle = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);2993 if (!handle)2994 return -EPROBE_DEFER;2995 2996 sensor->endpoint.bus_type = V4L2_MBUS_CSI2_DPHY;2997 2998 ret = v4l2_fwnode_endpoint_alloc_parse(handle, &sensor->endpoint);2999 fwnode_handle_put(handle);3000 if (ret) {3001 dev_err(dev, "failed to parse endpoint node\n");3002 return ret;3003 }3004 3005 /* GPIOs */3006 3007 sensor->powerdown = devm_gpiod_get_optional(dev, "powerdown",3008 GPIOD_OUT_HIGH);3009 if (IS_ERR(sensor->powerdown)) {3010 ret = PTR_ERR(sensor->powerdown);3011 goto error_endpoint;3012 }3013 3014 sensor->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);3015 if (IS_ERR(sensor->reset)) {3016 ret = PTR_ERR(sensor->reset);3017 goto error_endpoint;3018 }3019 3020 /* External Clock */3021 3022 sensor->extclk = devm_clk_get(dev, NULL);3023 if (PTR_ERR(sensor->extclk) == -ENOENT) {3024 dev_info(dev, "no external clock found, continuing...\n");3025 sensor->extclk = NULL;3026 } else if (IS_ERR(sensor->extclk)) {3027 dev_err(dev, "failed to get external clock\n");3028 ret = PTR_ERR(sensor->extclk);3029 goto error_endpoint;3030 }3031 3032 /*3033 * We could have either a 24MHz or 19.2MHz clock rate from either dt or3034 * ACPI...but we also need to support the weird IPU3 case which will3035 * have an external clock AND a clock-frequency property. Check for the3036 * clock-frequency property and if found, set that rate if we managed3037 * to acquire a clock. This should cover the ACPI case. If the system3038 * uses devicetree then the configured rate should already be set, so3039 * we can just read it.3040 */3041 ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",3042 &rate);3043 if (!ret && sensor->extclk) {3044 ret = clk_set_rate(sensor->extclk, rate);3045 if (ret) {3046 dev_err_probe(dev, ret, "failed to set clock rate\n");3047 goto error_endpoint;3048 }3049 } else if (ret && !sensor->extclk) {3050 dev_err_probe(dev, ret, "invalid clock config\n");3051 goto error_endpoint;3052 }3053 3054 sensor->extclk_rate = rate ? rate : clk_get_rate(sensor->extclk);3055 3056 for (i = 0; i < ARRAY_SIZE(supported_extclk_rates); i++) {3057 if (sensor->extclk_rate == supported_extclk_rates[i])3058 break;3059 }3060 3061 if (i == ARRAY_SIZE(supported_extclk_rates)) {3062 dev_err(dev, "clock rate %lu Hz is unsupported\n",3063 sensor->extclk_rate);3064 ret = -EINVAL;3065 goto error_endpoint;3066 }3067 3068 sensor->pll_configs = ov8865_pll_configs[i];3069 3070 /* Subdev, entity and pad */3071 3072 subdev = &sensor->subdev;3073 v4l2_i2c_subdev_init(subdev, client, &ov8865_subdev_ops);3074 3075 subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;3076 subdev->entity.function = MEDIA_ENT_F_CAM_SENSOR;3077 3078 pad = &sensor->pad;3079 pad->flags = MEDIA_PAD_FL_SOURCE;3080 3081 ret = media_entity_pads_init(&subdev->entity, 1, pad);3082 if (ret)3083 goto error_entity;3084 3085 /* Mutex */3086 3087 mutex_init(&sensor->mutex);3088 3089 /* Sensor */3090 3091 ret = ov8865_ctrls_init(sensor);3092 if (ret)3093 goto error_mutex;3094 3095 mutex_lock(&sensor->mutex);3096 ret = ov8865_state_init(sensor);3097 mutex_unlock(&sensor->mutex);3098 if (ret)3099 goto error_ctrls;3100 3101 /* Runtime PM */3102 3103 pm_runtime_set_suspended(sensor->dev);3104 pm_runtime_enable(sensor->dev);3105 3106 /* V4L2 subdev register */3107 3108 ret = v4l2_async_register_subdev_sensor(subdev);3109 if (ret)3110 goto error_pm;3111 3112 return 0;3113 3114error_pm:3115 pm_runtime_disable(sensor->dev);3116 3117error_ctrls:3118 v4l2_ctrl_handler_free(&sensor->ctrls.handler);3119 3120error_mutex:3121 mutex_destroy(&sensor->mutex);3122 3123error_entity:3124 media_entity_cleanup(&sensor->subdev.entity);3125 3126error_endpoint:3127 v4l2_fwnode_endpoint_free(&sensor->endpoint);3128 3129 return ret;3130}3131 3132static void ov8865_remove(struct i2c_client *client)3133{3134 struct v4l2_subdev *subdev = i2c_get_clientdata(client);3135 struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);3136 3137 v4l2_async_unregister_subdev(subdev);3138 pm_runtime_disable(sensor->dev);3139 v4l2_ctrl_handler_free(&sensor->ctrls.handler);3140 mutex_destroy(&sensor->mutex);3141 media_entity_cleanup(&subdev->entity);3142 3143 v4l2_fwnode_endpoint_free(&sensor->endpoint);3144}3145 3146static const struct dev_pm_ops ov8865_pm_ops = {3147 SET_RUNTIME_PM_OPS(ov8865_suspend, ov8865_resume, NULL)3148};3149 3150static const struct acpi_device_id ov8865_acpi_match[] = {3151 {"INT347A"},3152 { }3153};3154MODULE_DEVICE_TABLE(acpi, ov8865_acpi_match);3155 3156static const struct of_device_id ov8865_of_match[] = {3157 { .compatible = "ovti,ov8865" },3158 { }3159};3160MODULE_DEVICE_TABLE(of, ov8865_of_match);3161 3162static struct i2c_driver ov8865_driver = {3163 .driver = {3164 .name = "ov8865",3165 .of_match_table = ov8865_of_match,3166 .acpi_match_table = ov8865_acpi_match,3167 .pm = &ov8865_pm_ops,3168 },3169 .probe = ov8865_probe,3170 .remove = ov8865_remove,3171};3172 3173module_i2c_driver(ov8865_driver);3174 3175MODULE_AUTHOR("Paul Kocialkowski <paul.kocialkowski@bootlin.com>");3176MODULE_DESCRIPTION("V4L2 driver for the OmniVision OV8865 image sensor");3177MODULE_LICENSE("GPL v2");3178