1*247b8b85SWalter Werner Schneider // SPDX-License-Identifier: GPL-2.0 2*247b8b85SWalter Werner Schneider /* 3*247b8b85SWalter Werner Schneider * ov2732 driver 4*247b8b85SWalter Werner Schneider * 5*247b8b85SWalter Werner Schneider * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. 6*247b8b85SWalter Werner Schneider * Copyright (C) 2025-2026 Walter Werner Schneider <contact@schnwalter.eu> 7*247b8b85SWalter Werner Schneider */ 8*247b8b85SWalter Werner Schneider 9*247b8b85SWalter Werner Schneider #include <linux/clk.h> 10*247b8b85SWalter Werner Schneider #include <linux/delay.h> 11*247b8b85SWalter Werner Schneider #include <linux/gpio/consumer.h> 12*247b8b85SWalter Werner Schneider #include <linux/i2c.h> 13*247b8b85SWalter Werner Schneider #include <linux/module.h> 14*247b8b85SWalter Werner Schneider #include <linux/of.h> 15*247b8b85SWalter Werner Schneider #include <linux/pm_runtime.h> 16*247b8b85SWalter Werner Schneider #include <linux/regulator/consumer.h> 17*247b8b85SWalter Werner Schneider #include <media/v4l2-cci.h> 18*247b8b85SWalter Werner Schneider #include <media/v4l2-common.h> 19*247b8b85SWalter Werner Schneider #include <media/v4l2-ctrls.h> 20*247b8b85SWalter Werner Schneider #include <media/v4l2-device.h> 21*247b8b85SWalter Werner Schneider #include <media/v4l2-fwnode.h> 22*247b8b85SWalter Werner Schneider 23*247b8b85SWalter Werner Schneider #define OV2732_LANES 2 24*247b8b85SWalter Werner Schneider #define OV2732_BITS_PER_SAMPLE 10 25*247b8b85SWalter Werner Schneider #define OV2732_LINK_FREQ_DEFAULT 360000000 26*247b8b85SWalter Werner Schneider #define OV2732_XVCLK_FREQ 24000000 27*247b8b85SWalter Werner Schneider #define OV2732_PIXEL_RATE \ 28*247b8b85SWalter Werner Schneider (OV2732_LINK_FREQ_DEFAULT * 2 * OV2732_LANES / OV2732_BITS_PER_SAMPLE) 29*247b8b85SWalter Werner Schneider #define OV2732_NATIVE_WIDTH 1920U 30*247b8b85SWalter Werner Schneider #define OV2732_NATIVE_HEIGHT 1080U 31*247b8b85SWalter Werner Schneider 32*247b8b85SWalter Werner Schneider /* Delay from power up to the first SCCB transaction. */ 33*247b8b85SWalter Werner Schneider #define OV2732_POWER_UP_DELAY_CYCLES 8192 34*247b8b85SWalter Werner Schneider /* Delay from the last SCCB transaction to power down. */ 35*247b8b85SWalter Werner Schneider #define OV2732_POWER_DOWN_DELAY_CYCLES 512 36*247b8b85SWalter Werner Schneider #define OV2732_DELAY_US(cycles) \ 37*247b8b85SWalter Werner Schneider (DIV_ROUND_UP((cycles), OV2732_XVCLK_FREQ / USEC_PER_SEC)) 38*247b8b85SWalter Werner Schneider 39*247b8b85SWalter Werner Schneider #define OV2732_REG_CHIP_ID CCI_REG24(0x300a) 40*247b8b85SWalter Werner Schneider #define OV2732_CHIP_ID 0x002732 41*247b8b85SWalter Werner Schneider 42*247b8b85SWalter Werner Schneider #define OV2732_REG_MODE_SELECT CCI_REG8(0x0100) 43*247b8b85SWalter Werner Schneider #define OV2732_MODE_STANDBY 0x00 44*247b8b85SWalter Werner Schneider #define OV2732_MODE_STREAMING 0x01 45*247b8b85SWalter Werner Schneider 46*247b8b85SWalter Werner Schneider #define OV2732_REG_ANALOGUE_GAIN CCI_REG16(0x3508) 47*247b8b85SWalter Werner Schneider #define OV2732_REG_DIGITAL_GAIN CCI_REG16(0x350a) 48*247b8b85SWalter Werner Schneider #define OV2732_REG_EXPOSURE CCI_REG24(0x3500) 49*247b8b85SWalter Werner Schneider #define OV2732_REG_HTS CCI_REG16(0x380c) 50*247b8b85SWalter Werner Schneider #define OV2732_REG_VTS CCI_REG16(0x380e) 51*247b8b85SWalter Werner Schneider #define OV2732_ANALOGUE_GAIN_MIN 0x80 52*247b8b85SWalter Werner Schneider /* Max analogue gain is documented as 0x3fff, but it overflows after 0x3ff. */ 53*247b8b85SWalter Werner Schneider #define OV2732_ANALOGUE_GAIN_MAX 0x3ff 54*247b8b85SWalter Werner Schneider #define OV2732_ANALOGUE_GAIN_DEFAULT 0x80 55*247b8b85SWalter Werner Schneider #define OV2732_DIGITAL_GAIN_MIN 0x00 56*247b8b85SWalter Werner Schneider #define OV2732_DIGITAL_GAIN_MAX 0x3fff 57*247b8b85SWalter Werner Schneider #define OV2732_DIGITAL_GAIN_DEFAULT 0x0400 58*247b8b85SWalter Werner Schneider #define OV2732_EXPOSURE_DEFAULT 0x40 59*247b8b85SWalter Werner Schneider #define OV2732_EXPOSURE_MIN 0x10 60*247b8b85SWalter Werner Schneider #define OV2732_EXPOSURE_OFFSET 4 61*247b8b85SWalter Werner Schneider #define OV2732_HBLANK_DEFAULT 0x0068 62*247b8b85SWalter Werner Schneider #define OV2732_VTS_MAX 0x7fff 63*247b8b85SWalter Werner Schneider 64*247b8b85SWalter Werner Schneider #define OV2732_REG_TEST_PATTERN CCI_REG8(0x5080) 65*247b8b85SWalter Werner Schneider #define OV2732_TEST_PATTERN_DISABLE 0x00 66*247b8b85SWalter Werner Schneider #define OV2732_TEST_PATTERN_BAR1 0x80 67*247b8b85SWalter Werner Schneider #define OV2732_TEST_PATTERN_BAR2 0x84 68*247b8b85SWalter Werner Schneider #define OV2732_TEST_PATTERN_BAR3 0x88 69*247b8b85SWalter Werner Schneider #define OV2732_TEST_PATTERN_BAR4 0x8c 70*247b8b85SWalter Werner Schneider #define OV2732_TEST_PATTERN_BAR5 0xC0 71*247b8b85SWalter Werner Schneider #define OV2732_TEST_PATTERN_RANDOM 0x81 72*247b8b85SWalter Werner Schneider #define OV2732_TEST_PATTERN_SQUARES_C 0x82 73*247b8b85SWalter Werner Schneider #define OV2732_TEST_PATTERN_SQUARES_BW 0x92 74*247b8b85SWalter Werner Schneider 75*247b8b85SWalter Werner Schneider static const char * const ov2732_supply_names[] = { 76*247b8b85SWalter Werner Schneider "avdd", /* Analog power */ 77*247b8b85SWalter Werner Schneider "dovdd", /* Digital I/O power */ 78*247b8b85SWalter Werner Schneider "dvdd", /* Digital core power */ 79*247b8b85SWalter Werner Schneider }; 80*247b8b85SWalter Werner Schneider 81*247b8b85SWalter Werner Schneider static const struct cci_reg_sequence ov2732_common_regs[] = { 82*247b8b85SWalter Werner Schneider /* PLL control, reset all registers. */ 83*247b8b85SWalter Werner Schneider { CCI_REG8(0x0103), 0x01 }, 84*247b8b85SWalter Werner Schneider 85*247b8b85SWalter Werner Schneider /* Analog control. */ 86*247b8b85SWalter Werner Schneider { CCI_REG8(0x3600), 0x55 }, 87*247b8b85SWalter Werner Schneider { CCI_REG8(0x3601), 0x52 }, 88*247b8b85SWalter Werner Schneider { CCI_REG8(0x3612), 0xb5 }, 89*247b8b85SWalter Werner Schneider { CCI_REG8(0x3613), 0xb3 }, 90*247b8b85SWalter Werner Schneider { CCI_REG8(0x3616), 0x83 }, 91*247b8b85SWalter Werner Schneider { CCI_REG8(0x3621), 0x00 }, 92*247b8b85SWalter Werner Schneider { CCI_REG8(0x3624), 0x06 }, 93*247b8b85SWalter Werner Schneider { CCI_REG8(0x3642), 0x88 }, 94*247b8b85SWalter Werner Schneider { CCI_REG8(0x3660), 0x00 }, 95*247b8b85SWalter Werner Schneider { CCI_REG8(0x3661), 0x00 }, 96*247b8b85SWalter Werner Schneider { CCI_REG8(0x366a), 0x64 }, 97*247b8b85SWalter Werner Schneider { CCI_REG8(0x366c), 0x00 }, 98*247b8b85SWalter Werner Schneider { CCI_REG8(0x366e), 0xff }, 99*247b8b85SWalter Werner Schneider { CCI_REG8(0x366f), 0xff }, 100*247b8b85SWalter Werner Schneider { CCI_REG8(0x3677), 0x11 }, 101*247b8b85SWalter Werner Schneider { CCI_REG8(0x3678), 0x11 }, 102*247b8b85SWalter Werner Schneider { CCI_REG8(0x3679), 0x0c }, 103*247b8b85SWalter Werner Schneider { CCI_REG8(0x3680), 0xff }, 104*247b8b85SWalter Werner Schneider { CCI_REG8(0x3681), 0x16 }, 105*247b8b85SWalter Werner Schneider { CCI_REG8(0x3682), 0x16 }, 106*247b8b85SWalter Werner Schneider { CCI_REG8(0x3683), 0x90 }, 107*247b8b85SWalter Werner Schneider { CCI_REG8(0x3684), 0x90 }, 108*247b8b85SWalter Werner Schneider 109*247b8b85SWalter Werner Schneider /* ADC sync control. */ 110*247b8b85SWalter Werner Schneider { CCI_REG8(0x4503), 0x00 }, 111*247b8b85SWalter Werner Schneider { CCI_REG8(0x4508), 0x14 }, 112*247b8b85SWalter Werner Schneider { CCI_REG8(0x450a), 0x00 }, 113*247b8b85SWalter Werner Schneider { CCI_REG8(0x450b), 0x40 }, 114*247b8b85SWalter Werner Schneider 115*247b8b85SWalter Werner Schneider /* ISP control, enable: WIN, DPC & ISP. */ 116*247b8b85SWalter Werner Schneider { CCI_REG8(0x5000), 0xa1 }, 117*247b8b85SWalter Werner Schneider }; 118*247b8b85SWalter Werner Schneider 119*247b8b85SWalter Werner Schneider struct ov2732_mode { 120*247b8b85SWalter Werner Schneider u32 width; 121*247b8b85SWalter Werner Schneider u32 height; 122*247b8b85SWalter Werner Schneider u32 vts; 123*247b8b85SWalter Werner Schneider }; 124*247b8b85SWalter Werner Schneider 125*247b8b85SWalter Werner Schneider static const struct ov2732_mode supported_modes[] = { 126*247b8b85SWalter Werner Schneider { 127*247b8b85SWalter Werner Schneider .width = 1920, 128*247b8b85SWalter Werner Schneider .height = 1080, 129*247b8b85SWalter Werner Schneider .vts = 1184, 130*247b8b85SWalter Werner Schneider }, 131*247b8b85SWalter Werner Schneider }; 132*247b8b85SWalter Werner Schneider 133*247b8b85SWalter Werner Schneider struct ov2732 { 134*247b8b85SWalter Werner Schneider struct device *dev; 135*247b8b85SWalter Werner Schneider struct regmap *regmap; 136*247b8b85SWalter Werner Schneider 137*247b8b85SWalter Werner Schneider struct media_pad pad; 138*247b8b85SWalter Werner Schneider struct v4l2_subdev sd; 139*247b8b85SWalter Werner Schneider struct v4l2_ctrl_handler ctrl_handler; 140*247b8b85SWalter Werner Schneider struct v4l2_ctrl *hblank; 141*247b8b85SWalter Werner Schneider struct v4l2_ctrl *vblank; 142*247b8b85SWalter Werner Schneider struct v4l2_ctrl *exposure; 143*247b8b85SWalter Werner Schneider 144*247b8b85SWalter Werner Schneider struct clk *xvclk; 145*247b8b85SWalter Werner Schneider u32 xvclk_freq; 146*247b8b85SWalter Werner Schneider struct gpio_desc *powerdown_gpio; 147*247b8b85SWalter Werner Schneider struct gpio_desc *reset_gpio; 148*247b8b85SWalter Werner Schneider struct regulator_bulk_data supplies[ARRAY_SIZE(ov2732_supply_names)]; 149*247b8b85SWalter Werner Schneider }; 150*247b8b85SWalter Werner Schneider 151*247b8b85SWalter Werner Schneider #define to_ov2732(_sd) container_of(_sd, struct ov2732, sd) 152*247b8b85SWalter Werner Schneider 153*247b8b85SWalter Werner Schneider static const s64 link_freq_menu_items[] = { 154*247b8b85SWalter Werner Schneider OV2732_LINK_FREQ_DEFAULT, 155*247b8b85SWalter Werner Schneider }; 156*247b8b85SWalter Werner Schneider 157*247b8b85SWalter Werner Schneider static const char * const ov2732_test_pattern_menu[] = { 158*247b8b85SWalter Werner Schneider "Disabled", 159*247b8b85SWalter Werner Schneider "Vertical Color Bar Type 1", 160*247b8b85SWalter Werner Schneider "Vertical Color Bar Type 2", 161*247b8b85SWalter Werner Schneider "Vertical Color Bar Type 3", 162*247b8b85SWalter Werner Schneider "Vertical Color Bar Type 4", 163*247b8b85SWalter Werner Schneider "Vertical Color Bar Type 5", 164*247b8b85SWalter Werner Schneider "Random", 165*247b8b85SWalter Werner Schneider "Color Squares", 166*247b8b85SWalter Werner Schneider "Black and White Squares", 167*247b8b85SWalter Werner Schneider }; 168*247b8b85SWalter Werner Schneider 169*247b8b85SWalter Werner Schneider static const int ov2732_test_pattern_val[] = { 170*247b8b85SWalter Werner Schneider OV2732_TEST_PATTERN_DISABLE, 171*247b8b85SWalter Werner Schneider OV2732_TEST_PATTERN_BAR1, 172*247b8b85SWalter Werner Schneider OV2732_TEST_PATTERN_BAR2, 173*247b8b85SWalter Werner Schneider OV2732_TEST_PATTERN_BAR3, 174*247b8b85SWalter Werner Schneider OV2732_TEST_PATTERN_BAR4, 175*247b8b85SWalter Werner Schneider OV2732_TEST_PATTERN_BAR5, 176*247b8b85SWalter Werner Schneider OV2732_TEST_PATTERN_RANDOM, 177*247b8b85SWalter Werner Schneider OV2732_TEST_PATTERN_SQUARES_C, 178*247b8b85SWalter Werner Schneider OV2732_TEST_PATTERN_SQUARES_BW, 179*247b8b85SWalter Werner Schneider }; 180*247b8b85SWalter Werner Schneider 181*247b8b85SWalter Werner Schneider static int ov2732_power_on(struct device *dev) 182*247b8b85SWalter Werner Schneider { 183*247b8b85SWalter Werner Schneider struct v4l2_subdev *sd = dev_get_drvdata(dev); 184*247b8b85SWalter Werner Schneider struct ov2732 *ov2732 = to_ov2732(sd); 185*247b8b85SWalter Werner Schneider int ret; 186*247b8b85SWalter Werner Schneider 187*247b8b85SWalter Werner Schneider ret = regulator_bulk_enable(ARRAY_SIZE(ov2732_supply_names), 188*247b8b85SWalter Werner Schneider ov2732->supplies); 189*247b8b85SWalter Werner Schneider if (ret) { 190*247b8b85SWalter Werner Schneider dev_err(dev, "failed to enable regulators\n"); 191*247b8b85SWalter Werner Schneider return ret; 192*247b8b85SWalter Werner Schneider } 193*247b8b85SWalter Werner Schneider 194*247b8b85SWalter Werner Schneider ret = clk_prepare_enable(ov2732->xvclk); 195*247b8b85SWalter Werner Schneider if (ret) { 196*247b8b85SWalter Werner Schneider dev_err(dev, "failed to enable clock\n"); 197*247b8b85SWalter Werner Schneider goto reg_off; 198*247b8b85SWalter Werner Schneider } 199*247b8b85SWalter Werner Schneider 200*247b8b85SWalter Werner Schneider /* Wait 10ms before power up, as per datasheet. */ 201*247b8b85SWalter Werner Schneider fsleep(10 * USEC_PER_MSEC); 202*247b8b85SWalter Werner Schneider 203*247b8b85SWalter Werner Schneider gpiod_set_value_cansleep(ov2732->reset_gpio, 0); 204*247b8b85SWalter Werner Schneider gpiod_set_value_cansleep(ov2732->powerdown_gpio, 0); 205*247b8b85SWalter Werner Schneider 206*247b8b85SWalter Werner Schneider /* Datasheet requires an 8192 cycles wait, but that isn't enough. */ 207*247b8b85SWalter Werner Schneider fsleep(OV2732_DELAY_US(OV2732_POWER_UP_DELAY_CYCLES * 2)); 208*247b8b85SWalter Werner Schneider 209*247b8b85SWalter Werner Schneider return 0; 210*247b8b85SWalter Werner Schneider 211*247b8b85SWalter Werner Schneider reg_off: 212*247b8b85SWalter Werner Schneider regulator_bulk_disable(ARRAY_SIZE(ov2732_supply_names), 213*247b8b85SWalter Werner Schneider ov2732->supplies); 214*247b8b85SWalter Werner Schneider 215*247b8b85SWalter Werner Schneider return ret; 216*247b8b85SWalter Werner Schneider } 217*247b8b85SWalter Werner Schneider 218*247b8b85SWalter Werner Schneider static int ov2732_power_off(struct device *dev) 219*247b8b85SWalter Werner Schneider { 220*247b8b85SWalter Werner Schneider struct v4l2_subdev *sd = dev_get_drvdata(dev); 221*247b8b85SWalter Werner Schneider struct ov2732 *ov2732 = to_ov2732(sd); 222*247b8b85SWalter Werner Schneider 223*247b8b85SWalter Werner Schneider clk_disable_unprepare(ov2732->xvclk); 224*247b8b85SWalter Werner Schneider 225*247b8b85SWalter Werner Schneider /* Wait for 512 cycles as per datasheet. */ 226*247b8b85SWalter Werner Schneider fsleep(OV2732_DELAY_US(OV2732_POWER_DOWN_DELAY_CYCLES)); 227*247b8b85SWalter Werner Schneider 228*247b8b85SWalter Werner Schneider gpiod_set_value_cansleep(ov2732->powerdown_gpio, 1); 229*247b8b85SWalter Werner Schneider gpiod_set_value_cansleep(ov2732->reset_gpio, 1); 230*247b8b85SWalter Werner Schneider 231*247b8b85SWalter Werner Schneider regulator_bulk_disable(ARRAY_SIZE(ov2732_supply_names), 232*247b8b85SWalter Werner Schneider ov2732->supplies); 233*247b8b85SWalter Werner Schneider 234*247b8b85SWalter Werner Schneider return 0; 235*247b8b85SWalter Werner Schneider } 236*247b8b85SWalter Werner Schneider 237*247b8b85SWalter Werner Schneider static int ov2732_identify_chip(struct ov2732 *ov2732) 238*247b8b85SWalter Werner Schneider { 239*247b8b85SWalter Werner Schneider struct i2c_client *client = v4l2_get_subdevdata(&ov2732->sd); 240*247b8b85SWalter Werner Schneider int ret; 241*247b8b85SWalter Werner Schneider u64 val; 242*247b8b85SWalter Werner Schneider 243*247b8b85SWalter Werner Schneider ret = cci_read(ov2732->regmap, OV2732_REG_CHIP_ID, &val, NULL); 244*247b8b85SWalter Werner Schneider if (ret) 245*247b8b85SWalter Werner Schneider return dev_err_probe(&client->dev, ret, 246*247b8b85SWalter Werner Schneider "failed to read chip id\n"); 247*247b8b85SWalter Werner Schneider 248*247b8b85SWalter Werner Schneider if (val != OV2732_CHIP_ID) 249*247b8b85SWalter Werner Schneider return dev_err_probe(&client->dev, -ENODEV, 250*247b8b85SWalter Werner Schneider "chip id mismatch: %x!=%llx\n", 251*247b8b85SWalter Werner Schneider OV2732_CHIP_ID, val); 252*247b8b85SWalter Werner Schneider 253*247b8b85SWalter Werner Schneider return 0; 254*247b8b85SWalter Werner Schneider } 255*247b8b85SWalter Werner Schneider 256*247b8b85SWalter Werner Schneider static int ov2732_enum_mbus_code(struct v4l2_subdev *sd, 257*247b8b85SWalter Werner Schneider struct v4l2_subdev_state *state, 258*247b8b85SWalter Werner Schneider struct v4l2_subdev_mbus_code_enum *code) 259*247b8b85SWalter Werner Schneider { 260*247b8b85SWalter Werner Schneider if (code->index != 0) 261*247b8b85SWalter Werner Schneider return -EINVAL; 262*247b8b85SWalter Werner Schneider 263*247b8b85SWalter Werner Schneider code->code = MEDIA_BUS_FMT_SBGGR10_1X10; 264*247b8b85SWalter Werner Schneider 265*247b8b85SWalter Werner Schneider return 0; 266*247b8b85SWalter Werner Schneider } 267*247b8b85SWalter Werner Schneider 268*247b8b85SWalter Werner Schneider static int ov2732_enum_frame_size(struct v4l2_subdev *sd, 269*247b8b85SWalter Werner Schneider struct v4l2_subdev_state *state, 270*247b8b85SWalter Werner Schneider struct v4l2_subdev_frame_size_enum *fse) 271*247b8b85SWalter Werner Schneider { 272*247b8b85SWalter Werner Schneider if (fse->index >= ARRAY_SIZE(supported_modes)) 273*247b8b85SWalter Werner Schneider return -EINVAL; 274*247b8b85SWalter Werner Schneider 275*247b8b85SWalter Werner Schneider fse->min_width = supported_modes[fse->index].width; 276*247b8b85SWalter Werner Schneider fse->max_width = fse->min_width; 277*247b8b85SWalter Werner Schneider fse->min_height = supported_modes[fse->index].height; 278*247b8b85SWalter Werner Schneider fse->max_height = fse->min_height; 279*247b8b85SWalter Werner Schneider 280*247b8b85SWalter Werner Schneider return 0; 281*247b8b85SWalter Werner Schneider } 282*247b8b85SWalter Werner Schneider 283*247b8b85SWalter Werner Schneider static int ov2732_set_fmt(struct v4l2_subdev *sd, 284*247b8b85SWalter Werner Schneider struct v4l2_subdev_state *state, 285*247b8b85SWalter Werner Schneider struct v4l2_subdev_format *fmt) 286*247b8b85SWalter Werner Schneider { 287*247b8b85SWalter Werner Schneider struct ov2732 *ov2732 = to_ov2732(sd); 288*247b8b85SWalter Werner Schneider const struct ov2732_mode *mode; 289*247b8b85SWalter Werner Schneider s64 vblank_def; 290*247b8b85SWalter Werner Schneider int ret; 291*247b8b85SWalter Werner Schneider 292*247b8b85SWalter Werner Schneider mode = v4l2_find_nearest_size(supported_modes, 293*247b8b85SWalter Werner Schneider ARRAY_SIZE(supported_modes), 294*247b8b85SWalter Werner Schneider width, height, 295*247b8b85SWalter Werner Schneider fmt->format.width, fmt->format.height); 296*247b8b85SWalter Werner Schneider 297*247b8b85SWalter Werner Schneider fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10; 298*247b8b85SWalter Werner Schneider fmt->format.width = mode->width; 299*247b8b85SWalter Werner Schneider fmt->format.height = mode->height; 300*247b8b85SWalter Werner Schneider fmt->format.field = V4L2_FIELD_NONE; 301*247b8b85SWalter Werner Schneider fmt->format.colorspace = V4L2_COLORSPACE_RAW; 302*247b8b85SWalter Werner Schneider fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_601; 303*247b8b85SWalter Werner Schneider fmt->format.quantization = V4L2_QUANTIZATION_FULL_RANGE; 304*247b8b85SWalter Werner Schneider fmt->format.xfer_func = V4L2_XFER_FUNC_NONE; 305*247b8b85SWalter Werner Schneider 306*247b8b85SWalter Werner Schneider *v4l2_subdev_state_get_format(state, fmt->pad) = fmt->format; 307*247b8b85SWalter Werner Schneider 308*247b8b85SWalter Werner Schneider if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) 309*247b8b85SWalter Werner Schneider return 0; 310*247b8b85SWalter Werner Schneider 311*247b8b85SWalter Werner Schneider vblank_def = mode->vts - mode->height; 312*247b8b85SWalter Werner Schneider ret = __v4l2_ctrl_modify_range(ov2732->vblank, vblank_def, 313*247b8b85SWalter Werner Schneider OV2732_VTS_MAX - mode->height, 1, 314*247b8b85SWalter Werner Schneider vblank_def); 315*247b8b85SWalter Werner Schneider 316*247b8b85SWalter Werner Schneider return ret; 317*247b8b85SWalter Werner Schneider } 318*247b8b85SWalter Werner Schneider 319*247b8b85SWalter Werner Schneider static int ov2732_get_selection(struct v4l2_subdev *sd, 320*247b8b85SWalter Werner Schneider struct v4l2_subdev_state *state, 321*247b8b85SWalter Werner Schneider struct v4l2_subdev_selection *sel) 322*247b8b85SWalter Werner Schneider { 323*247b8b85SWalter Werner Schneider switch (sel->target) { 324*247b8b85SWalter Werner Schneider case V4L2_SEL_TGT_CROP: 325*247b8b85SWalter Werner Schneider sel->r = *v4l2_subdev_state_get_crop(state, 0); 326*247b8b85SWalter Werner Schneider return 0; 327*247b8b85SWalter Werner Schneider 328*247b8b85SWalter Werner Schneider case V4L2_SEL_TGT_NATIVE_SIZE: 329*247b8b85SWalter Werner Schneider case V4L2_SEL_TGT_CROP_DEFAULT: 330*247b8b85SWalter Werner Schneider case V4L2_SEL_TGT_CROP_BOUNDS: 331*247b8b85SWalter Werner Schneider sel->r.top = 0; 332*247b8b85SWalter Werner Schneider sel->r.left = 0; 333*247b8b85SWalter Werner Schneider sel->r.width = OV2732_NATIVE_WIDTH; 334*247b8b85SWalter Werner Schneider sel->r.height = OV2732_NATIVE_HEIGHT; 335*247b8b85SWalter Werner Schneider 336*247b8b85SWalter Werner Schneider return 0; 337*247b8b85SWalter Werner Schneider } 338*247b8b85SWalter Werner Schneider 339*247b8b85SWalter Werner Schneider return -EINVAL; 340*247b8b85SWalter Werner Schneider } 341*247b8b85SWalter Werner Schneider 342*247b8b85SWalter Werner Schneider static int ov2732_enable_streams(struct v4l2_subdev *sd, 343*247b8b85SWalter Werner Schneider struct v4l2_subdev_state *state, u32 pad, 344*247b8b85SWalter Werner Schneider u64 streams_mask) 345*247b8b85SWalter Werner Schneider { 346*247b8b85SWalter Werner Schneider struct ov2732 *ov2732 = to_ov2732(sd); 347*247b8b85SWalter Werner Schneider struct i2c_client *client = v4l2_get_subdevdata(&ov2732->sd); 348*247b8b85SWalter Werner Schneider int ret; 349*247b8b85SWalter Werner Schneider 350*247b8b85SWalter Werner Schneider ret = pm_runtime_resume_and_get(&client->dev); 351*247b8b85SWalter Werner Schneider if (ret < 0) 352*247b8b85SWalter Werner Schneider return ret; 353*247b8b85SWalter Werner Schneider 354*247b8b85SWalter Werner Schneider /* Set stream off register for PLL changes. */ 355*247b8b85SWalter Werner Schneider ret = cci_write(ov2732->regmap, OV2732_REG_MODE_SELECT, 356*247b8b85SWalter Werner Schneider OV2732_MODE_STANDBY, NULL); 357*247b8b85SWalter Werner Schneider if (ret) 358*247b8b85SWalter Werner Schneider goto err_put_autosuspend; 359*247b8b85SWalter Werner Schneider 360*247b8b85SWalter Werner Schneider /* Send all registers that are common to all modes */ 361*247b8b85SWalter Werner Schneider ret = cci_multi_reg_write(ov2732->regmap, ov2732_common_regs, 362*247b8b85SWalter Werner Schneider ARRAY_SIZE(ov2732_common_regs), NULL); 363*247b8b85SWalter Werner Schneider if (ret) { 364*247b8b85SWalter Werner Schneider dev_err(&client->dev, "failed to init registers\n"); 365*247b8b85SWalter Werner Schneider goto err_put_autosuspend; 366*247b8b85SWalter Werner Schneider } 367*247b8b85SWalter Werner Schneider 368*247b8b85SWalter Werner Schneider /* Apply customized values from user */ 369*247b8b85SWalter Werner Schneider ret = __v4l2_ctrl_handler_setup(ov2732->sd.ctrl_handler); 370*247b8b85SWalter Werner Schneider if (ret) 371*247b8b85SWalter Werner Schneider goto err_put_autosuspend; 372*247b8b85SWalter Werner Schneider 373*247b8b85SWalter Werner Schneider /* Set stream on register */ 374*247b8b85SWalter Werner Schneider ret = cci_write(ov2732->regmap, OV2732_REG_MODE_SELECT, 375*247b8b85SWalter Werner Schneider OV2732_MODE_STREAMING, NULL); 376*247b8b85SWalter Werner Schneider if (ret) 377*247b8b85SWalter Werner Schneider goto err_put_autosuspend; 378*247b8b85SWalter Werner Schneider 379*247b8b85SWalter Werner Schneider return 0; 380*247b8b85SWalter Werner Schneider 381*247b8b85SWalter Werner Schneider err_put_autosuspend: 382*247b8b85SWalter Werner Schneider pm_runtime_put_autosuspend(&client->dev); 383*247b8b85SWalter Werner Schneider 384*247b8b85SWalter Werner Schneider return ret; 385*247b8b85SWalter Werner Schneider } 386*247b8b85SWalter Werner Schneider 387*247b8b85SWalter Werner Schneider static int ov2732_disable_streams(struct v4l2_subdev *sd, 388*247b8b85SWalter Werner Schneider struct v4l2_subdev_state *state, u32 pad, 389*247b8b85SWalter Werner Schneider u64 streams_mask) 390*247b8b85SWalter Werner Schneider { 391*247b8b85SWalter Werner Schneider struct ov2732 *ov2732 = to_ov2732(sd); 392*247b8b85SWalter Werner Schneider struct i2c_client *client = v4l2_get_subdevdata(&ov2732->sd); 393*247b8b85SWalter Werner Schneider int ret; 394*247b8b85SWalter Werner Schneider 395*247b8b85SWalter Werner Schneider /* set stream off register */ 396*247b8b85SWalter Werner Schneider ret = cci_write(ov2732->regmap, OV2732_REG_MODE_SELECT, 397*247b8b85SWalter Werner Schneider OV2732_MODE_STANDBY, NULL); 398*247b8b85SWalter Werner Schneider if (ret) 399*247b8b85SWalter Werner Schneider dev_err(&client->dev, "%s failed to set stream\n", __func__); 400*247b8b85SWalter Werner Schneider 401*247b8b85SWalter Werner Schneider /* Wait for 512 cycles as per datasheet. */ 402*247b8b85SWalter Werner Schneider fsleep(OV2732_DELAY_US(OV2732_POWER_DOWN_DELAY_CYCLES)); 403*247b8b85SWalter Werner Schneider 404*247b8b85SWalter Werner Schneider pm_runtime_put_autosuspend(&client->dev); 405*247b8b85SWalter Werner Schneider 406*247b8b85SWalter Werner Schneider return ret; 407*247b8b85SWalter Werner Schneider } 408*247b8b85SWalter Werner Schneider 409*247b8b85SWalter Werner Schneider static const struct v4l2_subdev_video_ops ov2732_video_ops = { 410*247b8b85SWalter Werner Schneider .s_stream = v4l2_subdev_s_stream_helper, 411*247b8b85SWalter Werner Schneider }; 412*247b8b85SWalter Werner Schneider 413*247b8b85SWalter Werner Schneider static const struct v4l2_subdev_pad_ops ov2732_pad_ops = { 414*247b8b85SWalter Werner Schneider .enum_mbus_code = ov2732_enum_mbus_code, 415*247b8b85SWalter Werner Schneider .enum_frame_size = ov2732_enum_frame_size, 416*247b8b85SWalter Werner Schneider .get_fmt = v4l2_subdev_get_fmt, 417*247b8b85SWalter Werner Schneider .set_fmt = ov2732_set_fmt, 418*247b8b85SWalter Werner Schneider .get_selection = ov2732_get_selection, 419*247b8b85SWalter Werner Schneider .enable_streams = ov2732_enable_streams, 420*247b8b85SWalter Werner Schneider .disable_streams = ov2732_disable_streams, 421*247b8b85SWalter Werner Schneider }; 422*247b8b85SWalter Werner Schneider 423*247b8b85SWalter Werner Schneider static const struct v4l2_subdev_ops ov2732_subdev_ops = { 424*247b8b85SWalter Werner Schneider .video = &ov2732_video_ops, 425*247b8b85SWalter Werner Schneider .pad = &ov2732_pad_ops, 426*247b8b85SWalter Werner Schneider }; 427*247b8b85SWalter Werner Schneider 428*247b8b85SWalter Werner Schneider static int ov2732_init_state(struct v4l2_subdev *sd, 429*247b8b85SWalter Werner Schneider struct v4l2_subdev_state *sd_state) 430*247b8b85SWalter Werner Schneider { 431*247b8b85SWalter Werner Schneider struct v4l2_subdev_format fmt = { 432*247b8b85SWalter Werner Schneider .which = V4L2_SUBDEV_FORMAT_TRY, 433*247b8b85SWalter Werner Schneider .format = { 434*247b8b85SWalter Werner Schneider .width = 1920, 435*247b8b85SWalter Werner Schneider .height = 1080, 436*247b8b85SWalter Werner Schneider .code = MEDIA_BUS_FMT_SBGGR10_1X10, 437*247b8b85SWalter Werner Schneider .colorspace = V4L2_COLORSPACE_RAW, 438*247b8b85SWalter Werner Schneider .field = V4L2_FIELD_NONE, 439*247b8b85SWalter Werner Schneider .quantization = V4L2_QUANTIZATION_FULL_RANGE, 440*247b8b85SWalter Werner Schneider .xfer_func = V4L2_XFER_FUNC_NONE, 441*247b8b85SWalter Werner Schneider .ycbcr_enc = V4L2_YCBCR_ENC_601, 442*247b8b85SWalter Werner Schneider } 443*247b8b85SWalter Werner Schneider }; 444*247b8b85SWalter Werner Schneider 445*247b8b85SWalter Werner Schneider return ov2732_set_fmt(sd, sd_state, &fmt); 446*247b8b85SWalter Werner Schneider } 447*247b8b85SWalter Werner Schneider 448*247b8b85SWalter Werner Schneider static const struct v4l2_subdev_internal_ops ov2732_internal_ops = { 449*247b8b85SWalter Werner Schneider .init_state = ov2732_init_state, 450*247b8b85SWalter Werner Schneider }; 451*247b8b85SWalter Werner Schneider 452*247b8b85SWalter Werner Schneider static int ov2732_set_ctrl(struct v4l2_ctrl *ctrl) 453*247b8b85SWalter Werner Schneider { 454*247b8b85SWalter Werner Schneider struct ov2732 *ov2732 = 455*247b8b85SWalter Werner Schneider container_of(ctrl->handler, struct ov2732, ctrl_handler); 456*247b8b85SWalter Werner Schneider struct i2c_client *client = v4l2_get_subdevdata(&ov2732->sd); 457*247b8b85SWalter Werner Schneider const struct v4l2_mbus_framefmt *format; 458*247b8b85SWalter Werner Schneider struct v4l2_subdev_state *state; 459*247b8b85SWalter Werner Schneider int ret = 0; 460*247b8b85SWalter Werner Schneider 461*247b8b85SWalter Werner Schneider state = v4l2_subdev_get_locked_active_state(&ov2732->sd); 462*247b8b85SWalter Werner Schneider format = v4l2_subdev_state_get_format(state, 0); 463*247b8b85SWalter Werner Schneider 464*247b8b85SWalter Werner Schneider if (ctrl->id == V4L2_CID_VBLANK) { 465*247b8b85SWalter Werner Schneider int exposure_max, exposure_def; 466*247b8b85SWalter Werner Schneider 467*247b8b85SWalter Werner Schneider exposure_max = format->height + ctrl->val - 468*247b8b85SWalter Werner Schneider OV2732_EXPOSURE_OFFSET; 469*247b8b85SWalter Werner Schneider exposure_def = exposure_max; 470*247b8b85SWalter Werner Schneider ret = __v4l2_ctrl_modify_range(ov2732->exposure, 471*247b8b85SWalter Werner Schneider OV2732_EXPOSURE_MIN, 472*247b8b85SWalter Werner Schneider exposure_max, 473*247b8b85SWalter Werner Schneider ov2732->exposure->step, 474*247b8b85SWalter Werner Schneider exposure_def); 475*247b8b85SWalter Werner Schneider if (ret) 476*247b8b85SWalter Werner Schneider return ret; 477*247b8b85SWalter Werner Schneider } 478*247b8b85SWalter Werner Schneider 479*247b8b85SWalter Werner Schneider if (pm_runtime_get_if_in_use(&client->dev) == 0) 480*247b8b85SWalter Werner Schneider return 0; 481*247b8b85SWalter Werner Schneider 482*247b8b85SWalter Werner Schneider switch (ctrl->id) { 483*247b8b85SWalter Werner Schneider case V4L2_CID_ANALOGUE_GAIN: 484*247b8b85SWalter Werner Schneider cci_write(ov2732->regmap, OV2732_REG_ANALOGUE_GAIN, 485*247b8b85SWalter Werner Schneider ctrl->val, &ret); 486*247b8b85SWalter Werner Schneider break; 487*247b8b85SWalter Werner Schneider case V4L2_CID_DIGITAL_GAIN: 488*247b8b85SWalter Werner Schneider cci_write(ov2732->regmap, OV2732_REG_DIGITAL_GAIN, 489*247b8b85SWalter Werner Schneider ctrl->val, &ret); 490*247b8b85SWalter Werner Schneider break; 491*247b8b85SWalter Werner Schneider case V4L2_CID_EXPOSURE: 492*247b8b85SWalter Werner Schneider /* Lowest 4 bits are fraction bits. */ 493*247b8b85SWalter Werner Schneider cci_write(ov2732->regmap, OV2732_REG_EXPOSURE, 494*247b8b85SWalter Werner Schneider (u32)ctrl->val << 4, &ret); 495*247b8b85SWalter Werner Schneider break; 496*247b8b85SWalter Werner Schneider case V4L2_CID_VBLANK: 497*247b8b85SWalter Werner Schneider cci_write(ov2732->regmap, OV2732_REG_VTS, 498*247b8b85SWalter Werner Schneider format->height + ctrl->val, &ret); 499*247b8b85SWalter Werner Schneider break; 500*247b8b85SWalter Werner Schneider case V4L2_CID_TEST_PATTERN: 501*247b8b85SWalter Werner Schneider cci_write(ov2732->regmap, OV2732_REG_TEST_PATTERN, 502*247b8b85SWalter Werner Schneider ov2732_test_pattern_val[ctrl->val], &ret); 503*247b8b85SWalter Werner Schneider break; 504*247b8b85SWalter Werner Schneider default: 505*247b8b85SWalter Werner Schneider dev_info(&client->dev, 506*247b8b85SWalter Werner Schneider "ctrl(id:0x%x,val:0x%x) is not handled\n", 507*247b8b85SWalter Werner Schneider ctrl->id, ctrl->val); 508*247b8b85SWalter Werner Schneider ret = -EINVAL; 509*247b8b85SWalter Werner Schneider break; 510*247b8b85SWalter Werner Schneider } 511*247b8b85SWalter Werner Schneider 512*247b8b85SWalter Werner Schneider pm_runtime_put(&client->dev); 513*247b8b85SWalter Werner Schneider 514*247b8b85SWalter Werner Schneider return ret; 515*247b8b85SWalter Werner Schneider }; 516*247b8b85SWalter Werner Schneider 517*247b8b85SWalter Werner Schneider static const struct v4l2_ctrl_ops ov2732_ctrl_ops = { 518*247b8b85SWalter Werner Schneider .s_ctrl = ov2732_set_ctrl, 519*247b8b85SWalter Werner Schneider }; 520*247b8b85SWalter Werner Schneider 521*247b8b85SWalter Werner Schneider static int ov2732_init_controls(struct ov2732 *ov2732) 522*247b8b85SWalter Werner Schneider { 523*247b8b85SWalter Werner Schneider const struct ov2732_mode *mode = &supported_modes[0]; 524*247b8b85SWalter Werner Schneider struct v4l2_ctrl_handler *handler; 525*247b8b85SWalter Werner Schneider struct v4l2_ctrl *ctrl; 526*247b8b85SWalter Werner Schneider struct v4l2_fwnode_device_properties props; 527*247b8b85SWalter Werner Schneider s64 exposure_max, vblank_def, vblank_max; 528*247b8b85SWalter Werner Schneider int ret; 529*247b8b85SWalter Werner Schneider 530*247b8b85SWalter Werner Schneider handler = &ov2732->ctrl_handler; 531*247b8b85SWalter Werner Schneider ret = v4l2_ctrl_handler_init(handler, 10); 532*247b8b85SWalter Werner Schneider 533*247b8b85SWalter Werner Schneider v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 534*247b8b85SWalter Werner Schneider OV2732_PIXEL_RATE, OV2732_PIXEL_RATE, 535*247b8b85SWalter Werner Schneider 1, OV2732_PIXEL_RATE); 536*247b8b85SWalter Werner Schneider 537*247b8b85SWalter Werner Schneider ctrl = v4l2_ctrl_new_int_menu(handler, &ov2732_ctrl_ops, 538*247b8b85SWalter Werner Schneider V4L2_CID_LINK_FREQ, 0, 0, 539*247b8b85SWalter Werner Schneider link_freq_menu_items); 540*247b8b85SWalter Werner Schneider if (ctrl) 541*247b8b85SWalter Werner Schneider ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; 542*247b8b85SWalter Werner Schneider 543*247b8b85SWalter Werner Schneider ov2732->hblank = v4l2_ctrl_new_std(handler, &ov2732_ctrl_ops, 544*247b8b85SWalter Werner Schneider V4L2_CID_HBLANK, 545*247b8b85SWalter Werner Schneider OV2732_HBLANK_DEFAULT, 546*247b8b85SWalter Werner Schneider OV2732_HBLANK_DEFAULT, 547*247b8b85SWalter Werner Schneider 1, OV2732_HBLANK_DEFAULT); 548*247b8b85SWalter Werner Schneider if (ov2732->hblank) 549*247b8b85SWalter Werner Schneider ov2732->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; 550*247b8b85SWalter Werner Schneider 551*247b8b85SWalter Werner Schneider vblank_def = mode->vts - mode->height; 552*247b8b85SWalter Werner Schneider vblank_max = OV2732_VTS_MAX - mode->height; 553*247b8b85SWalter Werner Schneider ov2732->vblank = v4l2_ctrl_new_std(handler, &ov2732_ctrl_ops, 554*247b8b85SWalter Werner Schneider V4L2_CID_VBLANK, 555*247b8b85SWalter Werner Schneider vblank_def, vblank_max, 556*247b8b85SWalter Werner Schneider 1, vblank_def); 557*247b8b85SWalter Werner Schneider 558*247b8b85SWalter Werner Schneider exposure_max = mode->vts - OV2732_EXPOSURE_OFFSET; 559*247b8b85SWalter Werner Schneider ov2732->exposure = v4l2_ctrl_new_std(handler, &ov2732_ctrl_ops, 560*247b8b85SWalter Werner Schneider V4L2_CID_EXPOSURE, 561*247b8b85SWalter Werner Schneider OV2732_EXPOSURE_MIN, exposure_max, 562*247b8b85SWalter Werner Schneider 1, OV2732_EXPOSURE_DEFAULT); 563*247b8b85SWalter Werner Schneider 564*247b8b85SWalter Werner Schneider v4l2_ctrl_new_std(handler, &ov2732_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, 565*247b8b85SWalter Werner Schneider OV2732_ANALOGUE_GAIN_MIN, OV2732_ANALOGUE_GAIN_MAX, 566*247b8b85SWalter Werner Schneider 1, OV2732_ANALOGUE_GAIN_DEFAULT); 567*247b8b85SWalter Werner Schneider 568*247b8b85SWalter Werner Schneider v4l2_ctrl_new_std(handler, &ov2732_ctrl_ops, V4L2_CID_DIGITAL_GAIN, 569*247b8b85SWalter Werner Schneider OV2732_DIGITAL_GAIN_MIN, OV2732_DIGITAL_GAIN_MAX, 570*247b8b85SWalter Werner Schneider 1, OV2732_DIGITAL_GAIN_DEFAULT); 571*247b8b85SWalter Werner Schneider 572*247b8b85SWalter Werner Schneider v4l2_ctrl_new_std_menu_items(handler, &ov2732_ctrl_ops, 573*247b8b85SWalter Werner Schneider V4L2_CID_TEST_PATTERN, 574*247b8b85SWalter Werner Schneider ARRAY_SIZE(ov2732_test_pattern_menu) - 1, 575*247b8b85SWalter Werner Schneider 0, 0, ov2732_test_pattern_menu); 576*247b8b85SWalter Werner Schneider 577*247b8b85SWalter Werner Schneider if (handler->error) { 578*247b8b85SWalter Werner Schneider ret = handler->error; 579*247b8b85SWalter Werner Schneider dev_err_probe(ov2732->dev, ret, "Control init failed\n"); 580*247b8b85SWalter Werner Schneider goto err_handler_free; 581*247b8b85SWalter Werner Schneider } 582*247b8b85SWalter Werner Schneider 583*247b8b85SWalter Werner Schneider ret = v4l2_fwnode_device_parse(ov2732->dev, &props); 584*247b8b85SWalter Werner Schneider if (ret) 585*247b8b85SWalter Werner Schneider goto err_handler_free; 586*247b8b85SWalter Werner Schneider 587*247b8b85SWalter Werner Schneider ret = v4l2_ctrl_new_fwnode_properties(handler, &ov2732_ctrl_ops, &props); 588*247b8b85SWalter Werner Schneider if (ret) 589*247b8b85SWalter Werner Schneider goto err_handler_free; 590*247b8b85SWalter Werner Schneider 591*247b8b85SWalter Werner Schneider ov2732->sd.ctrl_handler = handler; 592*247b8b85SWalter Werner Schneider 593*247b8b85SWalter Werner Schneider return 0; 594*247b8b85SWalter Werner Schneider 595*247b8b85SWalter Werner Schneider err_handler_free: 596*247b8b85SWalter Werner Schneider v4l2_ctrl_handler_free(handler); 597*247b8b85SWalter Werner Schneider 598*247b8b85SWalter Werner Schneider return ret; 599*247b8b85SWalter Werner Schneider } 600*247b8b85SWalter Werner Schneider 601*247b8b85SWalter Werner Schneider static int ov2632_probe_dt(struct ov2732 *ov2732) 602*247b8b85SWalter Werner Schneider { 603*247b8b85SWalter Werner Schneider struct fwnode_handle *ep; 604*247b8b85SWalter Werner Schneider struct fwnode_handle *fwnode = dev_fwnode(ov2732->dev); 605*247b8b85SWalter Werner Schneider struct v4l2_fwnode_endpoint bus_cfg = { 606*247b8b85SWalter Werner Schneider .bus_type = V4L2_MBUS_CSI2_DPHY, 607*247b8b85SWalter Werner Schneider }; 608*247b8b85SWalter Werner Schneider int ret; 609*247b8b85SWalter Werner Schneider 610*247b8b85SWalter Werner Schneider ep = fwnode_graph_get_endpoint_by_id(fwnode, 0, 0, 0); 611*247b8b85SWalter Werner Schneider ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); 612*247b8b85SWalter Werner Schneider fwnode_handle_put(ep); 613*247b8b85SWalter Werner Schneider if (ret) { 614*247b8b85SWalter Werner Schneider dev_err_probe(ov2732->dev, -EINVAL, "could not parse endpoint\n"); 615*247b8b85SWalter Werner Schneider goto err_probe_dt; 616*247b8b85SWalter Werner Schneider } 617*247b8b85SWalter Werner Schneider 618*247b8b85SWalter Werner Schneider if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV2732_LANES) { 619*247b8b85SWalter Werner Schneider dev_err(ov2732->dev, "only a 2-lane CSI2 config is supported\n"); 620*247b8b85SWalter Werner Schneider ret = -EINVAL; 621*247b8b85SWalter Werner Schneider } 622*247b8b85SWalter Werner Schneider 623*247b8b85SWalter Werner Schneider err_probe_dt: 624*247b8b85SWalter Werner Schneider v4l2_fwnode_endpoint_free(&bus_cfg); 625*247b8b85SWalter Werner Schneider 626*247b8b85SWalter Werner Schneider return ret; 627*247b8b85SWalter Werner Schneider } 628*247b8b85SWalter Werner Schneider 629*247b8b85SWalter Werner Schneider static int ov2732_get_regulators(struct ov2732 *ov2732) 630*247b8b85SWalter Werner Schneider { 631*247b8b85SWalter Werner Schneider for (unsigned int i = 0; i < ARRAY_SIZE(ov2732_supply_names); i++) 632*247b8b85SWalter Werner Schneider ov2732->supplies[i].supply = ov2732_supply_names[i]; 633*247b8b85SWalter Werner Schneider 634*247b8b85SWalter Werner Schneider return devm_regulator_bulk_get(ov2732->dev, 635*247b8b85SWalter Werner Schneider ARRAY_SIZE(ov2732_supply_names), 636*247b8b85SWalter Werner Schneider ov2732->supplies); 637*247b8b85SWalter Werner Schneider } 638*247b8b85SWalter Werner Schneider 639*247b8b85SWalter Werner Schneider static int ov2732_probe(struct i2c_client *client) 640*247b8b85SWalter Werner Schneider { 641*247b8b85SWalter Werner Schneider struct ov2732 *ov2732; 642*247b8b85SWalter Werner Schneider int ret; 643*247b8b85SWalter Werner Schneider 644*247b8b85SWalter Werner Schneider ov2732 = devm_kzalloc(&client->dev, sizeof(*ov2732), GFP_KERNEL); 645*247b8b85SWalter Werner Schneider if (!ov2732) 646*247b8b85SWalter Werner Schneider return -ENOMEM; 647*247b8b85SWalter Werner Schneider 648*247b8b85SWalter Werner Schneider ov2732->dev = &client->dev; 649*247b8b85SWalter Werner Schneider 650*247b8b85SWalter Werner Schneider ret = ov2632_probe_dt(ov2732); 651*247b8b85SWalter Werner Schneider if (ret) 652*247b8b85SWalter Werner Schneider return ret; 653*247b8b85SWalter Werner Schneider 654*247b8b85SWalter Werner Schneider ov2732->xvclk = devm_v4l2_sensor_clk_get(ov2732->dev, NULL); 655*247b8b85SWalter Werner Schneider if (IS_ERR(ov2732->xvclk)) 656*247b8b85SWalter Werner Schneider return dev_err_probe(ov2732->dev, PTR_ERR(ov2732->xvclk), 657*247b8b85SWalter Werner Schneider "failed to get xvclk\n"); 658*247b8b85SWalter Werner Schneider 659*247b8b85SWalter Werner Schneider ov2732->xvclk_freq = clk_get_rate(ov2732->xvclk); 660*247b8b85SWalter Werner Schneider if (ov2732->xvclk_freq != OV2732_XVCLK_FREQ) 661*247b8b85SWalter Werner Schneider return dev_err_probe(ov2732->dev, -EINVAL, 662*247b8b85SWalter Werner Schneider "xvclk frequency not supported: %dHz\n", 663*247b8b85SWalter Werner Schneider ov2732->xvclk_freq); 664*247b8b85SWalter Werner Schneider 665*247b8b85SWalter Werner Schneider ov2732->powerdown_gpio = devm_gpiod_get_optional(ov2732->dev, 666*247b8b85SWalter Werner Schneider "powerdown", 667*247b8b85SWalter Werner Schneider GPIOD_OUT_HIGH); 668*247b8b85SWalter Werner Schneider 669*247b8b85SWalter Werner Schneider ov2732->reset_gpio = devm_gpiod_get_optional(ov2732->dev, "reset", 670*247b8b85SWalter Werner Schneider GPIOD_OUT_HIGH); 671*247b8b85SWalter Werner Schneider 672*247b8b85SWalter Werner Schneider ov2732->regmap = devm_cci_regmap_init_i2c(client, 16); 673*247b8b85SWalter Werner Schneider if (IS_ERR(ov2732->regmap)) 674*247b8b85SWalter Werner Schneider return dev_err_probe(ov2732->dev, PTR_ERR(ov2732->regmap), 675*247b8b85SWalter Werner Schneider "failed to init CCI\n"); 676*247b8b85SWalter Werner Schneider 677*247b8b85SWalter Werner Schneider ret = ov2732_get_regulators(ov2732); 678*247b8b85SWalter Werner Schneider if (ret) 679*247b8b85SWalter Werner Schneider return dev_err_probe(ov2732->dev, ret, 680*247b8b85SWalter Werner Schneider "failed to get regulators\n"); 681*247b8b85SWalter Werner Schneider 682*247b8b85SWalter Werner Schneider v4l2_i2c_subdev_init(&ov2732->sd, client, &ov2732_subdev_ops); 683*247b8b85SWalter Werner Schneider 684*247b8b85SWalter Werner Schneider /* Device must be powered on for ov2732_identify_chip(). */ 685*247b8b85SWalter Werner Schneider ret = ov2732_power_on(ov2732->dev); 686*247b8b85SWalter Werner Schneider if (ret) 687*247b8b85SWalter Werner Schneider return ret; 688*247b8b85SWalter Werner Schneider 689*247b8b85SWalter Werner Schneider pm_runtime_set_active(ov2732->dev); 690*247b8b85SWalter Werner Schneider pm_runtime_enable(ov2732->dev); 691*247b8b85SWalter Werner Schneider 692*247b8b85SWalter Werner Schneider ret = ov2732_identify_chip(ov2732); 693*247b8b85SWalter Werner Schneider if (ret) 694*247b8b85SWalter Werner Schneider goto err_power_off; 695*247b8b85SWalter Werner Schneider 696*247b8b85SWalter Werner Schneider ret = ov2732_init_controls(ov2732); 697*247b8b85SWalter Werner Schneider if (ret) 698*247b8b85SWalter Werner Schneider goto err_power_off; 699*247b8b85SWalter Werner Schneider 700*247b8b85SWalter Werner Schneider /* Initialize subdev */ 701*247b8b85SWalter Werner Schneider ov2732->sd.internal_ops = &ov2732_internal_ops; 702*247b8b85SWalter Werner Schneider ov2732->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 703*247b8b85SWalter Werner Schneider ov2732->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; 704*247b8b85SWalter Werner Schneider 705*247b8b85SWalter Werner Schneider /* Initialize source pad */ 706*247b8b85SWalter Werner Schneider ov2732->pad.flags = MEDIA_PAD_FL_SOURCE; 707*247b8b85SWalter Werner Schneider 708*247b8b85SWalter Werner Schneider ret = media_entity_pads_init(&ov2732->sd.entity, 1, &ov2732->pad); 709*247b8b85SWalter Werner Schneider if (ret) { 710*247b8b85SWalter Werner Schneider dev_err_probe(ov2732->dev, ret, "failed to init entity pads\n"); 711*247b8b85SWalter Werner Schneider goto error_handler_free; 712*247b8b85SWalter Werner Schneider } 713*247b8b85SWalter Werner Schneider 714*247b8b85SWalter Werner Schneider ov2732->sd.state_lock = ov2732->ctrl_handler.lock; 715*247b8b85SWalter Werner Schneider ret = v4l2_subdev_init_finalize(&ov2732->sd); 716*247b8b85SWalter Werner Schneider if (ret < 0) { 717*247b8b85SWalter Werner Schneider dev_err_probe(ov2732->dev, ret, "subdev init error\n"); 718*247b8b85SWalter Werner Schneider goto err_media_entity; 719*247b8b85SWalter Werner Schneider } 720*247b8b85SWalter Werner Schneider 721*247b8b85SWalter Werner Schneider ret = v4l2_async_register_subdev_sensor(&ov2732->sd); 722*247b8b85SWalter Werner Schneider if (ret < 0) { 723*247b8b85SWalter Werner Schneider dev_err_probe(ov2732->dev, ret, 724*247b8b85SWalter Werner Schneider "failed to register sensor sub-device\n"); 725*247b8b85SWalter Werner Schneider goto err_subdev_cleanup; 726*247b8b85SWalter Werner Schneider } 727*247b8b85SWalter Werner Schneider 728*247b8b85SWalter Werner Schneider pm_runtime_set_autosuspend_delay(ov2732->dev, 1000); 729*247b8b85SWalter Werner Schneider pm_runtime_use_autosuspend(ov2732->dev); 730*247b8b85SWalter Werner Schneider pm_runtime_idle(ov2732->dev); 731*247b8b85SWalter Werner Schneider 732*247b8b85SWalter Werner Schneider return 0; 733*247b8b85SWalter Werner Schneider 734*247b8b85SWalter Werner Schneider err_subdev_cleanup: 735*247b8b85SWalter Werner Schneider v4l2_subdev_cleanup(&ov2732->sd); 736*247b8b85SWalter Werner Schneider 737*247b8b85SWalter Werner Schneider err_media_entity: 738*247b8b85SWalter Werner Schneider media_entity_cleanup(&ov2732->sd.entity); 739*247b8b85SWalter Werner Schneider 740*247b8b85SWalter Werner Schneider error_handler_free: 741*247b8b85SWalter Werner Schneider v4l2_ctrl_handler_free(&ov2732->ctrl_handler); 742*247b8b85SWalter Werner Schneider 743*247b8b85SWalter Werner Schneider err_power_off: 744*247b8b85SWalter Werner Schneider pm_runtime_disable(ov2732->dev); 745*247b8b85SWalter Werner Schneider pm_runtime_set_suspended(ov2732->dev); 746*247b8b85SWalter Werner Schneider ov2732_power_off(ov2732->dev); 747*247b8b85SWalter Werner Schneider 748*247b8b85SWalter Werner Schneider return ret; 749*247b8b85SWalter Werner Schneider } 750*247b8b85SWalter Werner Schneider 751*247b8b85SWalter Werner Schneider static void ov2732_remove(struct i2c_client *client) 752*247b8b85SWalter Werner Schneider { 753*247b8b85SWalter Werner Schneider struct v4l2_subdev *sd = i2c_get_clientdata(client); 754*247b8b85SWalter Werner Schneider struct ov2732 *ov2732 = to_ov2732(sd); 755*247b8b85SWalter Werner Schneider 756*247b8b85SWalter Werner Schneider v4l2_async_unregister_subdev(sd); 757*247b8b85SWalter Werner Schneider v4l2_subdev_cleanup(sd); 758*247b8b85SWalter Werner Schneider media_entity_cleanup(&sd->entity); 759*247b8b85SWalter Werner Schneider v4l2_ctrl_handler_free(&ov2732->ctrl_handler); 760*247b8b85SWalter Werner Schneider 761*247b8b85SWalter Werner Schneider pm_runtime_disable(ov2732->dev); 762*247b8b85SWalter Werner Schneider if (!pm_runtime_status_suspended(ov2732->dev)) { 763*247b8b85SWalter Werner Schneider ov2732_power_off(ov2732->dev); 764*247b8b85SWalter Werner Schneider pm_runtime_set_suspended(ov2732->dev); 765*247b8b85SWalter Werner Schneider } 766*247b8b85SWalter Werner Schneider } 767*247b8b85SWalter Werner Schneider 768*247b8b85SWalter Werner Schneider static const struct of_device_id ov2732_of_match[] = { 769*247b8b85SWalter Werner Schneider { .compatible = "ovti,ov2732", }, 770*247b8b85SWalter Werner Schneider { }, 771*247b8b85SWalter Werner Schneider }; 772*247b8b85SWalter Werner Schneider MODULE_DEVICE_TABLE(of, ov2732_of_match); 773*247b8b85SWalter Werner Schneider 774*247b8b85SWalter Werner Schneider static DEFINE_RUNTIME_DEV_PM_OPS(ov2732_pm_ops, ov2732_power_off, 775*247b8b85SWalter Werner Schneider ov2732_power_on, NULL); 776*247b8b85SWalter Werner Schneider 777*247b8b85SWalter Werner Schneider static struct i2c_driver ov2732_i2c_driver = { 778*247b8b85SWalter Werner Schneider .driver = { 779*247b8b85SWalter Werner Schneider .name = "ov2732", 780*247b8b85SWalter Werner Schneider .of_match_table = ov2732_of_match, 781*247b8b85SWalter Werner Schneider .pm = pm_sleep_ptr(&ov2732_pm_ops), 782*247b8b85SWalter Werner Schneider }, 783*247b8b85SWalter Werner Schneider .probe = ov2732_probe, 784*247b8b85SWalter Werner Schneider .remove = ov2732_remove, 785*247b8b85SWalter Werner Schneider }; 786*247b8b85SWalter Werner Schneider module_i2c_driver(ov2732_i2c_driver); 787*247b8b85SWalter Werner Schneider 788*247b8b85SWalter Werner Schneider MODULE_DESCRIPTION("OmniVision ov2732 sensor driver"); 789*247b8b85SWalter Werner Schneider MODULE_LICENSE("GPL"); 790*247b8b85SWalter Werner Schneider MODULE_AUTHOR("Walter Werner Schneider <contact@schnwalter.eu>"); 791