13ee47cadSRui Miguel Silva // SPDX-License-Identifier: GPL-2.0 23ee47cadSRui Miguel Silva /* 33ee47cadSRui Miguel Silva * Omnivision OV2680 CMOS Image Sensor driver 43ee47cadSRui Miguel Silva * 53ee47cadSRui Miguel Silva * Copyright (C) 2018 Linaro Ltd 63ee47cadSRui Miguel Silva * 73ee47cadSRui Miguel Silva * Based on OV5640 Sensor Driver 83ee47cadSRui Miguel Silva * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. 93ee47cadSRui Miguel Silva * Copyright (C) 2014-2017 Mentor Graphics Inc. 103ee47cadSRui Miguel Silva * 113ee47cadSRui Miguel Silva */ 123ee47cadSRui Miguel Silva 133ee47cadSRui Miguel Silva #include <linux/clk.h> 143ee47cadSRui Miguel Silva #include <linux/delay.h> 153ee47cadSRui Miguel Silva #include <linux/err.h> 169289998eSHans de Goede #include <linux/gpio/consumer.h> 173ee47cadSRui Miguel Silva #include <linux/i2c.h> 183ee47cadSRui Miguel Silva #include <linux/init.h> 197c7e33b7SRob Herring #include <linux/mod_devicetable.h> 203ee47cadSRui Miguel Silva #include <linux/module.h> 21990732a6SHans de Goede #include <linux/pm_runtime.h> 229289998eSHans de Goede #include <linux/regmap.h> 233ee47cadSRui Miguel Silva #include <linux/regulator/consumer.h> 243ee47cadSRui Miguel Silva 259289998eSHans de Goede #include <media/v4l2-cci.h> 263ee47cadSRui Miguel Silva #include <media/v4l2-common.h> 273ee47cadSRui Miguel Silva #include <media/v4l2-ctrls.h> 283ee47cadSRui Miguel Silva #include <media/v4l2-subdev.h> 293ee47cadSRui Miguel Silva 303ee47cadSRui Miguel Silva #define OV2680_CHIP_ID 0x2680 313ee47cadSRui Miguel Silva 329289998eSHans de Goede #define OV2680_REG_STREAM_CTRL CCI_REG8(0x0100) 339289998eSHans de Goede #define OV2680_REG_SOFT_RESET CCI_REG8(0x0103) 343ee47cadSRui Miguel Silva 359289998eSHans de Goede #define OV2680_REG_CHIP_ID CCI_REG16(0x300a) 368e50a122SHans de Goede #define OV2680_REG_PLL_MULTIPLIER CCI_REG16(0x3081) 373ee47cadSRui Miguel Silva 389289998eSHans de Goede #define OV2680_REG_EXPOSURE_PK CCI_REG24(0x3500) 399289998eSHans de Goede #define OV2680_REG_R_MANUAL CCI_REG8(0x3503) 409289998eSHans de Goede #define OV2680_REG_GAIN_PK CCI_REG16(0x350a) 419289998eSHans de Goede #define OV2680_REG_TIMING_HTS CCI_REG16(0x380c) 429289998eSHans de Goede #define OV2680_REG_TIMING_VTS CCI_REG16(0x380e) 439289998eSHans de Goede #define OV2680_REG_FORMAT1 CCI_REG8(0x3820) 449289998eSHans de Goede #define OV2680_REG_FORMAT2 CCI_REG8(0x3821) 453ee47cadSRui Miguel Silva 469289998eSHans de Goede #define OV2680_REG_ISP_CTRL00 CCI_REG8(0x5080) 473ee47cadSRui Miguel Silva 483ee47cadSRui Miguel Silva #define OV2680_FRAME_RATE 30 493ee47cadSRui Miguel Silva 503ee47cadSRui Miguel Silva #define OV2680_WIDTH_MAX 1600 513ee47cadSRui Miguel Silva #define OV2680_HEIGHT_MAX 1200 523ee47cadSRui Miguel Silva 536d6849b2SHans de Goede #define OV2680_DEFAULT_WIDTH 800 546d6849b2SHans de Goede #define OV2680_DEFAULT_HEIGHT 600 556d6849b2SHans de Goede 563ee47cadSRui Miguel Silva enum ov2680_mode_id { 573ee47cadSRui Miguel Silva OV2680_MODE_QUXGA_800_600, 583ee47cadSRui Miguel Silva OV2680_MODE_720P_1280_720, 593ee47cadSRui Miguel Silva OV2680_MODE_UXGA_1600_1200, 603ee47cadSRui Miguel Silva OV2680_MODE_MAX, 613ee47cadSRui Miguel Silva }; 623ee47cadSRui Miguel Silva 633ee47cadSRui Miguel Silva static const char * const ov2680_supply_name[] = { 643ee47cadSRui Miguel Silva "DOVDD", 653ee47cadSRui Miguel Silva "DVDD", 663ee47cadSRui Miguel Silva "AVDD", 673ee47cadSRui Miguel Silva }; 683ee47cadSRui Miguel Silva 693ee47cadSRui Miguel Silva #define OV2680_NUM_SUPPLIES ARRAY_SIZE(ov2680_supply_name) 703ee47cadSRui Miguel Silva 718e50a122SHans de Goede enum { 728e50a122SHans de Goede OV2680_19_2_MHZ, 738e50a122SHans de Goede OV2680_24_MHZ, 748e50a122SHans de Goede }; 758e50a122SHans de Goede 768e50a122SHans de Goede static const unsigned long ov2680_xvclk_freqs[] = { 778e50a122SHans de Goede [OV2680_19_2_MHZ] = 19200000, 788e50a122SHans de Goede [OV2680_24_MHZ] = 24000000, 798e50a122SHans de Goede }; 808e50a122SHans de Goede 818e50a122SHans de Goede static const u8 ov2680_pll_multipliers[] = { 828e50a122SHans de Goede [OV2680_19_2_MHZ] = 69, 838e50a122SHans de Goede [OV2680_24_MHZ] = 55, 848e50a122SHans de Goede }; 858e50a122SHans de Goede 863ee47cadSRui Miguel Silva struct ov2680_mode_info { 873ee47cadSRui Miguel Silva const char *name; 883ee47cadSRui Miguel Silva enum ov2680_mode_id id; 893ee47cadSRui Miguel Silva u32 width; 903ee47cadSRui Miguel Silva u32 height; 919289998eSHans de Goede const struct reg_sequence *reg_data; 923ee47cadSRui Miguel Silva u32 reg_data_size; 933ee47cadSRui Miguel Silva }; 943ee47cadSRui Miguel Silva 953ee47cadSRui Miguel Silva struct ov2680_ctrls { 963ee47cadSRui Miguel Silva struct v4l2_ctrl_handler handler; 973ee47cadSRui Miguel Silva struct v4l2_ctrl *exposure; 983ee47cadSRui Miguel Silva struct v4l2_ctrl *gain; 993ee47cadSRui Miguel Silva struct v4l2_ctrl *hflip; 1003ee47cadSRui Miguel Silva struct v4l2_ctrl *vflip; 1013ee47cadSRui Miguel Silva struct v4l2_ctrl *test_pattern; 1023ee47cadSRui Miguel Silva }; 1033ee47cadSRui Miguel Silva 104*f614dfb8SHans de Goede struct ov2680_mode { 105*f614dfb8SHans de Goede struct v4l2_mbus_framefmt fmt; 106*f614dfb8SHans de Goede struct v4l2_fract frame_interval; 107*f614dfb8SHans de Goede }; 108*f614dfb8SHans de Goede 1093ee47cadSRui Miguel Silva struct ov2680_dev { 1107adfdecbSHans de Goede struct device *dev; 1119289998eSHans de Goede struct regmap *regmap; 1123ee47cadSRui Miguel Silva struct v4l2_subdev sd; 1133ee47cadSRui Miguel Silva 1143ee47cadSRui Miguel Silva struct media_pad pad; 1153ee47cadSRui Miguel Silva struct clk *xvclk; 1163ee47cadSRui Miguel Silva u32 xvclk_freq; 1178e50a122SHans de Goede u8 pll_mult; 1183ee47cadSRui Miguel Silva struct regulator_bulk_data supplies[OV2680_NUM_SUPPLIES]; 1193ee47cadSRui Miguel Silva 120e9305a23SHans de Goede struct gpio_desc *pwdn_gpio; 1213ee47cadSRui Miguel Silva struct mutex lock; /* protect members */ 1223ee47cadSRui Miguel Silva 1233ee47cadSRui Miguel Silva bool is_streaming; 1243ee47cadSRui Miguel Silva 1253ee47cadSRui Miguel Silva struct ov2680_ctrls ctrls; 126*f614dfb8SHans de Goede struct ov2680_mode mode; 1273ee47cadSRui Miguel Silva 1283ee47cadSRui Miguel Silva const struct ov2680_mode_info *current_mode; 1293ee47cadSRui Miguel Silva }; 1303ee47cadSRui Miguel Silva 1313ee47cadSRui Miguel Silva static const char * const test_pattern_menu[] = { 1323ee47cadSRui Miguel Silva "Disabled", 1333ee47cadSRui Miguel Silva "Color Bars", 1343ee47cadSRui Miguel Silva "Random Data", 1353ee47cadSRui Miguel Silva "Square", 1363ee47cadSRui Miguel Silva "Black Image", 1373ee47cadSRui Miguel Silva }; 1383ee47cadSRui Miguel Silva 1393ee47cadSRui Miguel Silva static const int ov2680_hv_flip_bayer_order[] = { 1403ee47cadSRui Miguel Silva MEDIA_BUS_FMT_SBGGR10_1X10, 1413ee47cadSRui Miguel Silva MEDIA_BUS_FMT_SGRBG10_1X10, 1423ee47cadSRui Miguel Silva MEDIA_BUS_FMT_SGBRG10_1X10, 1433ee47cadSRui Miguel Silva MEDIA_BUS_FMT_SRGGB10_1X10, 1443ee47cadSRui Miguel Silva }; 1453ee47cadSRui Miguel Silva 1469289998eSHans de Goede static const struct reg_sequence ov2680_setting_30fps_QUXGA_800_600[] = { 1470a61cf33SHans de Goede /* Set PLL SP DIV to 1 for binning mode */ 1480a61cf33SHans de Goede {0x3086, 0x01}, 1490a61cf33SHans de Goede 1500a61cf33SHans de Goede /* Sensor control register 0x0a to 0x23 for binning mode */ 1510a61cf33SHans de Goede {0x370a, 0x23}, 1520a61cf33SHans de Goede 1530a61cf33SHans de Goede /* Set X and Y output size to 800x600 */ 1540a61cf33SHans de Goede {0x3808, 0x03}, 1550a61cf33SHans de Goede {0x3809, 0x20}, 1560a61cf33SHans de Goede {0x380a, 0x02}, 1570a61cf33SHans de Goede {0x380b, 0x58}, 1580a61cf33SHans de Goede 1590a61cf33SHans de Goede /* Set HTS + VTS to 1708x644 */ 1600a61cf33SHans de Goede {0x380c, 0x06}, 1610a61cf33SHans de Goede {0x380d, 0xac}, 1620a61cf33SHans de Goede {0x380e, 0x02}, 1630a61cf33SHans de Goede {0x380f, 0x84}, 1640a61cf33SHans de Goede 1650a61cf33SHans de Goede /* Set ISP WIN X and Y start to 4x4 */ 1660a61cf33SHans de Goede {0x3811, 0x04}, 1670a61cf33SHans de Goede {0x3813, 0x04}, 1680a61cf33SHans de Goede 1690a61cf33SHans de Goede /* Set X INC and Y INC for binning */ 1700a61cf33SHans de Goede {0x3814, 0x31}, 1710a61cf33SHans de Goede {0x3815, 0x31}, 1720a61cf33SHans de Goede 1730a61cf33SHans de Goede /* Initialize FORMAT1 to default/reset value (vflip disabled) */ 1740a61cf33SHans de Goede {0x3820, 0xc0}, 1750a61cf33SHans de Goede 1760a61cf33SHans de Goede /* Set black level compensation range to 0 - 3 (default 0 - 11) */ 1770a61cf33SHans de Goede {0x4008, 0x00}, 1780a61cf33SHans de Goede {0x4009, 0x03}, 1790a61cf33SHans de Goede 1800a61cf33SHans de Goede /* Set MIPI pclk period to 0x1e (default/reset is 0x18) */ 1810a61cf33SHans de Goede {0x4837, 0x1e}, 1820a61cf33SHans de Goede 1830a61cf33SHans de Goede /* Initialize exposure to 0x4ee (overridden by the ctrl, drop this */ 1840a61cf33SHans de Goede {0x3501, 0x4e}, 1850a61cf33SHans de Goede {0x3502, 0xe0}, 1860a61cf33SHans de Goede 1870a61cf33SHans de Goede /* R MANUAL set exposure and gain to manual (hw does not do auto) */ 1887b5a42e6SHans de Goede {0x3503, 0x03}, 1893ee47cadSRui Miguel Silva }; 1903ee47cadSRui Miguel Silva 1919289998eSHans de Goede static const struct reg_sequence ov2680_setting_30fps_720P_1280_720[] = { 1920a61cf33SHans de Goede /* Set PLL SP DIV to 0 for not binning mode */ 1930a61cf33SHans de Goede {0x3086, 0x00}, 1940a61cf33SHans de Goede 1950a61cf33SHans de Goede /* Set X and Y output size to 1280x720 */ 1960a61cf33SHans de Goede {0x3808, 0x05}, 1970a61cf33SHans de Goede {0x3809, 0x00}, 1980a61cf33SHans de Goede {0x380a, 0x02}, 1990a61cf33SHans de Goede {0x380b, 0xd0}, 2000a61cf33SHans de Goede 2010a61cf33SHans de Goede /* Set HTS + VTS to 1704x1294 */ 2020a61cf33SHans de Goede {0x380c, 0x06}, 2030a61cf33SHans de Goede {0x380d, 0xa8}, 2040a61cf33SHans de Goede {0x380e, 0x05}, 2050a61cf33SHans de Goede {0x380f, 0x0e}, 2060a61cf33SHans de Goede 2070a61cf33SHans de Goede /* Set ISP WIN X and Y start to 8x6 */ 2080a61cf33SHans de Goede {0x3811, 0x08}, 2090a61cf33SHans de Goede {0x3813, 0x06}, 2100a61cf33SHans de Goede 2110a61cf33SHans de Goede /* Set X INC and Y INC for non binning */ 2120a61cf33SHans de Goede {0x3814, 0x11}, 2130a61cf33SHans de Goede {0x3815, 0x11}, 2140a61cf33SHans de Goede 2150a61cf33SHans de Goede /* Initialize FORMAT1 to default/reset value (vflip disabled) */ 2160a61cf33SHans de Goede {0x3820, 0xc0}, 2170a61cf33SHans de Goede 2180a61cf33SHans de Goede /* Set backlight compensation range start to 0 */ 2190a61cf33SHans de Goede {0x4008, 0x00}, 2203ee47cadSRui Miguel Silva }; 2213ee47cadSRui Miguel Silva 2229289998eSHans de Goede static const struct reg_sequence ov2680_setting_30fps_UXGA_1600_1200[] = { 2230a61cf33SHans de Goede /* Set PLL SP DIV to 0 for not binning mode */ 2240a61cf33SHans de Goede {0x3086, 0x00}, 2250a61cf33SHans de Goede 2260a61cf33SHans de Goede /* Initialize exposure to 0x4ee (overridden by the ctrl, drop this */ 2270a61cf33SHans de Goede {0x3501, 0x4e}, 2280a61cf33SHans de Goede {0x3502, 0xe0}, 2290a61cf33SHans de Goede 2300a61cf33SHans de Goede /* Set X and Y output size to 1600x1200 */ 2310a61cf33SHans de Goede {0x3808, 0x06}, 2320a61cf33SHans de Goede {0x3809, 0x40}, 2330a61cf33SHans de Goede {0x380a, 0x04}, 2340a61cf33SHans de Goede {0x380b, 0xb0}, 2350a61cf33SHans de Goede 2360a61cf33SHans de Goede /* Set HTS + VTS to 1704x1294 */ 2370a61cf33SHans de Goede {0x380c, 0x06}, 2380a61cf33SHans de Goede {0x380d, 0xa8}, 2390a61cf33SHans de Goede {0x380e, 0x05}, 2400a61cf33SHans de Goede {0x380f, 0x0e}, 2410a61cf33SHans de Goede 2420a61cf33SHans de Goede /* Set ISP WIN X and Y start to 0x0 */ 2430a61cf33SHans de Goede {0x3811, 0x00}, 2440a61cf33SHans de Goede {0x3813, 0x00}, 2450a61cf33SHans de Goede 2460a61cf33SHans de Goede /* Set X INC and Y INC for non binning */ 2470a61cf33SHans de Goede {0x3814, 0x11}, 2480a61cf33SHans de Goede {0x3815, 0x11}, 2490a61cf33SHans de Goede 2500a61cf33SHans de Goede /* Initialize FORMAT1 to default/reset value (vflip disabled) */ 2510a61cf33SHans de Goede {0x3820, 0xc0}, 2520a61cf33SHans de Goede 2530a61cf33SHans de Goede /* Set backlight compensation range start to 0 */ 2540a61cf33SHans de Goede {0x4008, 0x00}, 2550a61cf33SHans de Goede 2560a61cf33SHans de Goede /* Set MIPI pclk period to default/reset value of 0x18 */ 2570a61cf33SHans de Goede {0x4837, 0x18} 2583ee47cadSRui Miguel Silva }; 2593ee47cadSRui Miguel Silva 2603ee47cadSRui Miguel Silva static const struct ov2680_mode_info ov2680_mode_init_data = { 2613ee47cadSRui Miguel Silva "mode_quxga_800_600", OV2680_MODE_QUXGA_800_600, 800, 600, 2623ee47cadSRui Miguel Silva ov2680_setting_30fps_QUXGA_800_600, 2633ee47cadSRui Miguel Silva ARRAY_SIZE(ov2680_setting_30fps_QUXGA_800_600), 2643ee47cadSRui Miguel Silva }; 2653ee47cadSRui Miguel Silva 2663ee47cadSRui Miguel Silva static const struct ov2680_mode_info ov2680_mode_data[OV2680_MODE_MAX] = { 2673ee47cadSRui Miguel Silva {"mode_quxga_800_600", OV2680_MODE_QUXGA_800_600, 2683ee47cadSRui Miguel Silva 800, 600, ov2680_setting_30fps_QUXGA_800_600, 2693ee47cadSRui Miguel Silva ARRAY_SIZE(ov2680_setting_30fps_QUXGA_800_600)}, 2703ee47cadSRui Miguel Silva {"mode_720p_1280_720", OV2680_MODE_720P_1280_720, 2713ee47cadSRui Miguel Silva 1280, 720, ov2680_setting_30fps_720P_1280_720, 2723ee47cadSRui Miguel Silva ARRAY_SIZE(ov2680_setting_30fps_720P_1280_720)}, 2733ee47cadSRui Miguel Silva {"mode_uxga_1600_1200", OV2680_MODE_UXGA_1600_1200, 2743ee47cadSRui Miguel Silva 1600, 1200, ov2680_setting_30fps_UXGA_1600_1200, 2753ee47cadSRui Miguel Silva ARRAY_SIZE(ov2680_setting_30fps_UXGA_1600_1200)}, 2763ee47cadSRui Miguel Silva }; 2773ee47cadSRui Miguel Silva 2783ee47cadSRui Miguel Silva static struct ov2680_dev *to_ov2680_dev(struct v4l2_subdev *sd) 2793ee47cadSRui Miguel Silva { 2803ee47cadSRui Miguel Silva return container_of(sd, struct ov2680_dev, sd); 2813ee47cadSRui Miguel Silva } 2823ee47cadSRui Miguel Silva 2833ee47cadSRui Miguel Silva static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) 2843ee47cadSRui Miguel Silva { 2853ee47cadSRui Miguel Silva return &container_of(ctrl->handler, struct ov2680_dev, 2863ee47cadSRui Miguel Silva ctrls.handler)->sd; 2873ee47cadSRui Miguel Silva } 2883ee47cadSRui Miguel Silva 2893ee47cadSRui Miguel Silva static void ov2680_power_up(struct ov2680_dev *sensor) 2903ee47cadSRui Miguel Silva { 291e9305a23SHans de Goede if (!sensor->pwdn_gpio) 2923ee47cadSRui Miguel Silva return; 2933ee47cadSRui Miguel Silva 294e9305a23SHans de Goede gpiod_set_value(sensor->pwdn_gpio, 0); 2953ee47cadSRui Miguel Silva usleep_range(5000, 10000); 2963ee47cadSRui Miguel Silva } 2973ee47cadSRui Miguel Silva 2983ee47cadSRui Miguel Silva static void ov2680_power_down(struct ov2680_dev *sensor) 2993ee47cadSRui Miguel Silva { 300e9305a23SHans de Goede if (!sensor->pwdn_gpio) 3013ee47cadSRui Miguel Silva return; 3023ee47cadSRui Miguel Silva 303e9305a23SHans de Goede gpiod_set_value(sensor->pwdn_gpio, 1); 3043ee47cadSRui Miguel Silva usleep_range(5000, 10000); 3053ee47cadSRui Miguel Silva } 3063ee47cadSRui Miguel Silva 3076d6849b2SHans de Goede static void ov2680_set_bayer_order(struct ov2680_dev *sensor, 3086d6849b2SHans de Goede struct v4l2_mbus_framefmt *fmt) 3093ee47cadSRui Miguel Silva { 31050a7bad4SHans de Goede int hv_flip = 0; 3113ee47cadSRui Miguel Silva 31250a7bad4SHans de Goede if (sensor->ctrls.vflip && sensor->ctrls.vflip->val) 31350a7bad4SHans de Goede hv_flip += 1; 3143ee47cadSRui Miguel Silva 31550a7bad4SHans de Goede if (sensor->ctrls.hflip && sensor->ctrls.hflip->val) 31650a7bad4SHans de Goede hv_flip += 2; 3173ee47cadSRui Miguel Silva 3186d6849b2SHans de Goede fmt->code = ov2680_hv_flip_bayer_order[hv_flip]; 3196d6849b2SHans de Goede } 3206d6849b2SHans de Goede 3216d6849b2SHans de Goede static void ov2680_fill_format(struct ov2680_dev *sensor, 3226d6849b2SHans de Goede struct v4l2_mbus_framefmt *fmt, 3236d6849b2SHans de Goede unsigned int width, unsigned int height) 3246d6849b2SHans de Goede { 3256d6849b2SHans de Goede memset(fmt, 0, sizeof(*fmt)); 3266d6849b2SHans de Goede fmt->width = width; 3276d6849b2SHans de Goede fmt->height = height; 3286d6849b2SHans de Goede fmt->field = V4L2_FIELD_NONE; 3296d6849b2SHans de Goede fmt->colorspace = V4L2_COLORSPACE_SRGB; 3306d6849b2SHans de Goede ov2680_set_bayer_order(sensor, fmt); 3313ee47cadSRui Miguel Silva } 3323ee47cadSRui Miguel Silva 333d5d08ad3SHans de Goede static int ov2680_set_vflip(struct ov2680_dev *sensor, s32 val) 3343ee47cadSRui Miguel Silva { 3353ee47cadSRui Miguel Silva int ret; 3363ee47cadSRui Miguel Silva 337d5d08ad3SHans de Goede if (sensor->is_streaming) 338d5d08ad3SHans de Goede return -EBUSY; 339d5d08ad3SHans de Goede 3409289998eSHans de Goede ret = cci_update_bits(sensor->regmap, OV2680_REG_FORMAT1, 3419289998eSHans de Goede BIT(2), val ? BIT(2) : 0, NULL); 3423ee47cadSRui Miguel Silva if (ret < 0) 3433ee47cadSRui Miguel Silva return ret; 3443ee47cadSRui Miguel Silva 345*f614dfb8SHans de Goede ov2680_set_bayer_order(sensor, &sensor->mode.fmt); 34650a7bad4SHans de Goede return 0; 3473ee47cadSRui Miguel Silva } 3483ee47cadSRui Miguel Silva 349d5d08ad3SHans de Goede static int ov2680_set_hflip(struct ov2680_dev *sensor, s32 val) 3503ee47cadSRui Miguel Silva { 3513ee47cadSRui Miguel Silva int ret; 3523ee47cadSRui Miguel Silva 353d5d08ad3SHans de Goede if (sensor->is_streaming) 354d5d08ad3SHans de Goede return -EBUSY; 3553ee47cadSRui Miguel Silva 3569289998eSHans de Goede ret = cci_update_bits(sensor->regmap, OV2680_REG_FORMAT2, 3579289998eSHans de Goede BIT(2), val ? BIT(2) : 0, NULL); 3583ee47cadSRui Miguel Silva if (ret < 0) 3593ee47cadSRui Miguel Silva return ret; 3603ee47cadSRui Miguel Silva 361*f614dfb8SHans de Goede ov2680_set_bayer_order(sensor, &sensor->mode.fmt); 36250a7bad4SHans de Goede return 0; 3633ee47cadSRui Miguel Silva } 3643ee47cadSRui Miguel Silva 3653ee47cadSRui Miguel Silva static int ov2680_test_pattern_set(struct ov2680_dev *sensor, int value) 3663ee47cadSRui Miguel Silva { 3679289998eSHans de Goede int ret = 0; 3683ee47cadSRui Miguel Silva 3693ee47cadSRui Miguel Silva if (!value) 3709289998eSHans de Goede return cci_update_bits(sensor->regmap, OV2680_REG_ISP_CTRL00, 3719289998eSHans de Goede BIT(7), 0, NULL); 3723ee47cadSRui Miguel Silva 3739289998eSHans de Goede cci_update_bits(sensor->regmap, OV2680_REG_ISP_CTRL00, 3749289998eSHans de Goede 0x03, value - 1, &ret); 3759289998eSHans de Goede cci_update_bits(sensor->regmap, OV2680_REG_ISP_CTRL00, 3769289998eSHans de Goede BIT(7), BIT(7), &ret); 3779289998eSHans de Goede 3783ee47cadSRui Miguel Silva return ret; 3793ee47cadSRui Miguel Silva } 3803ee47cadSRui Miguel Silva 3817b5a42e6SHans de Goede static int ov2680_gain_set(struct ov2680_dev *sensor, u32 gain) 3823ee47cadSRui Miguel Silva { 3839289998eSHans de Goede return cci_write(sensor->regmap, OV2680_REG_GAIN_PK, gain, NULL); 3843ee47cadSRui Miguel Silva } 3853ee47cadSRui Miguel Silva 3867b5a42e6SHans de Goede static int ov2680_exposure_set(struct ov2680_dev *sensor, u32 exp) 3873ee47cadSRui Miguel Silva { 3889289998eSHans de Goede return cci_write(sensor->regmap, OV2680_REG_EXPOSURE_PK, exp << 4, 3899289998eSHans de Goede NULL); 3903ee47cadSRui Miguel Silva } 3913ee47cadSRui Miguel Silva 3923ee47cadSRui Miguel Silva static int ov2680_stream_enable(struct ov2680_dev *sensor) 3933ee47cadSRui Miguel Silva { 3943ee47cadSRui Miguel Silva int ret; 3953ee47cadSRui Miguel Silva 3968e50a122SHans de Goede ret = cci_write(sensor->regmap, OV2680_REG_PLL_MULTIPLIER, 3978e50a122SHans de Goede sensor->pll_mult, NULL); 3988e50a122SHans de Goede if (ret < 0) 3998e50a122SHans de Goede return ret; 4008e50a122SHans de Goede 4019289998eSHans de Goede ret = regmap_multi_reg_write(sensor->regmap, 402990732a6SHans de Goede ov2680_mode_init_data.reg_data, 403990732a6SHans de Goede ov2680_mode_init_data.reg_data_size); 404990732a6SHans de Goede if (ret < 0) 405990732a6SHans de Goede return ret; 406990732a6SHans de Goede 407990732a6SHans de Goede ret = regmap_multi_reg_write(sensor->regmap, 4089289998eSHans de Goede sensor->current_mode->reg_data, 4099289998eSHans de Goede sensor->current_mode->reg_data_size); 4103ee47cadSRui Miguel Silva if (ret < 0) 4113ee47cadSRui Miguel Silva return ret; 4123ee47cadSRui Miguel Silva 4137b5a42e6SHans de Goede /* Restore value of all ctrls */ 4147b5a42e6SHans de Goede ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler); 4153ee47cadSRui Miguel Silva if (ret < 0) 4163ee47cadSRui Miguel Silva return ret; 4173ee47cadSRui Miguel Silva 418990732a6SHans de Goede return cci_write(sensor->regmap, OV2680_REG_STREAM_CTRL, 1, NULL); 4193ee47cadSRui Miguel Silva } 4203ee47cadSRui Miguel Silva 421990732a6SHans de Goede static int ov2680_stream_disable(struct ov2680_dev *sensor) 4223ee47cadSRui Miguel Silva { 423990732a6SHans de Goede return cci_write(sensor->regmap, OV2680_REG_STREAM_CTRL, 0, NULL); 4243ee47cadSRui Miguel Silva } 4253ee47cadSRui Miguel Silva 4263ee47cadSRui Miguel Silva static int ov2680_power_off(struct ov2680_dev *sensor) 4273ee47cadSRui Miguel Silva { 4283ee47cadSRui Miguel Silva clk_disable_unprepare(sensor->xvclk); 4293ee47cadSRui Miguel Silva ov2680_power_down(sensor); 4303ee47cadSRui Miguel Silva regulator_bulk_disable(OV2680_NUM_SUPPLIES, sensor->supplies); 4313ee47cadSRui Miguel Silva return 0; 4323ee47cadSRui Miguel Silva } 4333ee47cadSRui Miguel Silva 4343ee47cadSRui Miguel Silva static int ov2680_power_on(struct ov2680_dev *sensor) 4353ee47cadSRui Miguel Silva { 4363ee47cadSRui Miguel Silva int ret; 4373ee47cadSRui Miguel Silva 4383ee47cadSRui Miguel Silva ret = regulator_bulk_enable(OV2680_NUM_SUPPLIES, sensor->supplies); 4393ee47cadSRui Miguel Silva if (ret < 0) { 4407adfdecbSHans de Goede dev_err(sensor->dev, "failed to enable regulators: %d\n", ret); 4413ee47cadSRui Miguel Silva return ret; 4423ee47cadSRui Miguel Silva } 4433ee47cadSRui Miguel Silva 444e9305a23SHans de Goede if (!sensor->pwdn_gpio) { 4459289998eSHans de Goede ret = cci_write(sensor->regmap, OV2680_REG_SOFT_RESET, 0x01, 4469289998eSHans de Goede NULL); 4473ee47cadSRui Miguel Silva if (ret != 0) { 4487adfdecbSHans de Goede dev_err(sensor->dev, "sensor soft reset failed\n"); 44984b4bd7eSHans de Goede goto err_disable_regulators; 4503ee47cadSRui Miguel Silva } 4513ee47cadSRui Miguel Silva usleep_range(1000, 2000); 4523ee47cadSRui Miguel Silva } else { 4533ee47cadSRui Miguel Silva ov2680_power_down(sensor); 4543ee47cadSRui Miguel Silva ov2680_power_up(sensor); 4553ee47cadSRui Miguel Silva } 4563ee47cadSRui Miguel Silva 4573ee47cadSRui Miguel Silva ret = clk_prepare_enable(sensor->xvclk); 4583ee47cadSRui Miguel Silva if (ret < 0) 45984b4bd7eSHans de Goede goto err_disable_regulators; 4603ee47cadSRui Miguel Silva 4613ee47cadSRui Miguel Silva return 0; 46284b4bd7eSHans de Goede 46384b4bd7eSHans de Goede err_disable_regulators: 46484b4bd7eSHans de Goede regulator_bulk_disable(OV2680_NUM_SUPPLIES, sensor->supplies); 46584b4bd7eSHans de Goede return ret; 4663ee47cadSRui Miguel Silva } 4673ee47cadSRui Miguel Silva 4683ee47cadSRui Miguel Silva static int ov2680_s_g_frame_interval(struct v4l2_subdev *sd, 4693ee47cadSRui Miguel Silva struct v4l2_subdev_frame_interval *fi) 4703ee47cadSRui Miguel Silva { 4713ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 4723ee47cadSRui Miguel Silva 4733ee47cadSRui Miguel Silva mutex_lock(&sensor->lock); 474*f614dfb8SHans de Goede fi->interval = sensor->mode.frame_interval; 4753ee47cadSRui Miguel Silva mutex_unlock(&sensor->lock); 4763ee47cadSRui Miguel Silva 4773ee47cadSRui Miguel Silva return 0; 4783ee47cadSRui Miguel Silva } 4793ee47cadSRui Miguel Silva 4803ee47cadSRui Miguel Silva static int ov2680_s_stream(struct v4l2_subdev *sd, int enable) 4813ee47cadSRui Miguel Silva { 4823ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 4833ee47cadSRui Miguel Silva int ret = 0; 4843ee47cadSRui Miguel Silva 4853ee47cadSRui Miguel Silva mutex_lock(&sensor->lock); 4863ee47cadSRui Miguel Silva 4873ee47cadSRui Miguel Silva if (sensor->is_streaming == !!enable) 4883ee47cadSRui Miguel Silva goto unlock; 4893ee47cadSRui Miguel Silva 490990732a6SHans de Goede if (enable) { 491990732a6SHans de Goede ret = pm_runtime_resume_and_get(sensor->sd.dev); 4923ee47cadSRui Miguel Silva if (ret < 0) 4933ee47cadSRui Miguel Silva goto unlock; 4943ee47cadSRui Miguel Silva 4953ee47cadSRui Miguel Silva ret = ov2680_stream_enable(sensor); 496990732a6SHans de Goede if (ret < 0) { 497990732a6SHans de Goede pm_runtime_put(sensor->sd.dev); 498990732a6SHans de Goede goto unlock; 499990732a6SHans de Goede } 500990732a6SHans de Goede } else { 5013ee47cadSRui Miguel Silva ret = ov2680_stream_disable(sensor); 502990732a6SHans de Goede pm_runtime_put(sensor->sd.dev); 503990732a6SHans de Goede } 5043ee47cadSRui Miguel Silva 5053ee47cadSRui Miguel Silva sensor->is_streaming = !!enable; 5063ee47cadSRui Miguel Silva 5073ee47cadSRui Miguel Silva unlock: 5083ee47cadSRui Miguel Silva mutex_unlock(&sensor->lock); 5093ee47cadSRui Miguel Silva 5103ee47cadSRui Miguel Silva return ret; 5113ee47cadSRui Miguel Silva } 5123ee47cadSRui Miguel Silva 5133ee47cadSRui Miguel Silva static int ov2680_enum_mbus_code(struct v4l2_subdev *sd, 5140d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state, 5153ee47cadSRui Miguel Silva struct v4l2_subdev_mbus_code_enum *code) 5163ee47cadSRui Miguel Silva { 5173ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 5183ee47cadSRui Miguel Silva 5193ee47cadSRui Miguel Silva if (code->pad != 0 || code->index != 0) 5203ee47cadSRui Miguel Silva return -EINVAL; 5213ee47cadSRui Miguel Silva 522*f614dfb8SHans de Goede code->code = sensor->mode.fmt.code; 5233ee47cadSRui Miguel Silva 5243ee47cadSRui Miguel Silva return 0; 5253ee47cadSRui Miguel Silva } 5263ee47cadSRui Miguel Silva 5273ee47cadSRui Miguel Silva static int ov2680_get_fmt(struct v4l2_subdev *sd, 5280d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state, 5293ee47cadSRui Miguel Silva struct v4l2_subdev_format *format) 5303ee47cadSRui Miguel Silva { 5313ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 5323ee47cadSRui Miguel Silva struct v4l2_mbus_framefmt *fmt = NULL; 5333ee47cadSRui Miguel Silva 5343ee47cadSRui Miguel Silva if (format->pad != 0) 5353ee47cadSRui Miguel Silva return -EINVAL; 5363ee47cadSRui Miguel Silva 5373ee47cadSRui Miguel Silva mutex_lock(&sensor->lock); 5383ee47cadSRui Miguel Silva 5393ee47cadSRui Miguel Silva if (format->which == V4L2_SUBDEV_FORMAT_TRY) { 5400d346d2aSTomi Valkeinen fmt = v4l2_subdev_get_try_format(&sensor->sd, sd_state, 5410d346d2aSTomi Valkeinen format->pad); 5423ee47cadSRui Miguel Silva } else { 543*f614dfb8SHans de Goede fmt = &sensor->mode.fmt; 5443ee47cadSRui Miguel Silva } 5453ee47cadSRui Miguel Silva 5463ee47cadSRui Miguel Silva format->format = *fmt; 5473ee47cadSRui Miguel Silva 5483ee47cadSRui Miguel Silva mutex_unlock(&sensor->lock); 5493ee47cadSRui Miguel Silva 55049c282d5SHans de Goede return 0; 5513ee47cadSRui Miguel Silva } 5523ee47cadSRui Miguel Silva 5533ee47cadSRui Miguel Silva static int ov2680_set_fmt(struct v4l2_subdev *sd, 5540d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state, 5553ee47cadSRui Miguel Silva struct v4l2_subdev_format *format) 5563ee47cadSRui Miguel Silva { 5573ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 5583ee47cadSRui Miguel Silva struct v4l2_mbus_framefmt *try_fmt; 5593ee47cadSRui Miguel Silva const struct ov2680_mode_info *mode; 5603ee47cadSRui Miguel Silva int ret = 0; 5613ee47cadSRui Miguel Silva 5623ee47cadSRui Miguel Silva if (format->pad != 0) 5633ee47cadSRui Miguel Silva return -EINVAL; 5643ee47cadSRui Miguel Silva 5653ee47cadSRui Miguel Silva mode = v4l2_find_nearest_size(ov2680_mode_data, 566c0e97a4bSHans de Goede ARRAY_SIZE(ov2680_mode_data), 567c0e97a4bSHans de Goede width, height, 568c0e97a4bSHans de Goede format->format.width, 569c0e97a4bSHans de Goede format->format.height); 570e521b9ccSHans de Goede if (!mode) 571e521b9ccSHans de Goede return -EINVAL; 5723ee47cadSRui Miguel Silva 573c0e97a4bSHans de Goede ov2680_fill_format(sensor, &format->format, mode->width, mode->height); 574c0e97a4bSHans de Goede 5753ee47cadSRui Miguel Silva if (format->which == V4L2_SUBDEV_FORMAT_TRY) { 5760d346d2aSTomi Valkeinen try_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0); 577c0e97a4bSHans de Goede *try_fmt = format->format; 578e521b9ccSHans de Goede return 0; 579e521b9ccSHans de Goede } 580e521b9ccSHans de Goede 581e521b9ccSHans de Goede mutex_lock(&sensor->lock); 582e521b9ccSHans de Goede 583e521b9ccSHans de Goede if (sensor->is_streaming) { 584e521b9ccSHans de Goede ret = -EBUSY; 5853ee47cadSRui Miguel Silva goto unlock; 5863ee47cadSRui Miguel Silva } 5873ee47cadSRui Miguel Silva 5883ee47cadSRui Miguel Silva sensor->current_mode = mode; 589*f614dfb8SHans de Goede sensor->mode.fmt = format->format; 5903ee47cadSRui Miguel Silva 5913ee47cadSRui Miguel Silva unlock: 5923ee47cadSRui Miguel Silva mutex_unlock(&sensor->lock); 5933ee47cadSRui Miguel Silva 5943ee47cadSRui Miguel Silva return ret; 5953ee47cadSRui Miguel Silva } 5963ee47cadSRui Miguel Silva 5973ee47cadSRui Miguel Silva static int ov2680_init_cfg(struct v4l2_subdev *sd, 5980d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state) 5993ee47cadSRui Miguel Silva { 6006d6849b2SHans de Goede struct ov2680_dev *sensor = to_ov2680_dev(sd); 6013ee47cadSRui Miguel Silva 6026d6849b2SHans de Goede ov2680_fill_format(sensor, &sd_state->pads[0].try_fmt, 6036d6849b2SHans de Goede OV2680_DEFAULT_WIDTH, OV2680_DEFAULT_HEIGHT); 6046d6849b2SHans de Goede return 0; 6053ee47cadSRui Miguel Silva } 6063ee47cadSRui Miguel Silva 6073ee47cadSRui Miguel Silva static int ov2680_enum_frame_size(struct v4l2_subdev *sd, 6080d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state, 6093ee47cadSRui Miguel Silva struct v4l2_subdev_frame_size_enum *fse) 6103ee47cadSRui Miguel Silva { 6113ee47cadSRui Miguel Silva int index = fse->index; 6123ee47cadSRui Miguel Silva 6133ee47cadSRui Miguel Silva if (index >= OV2680_MODE_MAX || index < 0) 6143ee47cadSRui Miguel Silva return -EINVAL; 6153ee47cadSRui Miguel Silva 6163ee47cadSRui Miguel Silva fse->min_width = ov2680_mode_data[index].width; 6173ee47cadSRui Miguel Silva fse->min_height = ov2680_mode_data[index].height; 6183ee47cadSRui Miguel Silva fse->max_width = ov2680_mode_data[index].width; 6193ee47cadSRui Miguel Silva fse->max_height = ov2680_mode_data[index].height; 6203ee47cadSRui Miguel Silva 6213ee47cadSRui Miguel Silva return 0; 6223ee47cadSRui Miguel Silva } 6233ee47cadSRui Miguel Silva 6244007015eSHans de Goede static bool ov2680_valid_frame_size(struct v4l2_subdev_frame_interval_enum *fie) 6254007015eSHans de Goede { 6264007015eSHans de Goede int i; 6274007015eSHans de Goede 6284007015eSHans de Goede for (i = 0; i < OV2680_MODE_MAX; i++) { 6294007015eSHans de Goede if (fie->width == ov2680_mode_data[i].width && 6304007015eSHans de Goede fie->height == ov2680_mode_data[i].height) 6314007015eSHans de Goede return true; 6324007015eSHans de Goede } 6334007015eSHans de Goede 6344007015eSHans de Goede return false; 6354007015eSHans de Goede } 6364007015eSHans de Goede 6373ee47cadSRui Miguel Silva static int ov2680_enum_frame_interval(struct v4l2_subdev *sd, 6380d346d2aSTomi Valkeinen struct v4l2_subdev_state *sd_state, 6393ee47cadSRui Miguel Silva struct v4l2_subdev_frame_interval_enum *fie) 6403ee47cadSRui Miguel Silva { 6414007015eSHans de Goede struct ov2680_dev *sensor = to_ov2680_dev(sd); 6423ee47cadSRui Miguel Silva 6434007015eSHans de Goede /* Only 1 framerate */ 6444007015eSHans de Goede if (fie->index || !ov2680_valid_frame_size(fie)) 6453ee47cadSRui Miguel Silva return -EINVAL; 6463ee47cadSRui Miguel Silva 647*f614dfb8SHans de Goede fie->interval = sensor->mode.frame_interval; 6483ee47cadSRui Miguel Silva 6493ee47cadSRui Miguel Silva return 0; 6503ee47cadSRui Miguel Silva } 6513ee47cadSRui Miguel Silva 6523ee47cadSRui Miguel Silva static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl) 6533ee47cadSRui Miguel Silva { 6543ee47cadSRui Miguel Silva struct v4l2_subdev *sd = ctrl_to_sd(ctrl); 6553ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 65637f7e57eSHans de Goede int ret; 6573ee47cadSRui Miguel Silva 65837f7e57eSHans de Goede /* Only apply changes to the controls if the device is powered up */ 65937f7e57eSHans de Goede if (!pm_runtime_get_if_in_use(sensor->sd.dev)) { 660*f614dfb8SHans de Goede ov2680_set_bayer_order(sensor, &sensor->mode.fmt); 6613ee47cadSRui Miguel Silva return 0; 66237f7e57eSHans de Goede } 6633ee47cadSRui Miguel Silva 6643ee47cadSRui Miguel Silva switch (ctrl->id) { 6653ee47cadSRui Miguel Silva case V4L2_CID_GAIN: 66637f7e57eSHans de Goede ret = ov2680_gain_set(sensor, ctrl->val); 66737f7e57eSHans de Goede break; 6683ee47cadSRui Miguel Silva case V4L2_CID_EXPOSURE: 66937f7e57eSHans de Goede ret = ov2680_exposure_set(sensor, ctrl->val); 67037f7e57eSHans de Goede break; 6713ee47cadSRui Miguel Silva case V4L2_CID_VFLIP: 67237f7e57eSHans de Goede ret = ov2680_set_vflip(sensor, ctrl->val); 67337f7e57eSHans de Goede break; 6743ee47cadSRui Miguel Silva case V4L2_CID_HFLIP: 67537f7e57eSHans de Goede ret = ov2680_set_hflip(sensor, ctrl->val); 67637f7e57eSHans de Goede break; 6773ee47cadSRui Miguel Silva case V4L2_CID_TEST_PATTERN: 67837f7e57eSHans de Goede ret = ov2680_test_pattern_set(sensor, ctrl->val); 67937f7e57eSHans de Goede break; 6803ee47cadSRui Miguel Silva default: 68137f7e57eSHans de Goede ret = -EINVAL; 6823ee47cadSRui Miguel Silva break; 6833ee47cadSRui Miguel Silva } 6843ee47cadSRui Miguel Silva 68537f7e57eSHans de Goede pm_runtime_put(sensor->sd.dev); 68637f7e57eSHans de Goede return ret; 6873ee47cadSRui Miguel Silva } 6883ee47cadSRui Miguel Silva 6893ee47cadSRui Miguel Silva static const struct v4l2_ctrl_ops ov2680_ctrl_ops = { 6903ee47cadSRui Miguel Silva .s_ctrl = ov2680_s_ctrl, 6913ee47cadSRui Miguel Silva }; 6923ee47cadSRui Miguel Silva 6933ee47cadSRui Miguel Silva static const struct v4l2_subdev_video_ops ov2680_video_ops = { 6943ee47cadSRui Miguel Silva .g_frame_interval = ov2680_s_g_frame_interval, 6953ee47cadSRui Miguel Silva .s_frame_interval = ov2680_s_g_frame_interval, 6963ee47cadSRui Miguel Silva .s_stream = ov2680_s_stream, 6973ee47cadSRui Miguel Silva }; 6983ee47cadSRui Miguel Silva 6993ee47cadSRui Miguel Silva static const struct v4l2_subdev_pad_ops ov2680_pad_ops = { 7003ee47cadSRui Miguel Silva .init_cfg = ov2680_init_cfg, 7013ee47cadSRui Miguel Silva .enum_mbus_code = ov2680_enum_mbus_code, 7023ee47cadSRui Miguel Silva .get_fmt = ov2680_get_fmt, 7033ee47cadSRui Miguel Silva .set_fmt = ov2680_set_fmt, 7043ee47cadSRui Miguel Silva .enum_frame_size = ov2680_enum_frame_size, 7053ee47cadSRui Miguel Silva .enum_frame_interval = ov2680_enum_frame_interval, 7063ee47cadSRui Miguel Silva }; 7073ee47cadSRui Miguel Silva 7083ee47cadSRui Miguel Silva static const struct v4l2_subdev_ops ov2680_subdev_ops = { 7093ee47cadSRui Miguel Silva .video = &ov2680_video_ops, 7103ee47cadSRui Miguel Silva .pad = &ov2680_pad_ops, 7113ee47cadSRui Miguel Silva }; 7123ee47cadSRui Miguel Silva 7133ee47cadSRui Miguel Silva static int ov2680_mode_init(struct ov2680_dev *sensor) 7143ee47cadSRui Miguel Silva { 7153ee47cadSRui Miguel Silva const struct ov2680_mode_info *init_mode; 7163ee47cadSRui Miguel Silva 7173ee47cadSRui Miguel Silva /* set initial mode */ 718*f614dfb8SHans de Goede ov2680_fill_format(sensor, &sensor->mode.fmt, 7196d6849b2SHans de Goede OV2680_DEFAULT_WIDTH, OV2680_DEFAULT_HEIGHT); 7203ee47cadSRui Miguel Silva 721*f614dfb8SHans de Goede sensor->mode.frame_interval.denominator = OV2680_FRAME_RATE; 722*f614dfb8SHans de Goede sensor->mode.frame_interval.numerator = 1; 7233ee47cadSRui Miguel Silva 7243ee47cadSRui Miguel Silva init_mode = &ov2680_mode_init_data; 7253ee47cadSRui Miguel Silva 7263ee47cadSRui Miguel Silva sensor->current_mode = init_mode; 7273ee47cadSRui Miguel Silva 7283ee47cadSRui Miguel Silva return 0; 7293ee47cadSRui Miguel Silva } 7303ee47cadSRui Miguel Silva 731e7f4861dSJavier Martinez Canillas static int ov2680_v4l2_register(struct ov2680_dev *sensor) 7323ee47cadSRui Miguel Silva { 7337adfdecbSHans de Goede struct i2c_client *client = to_i2c_client(sensor->dev); 7343ee47cadSRui Miguel Silva const struct v4l2_ctrl_ops *ops = &ov2680_ctrl_ops; 7353ee47cadSRui Miguel Silva struct ov2680_ctrls *ctrls = &sensor->ctrls; 7363ee47cadSRui Miguel Silva struct v4l2_ctrl_handler *hdl = &ctrls->handler; 7373ee47cadSRui Miguel Silva int ret = 0; 7383ee47cadSRui Miguel Silva 7397adfdecbSHans de Goede v4l2_i2c_subdev_init(&sensor->sd, client, &ov2680_subdev_ops); 7403ee47cadSRui Miguel Silva 7413ee47cadSRui Miguel Silva sensor->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; 7423ee47cadSRui Miguel Silva sensor->pad.flags = MEDIA_PAD_FL_SOURCE; 7433ee47cadSRui Miguel Silva sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; 7443ee47cadSRui Miguel Silva 7453ee47cadSRui Miguel Silva ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad); 7463ee47cadSRui Miguel Silva if (ret < 0) 7473ee47cadSRui Miguel Silva return ret; 7483ee47cadSRui Miguel Silva 7497b5a42e6SHans de Goede v4l2_ctrl_handler_init(hdl, 5); 7503ee47cadSRui Miguel Silva 7513ee47cadSRui Miguel Silva hdl->lock = &sensor->lock; 7523ee47cadSRui Miguel Silva 7533ee47cadSRui Miguel Silva ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0); 7543ee47cadSRui Miguel Silva ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0); 7553ee47cadSRui Miguel Silva 7563ee47cadSRui Miguel Silva ctrls->test_pattern = v4l2_ctrl_new_std_menu_items(hdl, 7573ee47cadSRui Miguel Silva &ov2680_ctrl_ops, V4L2_CID_TEST_PATTERN, 7583ee47cadSRui Miguel Silva ARRAY_SIZE(test_pattern_menu) - 1, 7593ee47cadSRui Miguel Silva 0, 0, test_pattern_menu); 7603ee47cadSRui Miguel Silva 7613ee47cadSRui Miguel Silva ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE, 7623ee47cadSRui Miguel Silva 0, 32767, 1, 0); 7633ee47cadSRui Miguel Silva 7643ee47cadSRui Miguel Silva ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN, 0, 2047, 1, 0); 7653ee47cadSRui Miguel Silva 7663ee47cadSRui Miguel Silva if (hdl->error) { 7673ee47cadSRui Miguel Silva ret = hdl->error; 7683ee47cadSRui Miguel Silva goto cleanup_entity; 7693ee47cadSRui Miguel Silva } 7703ee47cadSRui Miguel Silva 77166274280SDave Stevenson ctrls->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; 77266274280SDave Stevenson ctrls->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; 7733ee47cadSRui Miguel Silva 7743ee47cadSRui Miguel Silva sensor->sd.ctrl_handler = hdl; 7753ee47cadSRui Miguel Silva 7763ee47cadSRui Miguel Silva ret = v4l2_async_register_subdev(&sensor->sd); 7773ee47cadSRui Miguel Silva if (ret < 0) 7783ee47cadSRui Miguel Silva goto cleanup_entity; 7793ee47cadSRui Miguel Silva 7803ee47cadSRui Miguel Silva return 0; 7813ee47cadSRui Miguel Silva 7823ee47cadSRui Miguel Silva cleanup_entity: 7833ee47cadSRui Miguel Silva media_entity_cleanup(&sensor->sd.entity); 7843ee47cadSRui Miguel Silva v4l2_ctrl_handler_free(hdl); 7853ee47cadSRui Miguel Silva 7863ee47cadSRui Miguel Silva return ret; 7873ee47cadSRui Miguel Silva } 7883ee47cadSRui Miguel Silva 7893ee47cadSRui Miguel Silva static int ov2680_get_regulators(struct ov2680_dev *sensor) 7903ee47cadSRui Miguel Silva { 7913ee47cadSRui Miguel Silva int i; 7923ee47cadSRui Miguel Silva 7933ee47cadSRui Miguel Silva for (i = 0; i < OV2680_NUM_SUPPLIES; i++) 7943ee47cadSRui Miguel Silva sensor->supplies[i].supply = ov2680_supply_name[i]; 7953ee47cadSRui Miguel Silva 7967adfdecbSHans de Goede return devm_regulator_bulk_get(sensor->dev, 7977adfdecbSHans de Goede OV2680_NUM_SUPPLIES, sensor->supplies); 7983ee47cadSRui Miguel Silva } 7993ee47cadSRui Miguel Silva 8003ee47cadSRui Miguel Silva static int ov2680_check_id(struct ov2680_dev *sensor) 8013ee47cadSRui Miguel Silva { 8029289998eSHans de Goede u64 chip_id; 8033ee47cadSRui Miguel Silva int ret; 8043ee47cadSRui Miguel Silva 8059289998eSHans de Goede ret = cci_read(sensor->regmap, OV2680_REG_CHIP_ID, &chip_id, NULL); 8063ee47cadSRui Miguel Silva if (ret < 0) { 8077adfdecbSHans de Goede dev_err(sensor->dev, "failed to read chip id\n"); 8083ee47cadSRui Miguel Silva return -ENODEV; 8093ee47cadSRui Miguel Silva } 8103ee47cadSRui Miguel Silva 8113ee47cadSRui Miguel Silva if (chip_id != OV2680_CHIP_ID) { 8127adfdecbSHans de Goede dev_err(sensor->dev, "chip id: 0x%04llx does not match expected 0x%04x\n", 8133ee47cadSRui Miguel Silva chip_id, OV2680_CHIP_ID); 8143ee47cadSRui Miguel Silva return -ENODEV; 8153ee47cadSRui Miguel Silva } 8163ee47cadSRui Miguel Silva 8173ee47cadSRui Miguel Silva return 0; 8183ee47cadSRui Miguel Silva } 8193ee47cadSRui Miguel Silva 820913c55a8SChristophe JAILLET static int ov2680_parse_dt(struct ov2680_dev *sensor) 8213ee47cadSRui Miguel Silva { 8227adfdecbSHans de Goede struct device *dev = sensor->dev; 82383634470SHans de Goede struct fwnode_handle *ep_fwnode; 824e9305a23SHans de Goede struct gpio_desc *gpio; 825ec7dfad5SHans de Goede unsigned int rate = 0; 8268e50a122SHans de Goede int i, ret; 8273ee47cadSRui Miguel Silva 828e9305a23SHans de Goede /* 82983634470SHans de Goede * Sometimes the fwnode graph is initialized by the bridge driver. 83083634470SHans de Goede * Bridge drivers doing this may also add GPIO mappings, wait for this. 83183634470SHans de Goede */ 83283634470SHans de Goede ep_fwnode = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); 83383634470SHans de Goede if (!ep_fwnode) 83483634470SHans de Goede return dev_err_probe(dev, -EPROBE_DEFER, 83583634470SHans de Goede "waiting for fwnode graph endpoint\n"); 83683634470SHans de Goede 83783634470SHans de Goede fwnode_handle_put(ep_fwnode); 83883634470SHans de Goede 83983634470SHans de Goede /* 840e9305a23SHans de Goede * The pin we want is named XSHUTDN in the datasheet. Linux sensor 841e9305a23SHans de Goede * drivers have standardized on using "powerdown" as con-id name 842e9305a23SHans de Goede * for powerdown or shutdown pins. Older DTB files use "reset", 843e9305a23SHans de Goede * so fallback to that if there is no "powerdown" pin. 844e9305a23SHans de Goede */ 845e9305a23SHans de Goede gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); 846e9305a23SHans de Goede if (!gpio) 847e9305a23SHans de Goede gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); 848e9305a23SHans de Goede 849e9305a23SHans de Goede ret = PTR_ERR_OR_ZERO(gpio); 8503ee47cadSRui Miguel Silva if (ret < 0) { 8513ee47cadSRui Miguel Silva dev_dbg(dev, "error while getting reset gpio: %d\n", ret); 8523ee47cadSRui Miguel Silva return ret; 8533ee47cadSRui Miguel Silva } 8543ee47cadSRui Miguel Silva 855e9305a23SHans de Goede sensor->pwdn_gpio = gpio; 856e9305a23SHans de Goede 857ec7dfad5SHans de Goede sensor->xvclk = devm_clk_get_optional(dev, "xvclk"); 8583ee47cadSRui Miguel Silva if (IS_ERR(sensor->xvclk)) { 8593ee47cadSRui Miguel Silva dev_err(dev, "xvclk clock missing or invalid\n"); 8603ee47cadSRui Miguel Silva return PTR_ERR(sensor->xvclk); 8613ee47cadSRui Miguel Silva } 8623ee47cadSRui Miguel Silva 863ec7dfad5SHans de Goede /* 864ec7dfad5SHans de Goede * We could have either a 24MHz or 19.2MHz clock rate from either DT or 865ec7dfad5SHans de Goede * ACPI... but we also need to support the weird IPU3 case which will 866ec7dfad5SHans de Goede * have an external clock AND a clock-frequency property. Check for the 867ec7dfad5SHans de Goede * clock-frequency property and if found, set that rate if we managed 868ec7dfad5SHans de Goede * to acquire a clock. This should cover the ACPI case. If the system 869ec7dfad5SHans de Goede * uses devicetree then the configured rate should already be set, so 870ec7dfad5SHans de Goede * we can just read it. 871ec7dfad5SHans de Goede */ 872ec7dfad5SHans de Goede ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", 873ec7dfad5SHans de Goede &rate); 874ec7dfad5SHans de Goede if (ret && !sensor->xvclk) 875ec7dfad5SHans de Goede return dev_err_probe(dev, ret, "invalid clock config\n"); 876ec7dfad5SHans de Goede 877ec7dfad5SHans de Goede if (!ret && sensor->xvclk) { 878ec7dfad5SHans de Goede ret = clk_set_rate(sensor->xvclk, rate); 879ec7dfad5SHans de Goede if (ret) 880ec7dfad5SHans de Goede return dev_err_probe(dev, ret, 881ec7dfad5SHans de Goede "failed to set clock rate\n"); 882ec7dfad5SHans de Goede } 883ec7dfad5SHans de Goede 884ec7dfad5SHans de Goede sensor->xvclk_freq = rate ?: clk_get_rate(sensor->xvclk); 8858e50a122SHans de Goede 8868e50a122SHans de Goede for (i = 0; i < ARRAY_SIZE(ov2680_xvclk_freqs); i++) { 8878e50a122SHans de Goede if (sensor->xvclk_freq == ov2680_xvclk_freqs[i]) 8888e50a122SHans de Goede break; 8893ee47cadSRui Miguel Silva } 8903ee47cadSRui Miguel Silva 8918e50a122SHans de Goede if (i == ARRAY_SIZE(ov2680_xvclk_freqs)) 8928e50a122SHans de Goede return dev_err_probe(dev, -EINVAL, 8938e50a122SHans de Goede "unsupported xvclk frequency %d Hz\n", 8948e50a122SHans de Goede sensor->xvclk_freq); 8958e50a122SHans de Goede 8968e50a122SHans de Goede sensor->pll_mult = ov2680_pll_multipliers[i]; 8978e50a122SHans de Goede 8983ee47cadSRui Miguel Silva return 0; 8993ee47cadSRui Miguel Silva } 9003ee47cadSRui Miguel Silva 9013ee47cadSRui Miguel Silva static int ov2680_probe(struct i2c_client *client) 9023ee47cadSRui Miguel Silva { 9033ee47cadSRui Miguel Silva struct device *dev = &client->dev; 9043ee47cadSRui Miguel Silva struct ov2680_dev *sensor; 9053ee47cadSRui Miguel Silva int ret; 9063ee47cadSRui Miguel Silva 9073ee47cadSRui Miguel Silva sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); 9083ee47cadSRui Miguel Silva if (!sensor) 9093ee47cadSRui Miguel Silva return -ENOMEM; 9103ee47cadSRui Miguel Silva 9117adfdecbSHans de Goede sensor->dev = &client->dev; 9123ee47cadSRui Miguel Silva 9139289998eSHans de Goede sensor->regmap = devm_cci_regmap_init_i2c(client, 16); 9149289998eSHans de Goede if (IS_ERR(sensor->regmap)) 9159289998eSHans de Goede return PTR_ERR(sensor->regmap); 9169289998eSHans de Goede 917913c55a8SChristophe JAILLET ret = ov2680_parse_dt(sensor); 9183ee47cadSRui Miguel Silva if (ret < 0) 91983634470SHans de Goede return ret; 9203ee47cadSRui Miguel Silva 9213ee47cadSRui Miguel Silva ret = ov2680_mode_init(sensor); 9223ee47cadSRui Miguel Silva if (ret < 0) 9233ee47cadSRui Miguel Silva return ret; 9243ee47cadSRui Miguel Silva 9253ee47cadSRui Miguel Silva ret = ov2680_get_regulators(sensor); 9263ee47cadSRui Miguel Silva if (ret < 0) { 9273ee47cadSRui Miguel Silva dev_err(dev, "failed to get regulators\n"); 9283ee47cadSRui Miguel Silva return ret; 9293ee47cadSRui Miguel Silva } 9303ee47cadSRui Miguel Silva 9313ee47cadSRui Miguel Silva mutex_init(&sensor->lock); 9323ee47cadSRui Miguel Silva 933990732a6SHans de Goede /* 934990732a6SHans de Goede * Power up and verify the chip now, so that if runtime pm is 935990732a6SHans de Goede * disabled the chip is left on and streaming will work. 936990732a6SHans de Goede */ 937990732a6SHans de Goede ret = ov2680_power_on(sensor); 9383ee47cadSRui Miguel Silva if (ret < 0) 9393ee47cadSRui Miguel Silva goto lock_destroy; 9403ee47cadSRui Miguel Silva 941990732a6SHans de Goede ret = ov2680_check_id(sensor); 942990732a6SHans de Goede if (ret < 0) 943990732a6SHans de Goede goto err_powerdown; 944990732a6SHans de Goede 945990732a6SHans de Goede pm_runtime_set_active(&client->dev); 946990732a6SHans de Goede pm_runtime_get_noresume(&client->dev); 947990732a6SHans de Goede pm_runtime_enable(&client->dev); 948990732a6SHans de Goede 949e7f4861dSJavier Martinez Canillas ret = ov2680_v4l2_register(sensor); 9503ee47cadSRui Miguel Silva if (ret < 0) 951990732a6SHans de Goede goto err_pm_runtime; 952990732a6SHans de Goede 953990732a6SHans de Goede pm_runtime_set_autosuspend_delay(&client->dev, 1000); 954990732a6SHans de Goede pm_runtime_use_autosuspend(&client->dev); 955990732a6SHans de Goede pm_runtime_put_autosuspend(&client->dev); 9563ee47cadSRui Miguel Silva 9573ee47cadSRui Miguel Silva dev_info(dev, "ov2680 init correctly\n"); 9583ee47cadSRui Miguel Silva 9593ee47cadSRui Miguel Silva return 0; 9603ee47cadSRui Miguel Silva 961990732a6SHans de Goede err_pm_runtime: 962990732a6SHans de Goede pm_runtime_disable(&client->dev); 963990732a6SHans de Goede pm_runtime_put_noidle(&client->dev); 964990732a6SHans de Goede err_powerdown: 965990732a6SHans de Goede ov2680_power_off(sensor); 9663ee47cadSRui Miguel Silva lock_destroy: 967b7a41762SJavier Martinez Canillas dev_err(dev, "ov2680 init fail: %d\n", ret); 9683ee47cadSRui Miguel Silva mutex_destroy(&sensor->lock); 9693ee47cadSRui Miguel Silva 9703ee47cadSRui Miguel Silva return ret; 9713ee47cadSRui Miguel Silva } 9723ee47cadSRui Miguel Silva 973ed5c2f5fSUwe Kleine-König static void ov2680_remove(struct i2c_client *client) 9743ee47cadSRui Miguel Silva { 9753ee47cadSRui Miguel Silva struct v4l2_subdev *sd = i2c_get_clientdata(client); 9763ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 9773ee47cadSRui Miguel Silva 9783ee47cadSRui Miguel Silva v4l2_async_unregister_subdev(&sensor->sd); 9793ee47cadSRui Miguel Silva mutex_destroy(&sensor->lock); 9803ee47cadSRui Miguel Silva media_entity_cleanup(&sensor->sd.entity); 9813ee47cadSRui Miguel Silva v4l2_ctrl_handler_free(&sensor->ctrls.handler); 982990732a6SHans de Goede 983990732a6SHans de Goede /* 984990732a6SHans de Goede * Disable runtime PM. In case runtime PM is disabled in the kernel, 985990732a6SHans de Goede * make sure to turn power off manually. 986990732a6SHans de Goede */ 987990732a6SHans de Goede pm_runtime_disable(&client->dev); 988990732a6SHans de Goede if (!pm_runtime_status_suspended(&client->dev)) 989990732a6SHans de Goede ov2680_power_off(sensor); 990990732a6SHans de Goede pm_runtime_set_suspended(&client->dev); 9913ee47cadSRui Miguel Silva } 9923ee47cadSRui Miguel Silva 993990732a6SHans de Goede static int ov2680_suspend(struct device *dev) 9943ee47cadSRui Miguel Silva { 9957519296dSKrzysztof Kozlowski struct v4l2_subdev *sd = dev_get_drvdata(dev); 9963ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 9973ee47cadSRui Miguel Silva 9983ee47cadSRui Miguel Silva if (sensor->is_streaming) 9993ee47cadSRui Miguel Silva ov2680_stream_disable(sensor); 10003ee47cadSRui Miguel Silva 1001990732a6SHans de Goede return ov2680_power_off(sensor); 10023ee47cadSRui Miguel Silva } 10033ee47cadSRui Miguel Silva 1004990732a6SHans de Goede static int ov2680_resume(struct device *dev) 10053ee47cadSRui Miguel Silva { 10067519296dSKrzysztof Kozlowski struct v4l2_subdev *sd = dev_get_drvdata(dev); 10073ee47cadSRui Miguel Silva struct ov2680_dev *sensor = to_ov2680_dev(sd); 10083ee47cadSRui Miguel Silva int ret; 10093ee47cadSRui Miguel Silva 1010990732a6SHans de Goede ret = ov2680_power_on(sensor); 1011990732a6SHans de Goede if (ret < 0) 1012990732a6SHans de Goede goto stream_disable; 1013990732a6SHans de Goede 10143ee47cadSRui Miguel Silva if (sensor->is_streaming) { 10153ee47cadSRui Miguel Silva ret = ov2680_stream_enable(sensor); 10163ee47cadSRui Miguel Silva if (ret < 0) 10173ee47cadSRui Miguel Silva goto stream_disable; 10183ee47cadSRui Miguel Silva } 10193ee47cadSRui Miguel Silva 10203ee47cadSRui Miguel Silva return 0; 10213ee47cadSRui Miguel Silva 10223ee47cadSRui Miguel Silva stream_disable: 10233ee47cadSRui Miguel Silva ov2680_stream_disable(sensor); 10243ee47cadSRui Miguel Silva sensor->is_streaming = false; 10253ee47cadSRui Miguel Silva 10263ee47cadSRui Miguel Silva return ret; 10273ee47cadSRui Miguel Silva } 10283ee47cadSRui Miguel Silva 1029990732a6SHans de Goede static DEFINE_RUNTIME_DEV_PM_OPS(ov2680_pm_ops, ov2680_suspend, ov2680_resume, 1030990732a6SHans de Goede NULL); 10313ee47cadSRui Miguel Silva 10323ee47cadSRui Miguel Silva static const struct of_device_id ov2680_dt_ids[] = { 10333ee47cadSRui Miguel Silva { .compatible = "ovti,ov2680" }, 10343ee47cadSRui Miguel Silva { /* sentinel */ }, 10353ee47cadSRui Miguel Silva }; 10363ee47cadSRui Miguel Silva MODULE_DEVICE_TABLE(of, ov2680_dt_ids); 10373ee47cadSRui Miguel Silva 1038df3ecab8SHans de Goede static const struct acpi_device_id ov2680_acpi_ids[] = { 1039df3ecab8SHans de Goede { "OVTI2680" }, 1040df3ecab8SHans de Goede { /* sentinel */ } 1041df3ecab8SHans de Goede }; 1042df3ecab8SHans de Goede MODULE_DEVICE_TABLE(acpi, ov2680_acpi_ids); 1043df3ecab8SHans de Goede 10443ee47cadSRui Miguel Silva static struct i2c_driver ov2680_i2c_driver = { 10453ee47cadSRui Miguel Silva .driver = { 10463ee47cadSRui Miguel Silva .name = "ov2680", 1047990732a6SHans de Goede .pm = pm_sleep_ptr(&ov2680_pm_ops), 104814155c4fSKrzysztof Kozlowski .of_match_table = ov2680_dt_ids, 1049df3ecab8SHans de Goede .acpi_match_table = ov2680_acpi_ids, 10503ee47cadSRui Miguel Silva }, 1051aaeb31c0SUwe Kleine-König .probe = ov2680_probe, 10523ee47cadSRui Miguel Silva .remove = ov2680_remove, 10533ee47cadSRui Miguel Silva }; 10543ee47cadSRui Miguel Silva module_i2c_driver(ov2680_i2c_driver); 10553ee47cadSRui Miguel Silva 10563ee47cadSRui Miguel Silva MODULE_AUTHOR("Rui Miguel Silva <rui.silva@linaro.org>"); 10573ee47cadSRui Miguel Silva MODULE_DESCRIPTION("OV2680 CMOS Image Sensor driver"); 10583ee47cadSRui Miguel Silva MODULE_LICENSE("GPL v2"); 1059