From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 03 Jan 2024 09:43:39 +0000
Subject: [PATCH] update kernel to 5.10.198
---
kernel/drivers/media/i2c/ov7251.c | 1001 ++++++++++++++++++++++++++++++++++++++--------------------
1 files changed, 658 insertions(+), 343 deletions(-)
diff --git a/kernel/drivers/media/i2c/ov7251.c b/kernel/drivers/media/i2c/ov7251.c
index 75e416b..c144428 100644
--- a/kernel/drivers/media/i2c/ov7251.c
+++ b/kernel/drivers/media/i2c/ov7251.c
@@ -2,16 +2,12 @@
/*
* ov7251 driver
*
- * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
*
- * V0.0X01.0X01 add poweron function.
- * V0.0X01.0X02 fix mclk issue when probe multiple camera.
- * V0.0X01.0X03 add enum_frame_interval function.
- * V0.0X01.0X04 add quick stream on/off
- * V0.0X01.0X05 add function g_mbus_config
- * V0.0X01.0X06 support 640x480@120fps mode
+ * V0.0X01.0X01 first version
*/
+//#define DEBUG
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/delay.h>
@@ -19,28 +15,33 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
-#include <linux/pinctrl/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/rk-camera-module.h>
+#include <linux/rk-preisp.h>
#include <media/media-entity.h>
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
+#include <linux/pinctrl/consumer.h>
-#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x06)
+#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01)
#ifndef V4L2_CID_DIGITAL_GAIN
#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
#endif
-/* 48Mhz */
-#define OV7251_PIXEL_RATE (48 * 1000 * 1000)
+#define OV7251_LANES 1
+#define OV7251_BITS_PER_SAMPLE 10
+#define OV7251_LINK_FREQ_240 240000000
+
+#define PIXEL_RATE_WITH_240M_10BIT (OV7251_LINK_FREQ_240 * 2 * \
+ OV7251_LANES / OV7251_BITS_PER_SAMPLE)
#define OV7251_XVCLK_FREQ 24000000
-#define CHIP_ID 0x007750
+#define CHIP_ID 0x77
#define OV7251_REG_CHIP_ID 0x300a
#define OV7251_REG_MOD_VENDOR_ID 0x3d10
#define OV7251_REG_OPT_LOAD_CTRL 0x3d81
@@ -53,7 +54,6 @@
#define OV7251_EXPOSURE_MIN 4
#define OV7251_EXPOSURE_STEP 0xf
#define OV7251_VTS_MAX 0xffff
-#define OV7251_REG_VTS 0x380e
#define OV7251_REG_ANALOG_GAIN 0x350a
#define ANALOG_GAIN_MASK 0x3ff
@@ -66,23 +66,29 @@
#define OV7251_TEST_PATTERN_ENABLE 0x80
#define OV7251_TEST_PATTERN_DISABLE 0x0
+#define OV7251_REG_VTS 0x380e
+
+#define OV7251_MIRROR_REG 0x3821
+#define OV7251_FLIP_REG 0x3820
+
+#define OV7251_FETCH_MIRROR(VAL, ENABLE) (ENABLE ? VAL | 0x01 : VAL & 0xf9)
+#define OV7251_FETCH_FLIP(VAL, ENABLE) (ENABLE ? VAL | 0x01 : VAL & 0x9f)
+
+#define REG_DELAY 0xFFFE
#define REG_NULL 0xFFFF
#define OV7251_REG_VALUE_08BIT 1
#define OV7251_REG_VALUE_16BIT 2
#define OV7251_REG_VALUE_24BIT 3
-#define OV7251_NAME "ov7251"
-#define OV7251_LANES 1
-#define PIX_FORMAT MEDIA_BUS_FMT_Y10_1X10
-
#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
#define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep"
+#define OV7251_NAME "ov7251"
static const char * const ov7251_supply_names[] = {
"avdd", /* Analog power */
"dovdd", /* Digital I/O power */
- "dvdd", /* Digital core power not needed*/
+ "dvdd", /* Digital core power */
};
#define OV7251_NUM_SUPPLIES ARRAY_SIZE(ov7251_supply_names)
@@ -93,6 +99,7 @@
};
struct ov7251_mode {
+ u32 bus_fmt;
u32 width;
u32 height;
struct v4l2_fract max_fps;
@@ -101,6 +108,7 @@
u32 exp_def;
const struct regval *reg_list;
u32 hdr_mode;
+ u32 vc[PAD_MAX];
};
struct ov7251 {
@@ -109,9 +117,11 @@
struct gpio_desc *reset_gpio;
struct gpio_desc *pwdn_gpio;
struct regulator_bulk_data supplies[OV7251_NUM_SUPPLIES];
+
struct pinctrl *pinctrl;
struct pinctrl_state *pins_default;
struct pinctrl_state *pins_sleep;
+
struct v4l2_subdev subdev;
struct media_pad pad;
struct v4l2_ctrl_handler ctrl_handler;
@@ -125,26 +135,25 @@
bool streaming;
bool power_on;
const struct ov7251_mode *cur_mode;
+ struct v4l2_fract cur_fps;
u32 module_index;
const char *module_facing;
const char *module_name;
const char *len_name;
+ u32 cur_vts;
};
#define to_ov7251(sd) container_of(sd, struct ov7251, subdev)
/*
* Xclk 24Mhz
- * Pclk 48Mhz
- * PCLK = HTS * VTS * FPS
- * linelength 775(0x302)
- * framelength 516(0x204)
- * grabwindow_width 640
- * grabwindow_height 480
- * max_framerate 120fps
- * mipi_datarate per lane 640Mbps
*/
-static const struct regval ov7251_640x480_120fps_regs[] = {
+static const struct regval ov7251_global_regs[] = {
+ {REG_NULL, 0x00},
+};
+
+
+static __maybe_unused const struct regval ov7251_640x480_120fps_regs[] = {
{0x0103, 0x01},
{0x0100, 0x00},
{0x3005, 0x00},
@@ -289,159 +298,424 @@
/*
* Xclk 24Mhz
- * Pclk 48Mhz
- * PCLK = HTS * VTS * FPS
- * linelength 928(0x3a0)
- * framelength 1720(0x6b8)
- * grabwindow_width 640
- * grabwindow_height 480
* max_framerate 30fps
- * mipi_datarate per lane 640Mbps
+ * mipi_datarate per lane 630Mbps, 2lane
*/
-static const struct regval ov7251_640x480_30fps_regs[] = {
- {0x0100, 0x00},
- {0x0103, 0x01},
- {0x3001, 0x62},
- {0x3005, 0x00},
- {0x3012, 0xc0},
- {0x3013, 0xd2},
- {0x3014, 0x04},
- {0x3016, 0x10},
- {0x3017, 0x00},
- {0x3018, 0x00},
- {0x301a, 0x00},
- {0x301b, 0x00},
- {0x301c, 0x20},
- {0x3023, 0x05},
- {0x3037, 0xf0},
- {0x3098, 0x04},
- {0x3099, 0x28},
- {0x309a, 0x05},
- {0x309b, 0x04},
- {0x30b0, 0x0a},
- {0x30b1, 0x01},
- {0x30b3, 0x64},
- {0x30b4, 0x03},
- {0x30b5, 0x05},
- {0x3106, 0xda},
- {0x3500, 0x00},
- {0x3501, 0x1f},
- {0x3502, 0x80},
- {0x3503, 0x07},
- {0x3509, 0x10},
- {0x350b, 0x10},
- {0x3600, 0x1c},
- {0x3602, 0x62},
- {0x3620, 0xb7},
- {0x3622, 0x04},
- {0x3626, 0x21},
- {0x3627, 0x30},
- {0x3630, 0x44},
- {0x3631, 0x35},
- {0x3634, 0x60},
- {0x3636, 0x00},
- {0x3662, 0x01},
- {0x3663, 0x70},
- {0x3664, 0xf0},
- {0x3666, 0x0a},
- {0x3669, 0x1a},
- {0x366a, 0x00},
- {0x366b, 0x50},
- {0x3673, 0x01},
- {0x3674, 0xff},
- {0x3675, 0x03},
- {0x3705, 0xc1},
- {0x3709, 0x40},
- {0x373c, 0x08},
- {0x3742, 0x00},
- {0x3757, 0xb3},
- {0x3788, 0x00},
- {0x37a8, 0x01},
- {0x37a9, 0xc0},
- {0x3800, 0x00},
- {0x3801, 0x04},
- {0x3802, 0x00},
- {0x3803, 0x04},
- {0x3804, 0x02},
- {0x3805, 0x8b},
- {0x3806, 0x01},
- {0x3807, 0xeb},
- {0x3808, 0x02},
- {0x3809, 0x80},
- {0x380a, 0x01},
- {0x380b, 0xe0},
- {0x380c, 0x03},
- {0x380d, 0xa0},
- {0x380e, 0x06},
- {0x380f, 0xb8},
- {0x3810, 0x00},
- {0x3811, 0x02},
- {0x3812, 0x00},
- {0x3813, 0x02},
- {0x3814, 0x11},
- {0x3815, 0x11},
- {0x3820, 0x40},
- {0x3821, 0x00},
- {0x382f, 0x0e},
- {0x3832, 0x00},
- {0x3833, 0x05},
- {0x3834, 0x00},
- {0x3835, 0x0c},
- {0x3837, 0x00},
- {0x3b80, 0x00},
- {0x3b81, 0xa5},
- {0x3b82, 0x10},
- {0x3b83, 0x00},
- {0x3b84, 0x08},
- {0x3b85, 0x00},
- {0x3b86, 0x01},
- {0x3b87, 0x00},
- {0x3b88, 0x00},
- {0x3b89, 0x00},
- {0x3b8a, 0x00},
- {0x3b8b, 0x05},
- {0x3b8c, 0x00},
- {0x3b8d, 0x00},
- {0x3b8e, 0x00},
- {0x3b8f, 0x1a},
- {0x3b94, 0x05},
- {0x3b95, 0xf2},
- {0x3b96, 0x40},
- {0x3c00, 0x89},
- {0x3c01, 0x63},
- {0x3c02, 0x01},
- {0x3c03, 0x00},
- {0x3c04, 0x00},
- {0x3c05, 0x03},
- {0x3c06, 0x00},
- {0x3c07, 0x06},
- {0x3c0c, 0x01},
- {0x3c0d, 0xd0},
- {0x3c0e, 0x02},
- {0x3c0f, 0x04},
- {0x4001, 0x42},
- {0x4004, 0x04},
- {0x4005, 0x00},
- {0x404e, 0x01},
- {0x4241, 0x00},
- {0x4242, 0x00},
- {0x4300, 0xff},
- {0x4301, 0x00},
- {0x4501, 0x48},
- {0x4600, 0x00},
- {0x4601, 0x4e},
- {0x4801, 0x0f},
- {0x4806, 0x0f},
- {0x4819, 0xaa},
- {0x4823, 0x3e},
- {0x4837, 0x19},
- {0x4a0d, 0x00},
- {0x4a47, 0x7f},
- {0x4a49, 0xf0},
- {0x4a4b, 0x30},
- {0x5000, 0x85},
- {0x5001, 0x80},
- {REG_NULL, 0x00},
+static __maybe_unused const struct regval ov7251_setting_vga_30fps[] = {
+ { 0x3005, 0x00 },
+ { 0x3012, 0xc0 },
+ { 0x3013, 0xd2 },
+ { 0x3014, 0x04 },
+ { 0x3016, 0xf0 },
+ { 0x3017, 0xf0 },
+ { 0x3018, 0xf0 },
+ { 0x301a, 0xf0 },
+ { 0x301b, 0xf0 },
+ { 0x301c, 0xf0 },
+ { 0x3023, 0x05 },
+ { 0x3037, 0xf0 },
+ { 0x3098, 0x04 }, /* pll2 pre divider */
+ { 0x3099, 0x28 }, /* pll2 multiplier */
+ { 0x309a, 0x05 }, /* pll2 sys divider */
+ { 0x309b, 0x04 }, /* pll2 adc divider */
+ { 0x309d, 0x00 }, /* pll2 divider */
+ { 0x30b0, 0x0a }, /* pll1 pix divider */
+ { 0x30b1, 0x01 }, /* pll1 divider */
+ { 0x30b3, 0x64 }, /* pll1 multiplier */
+ { 0x30b4, 0x03 }, /* pll1 pre divider */
+ { 0x30b5, 0x05 }, /* pll1 mipi divider */
+ { 0x3106, 0xda },
+ { 0x3503, 0x07 },
+ { 0x3509, 0x10 },
+ { 0x3600, 0x1c },
+ { 0x3602, 0x62 },
+ { 0x3620, 0xb7 },
+ { 0x3622, 0x04 },
+ { 0x3626, 0x21 },
+ { 0x3627, 0x30 },
+ { 0x3630, 0x44 },
+ { 0x3631, 0x35 },
+ { 0x3634, 0x60 },
+ { 0x3636, 0x00 },
+ { 0x3662, 0x01 },
+ { 0x3663, 0x70 },
+ { 0x3664, 0x50 },
+ { 0x3666, 0x0a },
+ { 0x3669, 0x1a },
+ { 0x366a, 0x00 },
+ { 0x366b, 0x50 },
+ { 0x3673, 0x01 },
+ { 0x3674, 0xff },
+ { 0x3675, 0x03 },
+ { 0x3705, 0xc1 },
+ { 0x3709, 0x40 },
+ { 0x373c, 0x08 },
+ { 0x3742, 0x00 },
+ { 0x3757, 0xb3 },
+ { 0x3788, 0x00 },
+ { 0x37a8, 0x01 },
+ { 0x37a9, 0xc0 },
+ { 0x3800, 0x00 },
+ { 0x3801, 0x04 },
+ { 0x3802, 0x00 },
+ { 0x3803, 0x04 },
+ { 0x3804, 0x02 },
+ { 0x3805, 0x8b },
+ { 0x3806, 0x01 },
+ { 0x3807, 0xeb },
+ { 0x3808, 0x02 }, /* width high */
+ { 0x3809, 0x80 }, /* width low */
+ { 0x380a, 0x01 }, /* height high */
+ { 0x380b, 0xe0 }, /* height low */
+ { 0x380c, 0x03 }, /* total horiz timing high */
+ { 0x380d, 0xa0 }, /* total horiz timing low */
+ { 0x380e, 0x06 }, /* total vertical timing high */
+ { 0x380f, 0xbc }, /* total vertical timing low */
+ { 0x3810, 0x00 },
+ { 0x3811, 0x04 },
+ { 0x3812, 0x00 },
+ { 0x3813, 0x05 },
+ { 0x3814, 0x11 },
+ { 0x3815, 0x11 },
+ { 0x3820, 0x40 },
+ { 0x3821, 0x00 },
+ { 0x382f, 0x0e },
+ { 0x3832, 0x00 },
+ { 0x3833, 0x05 },
+ { 0x3834, 0x00 },
+ { 0x3835, 0x0c },
+ { 0x3837, 0x00 },
+ { 0x3b80, 0x00 },
+ { 0x3b81, 0xa5 },
+ { 0x3b82, 0x10 },
+ { 0x3b83, 0x00 },
+ { 0x3b84, 0x08 },
+ { 0x3b85, 0x00 },
+ { 0x3b86, 0x01 },
+ { 0x3b87, 0x00 },
+ { 0x3b88, 0x00 },
+ { 0x3b89, 0x00 },
+ { 0x3b8a, 0x00 },
+ { 0x3b8b, 0x05 },
+ { 0x3b8c, 0x00 },
+ { 0x3b8d, 0x00 },
+ { 0x3b8e, 0x00 },
+ { 0x3b8f, 0x1a },
+ { 0x3b94, 0x05 },
+ { 0x3b95, 0xf2 },
+ { 0x3b96, 0x40 },
+ { 0x3c00, 0x89 },
+ { 0x3c01, 0x63 },
+ { 0x3c02, 0x01 },
+ { 0x3c03, 0x00 },
+ { 0x3c04, 0x00 },
+ { 0x3c05, 0x03 },
+ { 0x3c06, 0x00 },
+ { 0x3c07, 0x06 },
+ { 0x3c0c, 0x01 },
+ { 0x3c0d, 0xd0 },
+ { 0x3c0e, 0x02 },
+ { 0x3c0f, 0x0a },
+ { 0x4001, 0x42 },
+ { 0x4004, 0x04 },
+ { 0x4005, 0x00 },
+ { 0x404e, 0x01 },
+ { 0x4300, 0xff },
+ { 0x4301, 0x00 },
+ { 0x4315, 0x00 },
+ { 0x4501, 0x48 },
+ { 0x4600, 0x00 },
+ { 0x4601, 0x4e },
+ { 0x4801, 0x0f },
+ { 0x4806, 0x0f },
+ { 0x4819, 0xaa },
+ { 0x4823, 0x3e },
+ { 0x4837, 0x19 },
+ { 0x4a0d, 0x00 },
+ { 0x4a47, 0x7f },
+ { 0x4a49, 0xf0 },
+ { 0x4a4b, 0x30 },
+ { 0x5000, 0x85 },
+ { 0x5001, 0x80 },
+ {REG_NULL, 0x00 },
+};
+
+static __maybe_unused const struct regval ov7251_setting_vga_60fps[] = {
+ { 0x3005, 0x00 },
+ { 0x3012, 0xc0 },
+ { 0x3013, 0xd2 },
+ { 0x3014, 0x04 },
+ { 0x3016, 0x10 },
+ { 0x3017, 0x00 },
+ { 0x3018, 0x00 },
+ { 0x301a, 0x00 },
+ { 0x301b, 0x00 },
+ { 0x301c, 0x00 },
+ { 0x3023, 0x05 },
+ { 0x3037, 0xf0 },
+ { 0x3098, 0x04 }, /* pll2 pre divider */
+ { 0x3099, 0x28 }, /* pll2 multiplier */
+ { 0x309a, 0x05 }, /* pll2 sys divider */
+ { 0x309b, 0x04 }, /* pll2 adc divider */
+ { 0x309d, 0x00 }, /* pll2 divider */
+ { 0x30b0, 0x0a }, /* pll1 pix divider */
+ { 0x30b1, 0x01 }, /* pll1 divider */
+ { 0x30b3, 0x64 }, /* pll1 multiplier */
+ { 0x30b4, 0x03 }, /* pll1 pre divider */
+ { 0x30b5, 0x05 }, /* pll1 mipi divider */
+ { 0x3106, 0xda },
+ { 0x3503, 0x07 },
+ { 0x3509, 0x10 },
+ { 0x3600, 0x1c },
+ { 0x3602, 0x62 },
+ { 0x3620, 0xb7 },
+ { 0x3622, 0x04 },
+ { 0x3626, 0x21 },
+ { 0x3627, 0x30 },
+ { 0x3630, 0x44 },
+ { 0x3631, 0x35 },
+ { 0x3634, 0x60 },
+ { 0x3636, 0x00 },
+ { 0x3662, 0x01 },
+ { 0x3663, 0x70 },
+ { 0x3664, 0x50 },
+ { 0x3666, 0x0a },
+ { 0x3669, 0x1a },
+ { 0x366a, 0x00 },
+ { 0x366b, 0x50 },
+ { 0x3673, 0x01 },
+ { 0x3674, 0xff },
+ { 0x3675, 0x03 },
+ { 0x3705, 0xc1 },
+ { 0x3709, 0x40 },
+ { 0x373c, 0x08 },
+ { 0x3742, 0x00 },
+ { 0x3757, 0xb3 },
+ { 0x3788, 0x00 },
+ { 0x37a8, 0x01 },
+ { 0x37a9, 0xc0 },
+ { 0x3800, 0x00 },
+ { 0x3801, 0x04 },
+ { 0x3802, 0x00 },
+ { 0x3803, 0x04 },
+ { 0x3804, 0x02 },
+ { 0x3805, 0x8b },
+ { 0x3806, 0x01 },
+ { 0x3807, 0xeb },
+ { 0x3808, 0x02 }, /* width high */
+ { 0x3809, 0x80 }, /* width low */
+ { 0x380a, 0x01 }, /* height high */
+ { 0x380b, 0xe0 }, /* height low */
+ { 0x380c, 0x03 }, /* total horiz timing high */
+ { 0x380d, 0xa0 }, /* total horiz timing low */
+ { 0x380e, 0x03 }, /* total vertical timing high */
+ { 0x380f, 0x5c }, /* total vertical timing low */
+ { 0x3810, 0x00 },
+ { 0x3811, 0x04 },
+ { 0x3812, 0x00 },
+ { 0x3813, 0x05 },
+ { 0x3814, 0x11 },
+ { 0x3815, 0x11 },
+ { 0x3820, 0x40 },
+ { 0x3821, 0x00 },
+ { 0x382f, 0x0e },
+ { 0x3832, 0x00 },
+ { 0x3833, 0x05 },
+ { 0x3834, 0x00 },
+ { 0x3835, 0x0c },
+ { 0x3837, 0x00 },
+ { 0x3b80, 0x00 },
+ { 0x3b81, 0xa5 },
+ { 0x3b82, 0x10 },
+ { 0x3b83, 0x00 },
+ { 0x3b84, 0x08 },
+ { 0x3b85, 0x00 },
+ { 0x3b86, 0x01 },
+ { 0x3b87, 0x00 },
+ { 0x3b88, 0x00 },
+ { 0x3b89, 0x00 },
+ { 0x3b8a, 0x00 },
+ { 0x3b8b, 0x05 },
+ { 0x3b8c, 0x00 },
+ { 0x3b8d, 0x00 },
+ { 0x3b8e, 0x00 },
+ { 0x3b8f, 0x1a },
+ { 0x3b94, 0x05 },
+ { 0x3b95, 0xf2 },
+ { 0x3b96, 0x40 },
+ { 0x3c00, 0x89 },
+ { 0x3c01, 0x63 },
+ { 0x3c02, 0x01 },
+ { 0x3c03, 0x00 },
+ { 0x3c04, 0x00 },
+ { 0x3c05, 0x03 },
+ { 0x3c06, 0x00 },
+ { 0x3c07, 0x06 },
+ { 0x3c0c, 0x01 },
+ { 0x3c0d, 0xd0 },
+ { 0x3c0e, 0x02 },
+ { 0x3c0f, 0x0a },
+ { 0x4001, 0x42 },
+ { 0x4004, 0x04 },
+ { 0x4005, 0x00 },
+ { 0x404e, 0x01 },
+ { 0x4300, 0xff },
+ { 0x4301, 0x00 },
+ { 0x4315, 0x00 },
+ { 0x4501, 0x48 },
+ { 0x4600, 0x00 },
+ { 0x4601, 0x4e },
+ { 0x4801, 0x0f },
+ { 0x4806, 0x0f },
+ { 0x4819, 0xaa },
+ { 0x4823, 0x3e },
+ { 0x4837, 0x19 },
+ { 0x4a0d, 0x00 },
+ { 0x4a47, 0x7f },
+ { 0x4a49, 0xf0 },
+ { 0x4a4b, 0x30 },
+ { 0x5000, 0x85 },
+ { 0x5001, 0x80 },
+ {REG_NULL, 0x00 },
+};
+
+static __maybe_unused const struct regval ov7251_setting_vga_90fps[] = {
+ { 0x3005, 0x00 },
+ { 0x3012, 0xc0 },
+ { 0x3013, 0xd2 },
+ { 0x3014, 0x04 },
+ { 0x3016, 0x10 },
+ { 0x3017, 0x00 },
+ { 0x3018, 0x00 },
+ { 0x301a, 0x00 },
+ { 0x301b, 0x00 },
+ { 0x301c, 0x00 },
+ { 0x3023, 0x05 },
+ { 0x3037, 0xf0 },
+ { 0x3098, 0x04 }, /* pll2 pre divider */
+ { 0x3099, 0x28 }, /* pll2 multiplier */
+ { 0x309a, 0x05 }, /* pll2 sys divider */
+ { 0x309b, 0x04 }, /* pll2 adc divider */
+ { 0x309d, 0x00 }, /* pll2 divider */
+ { 0x30b0, 0x0a }, /* pll1 pix divider */
+ { 0x30b1, 0x01 }, /* pll1 divider */
+ { 0x30b3, 0x64 }, /* pll1 multiplier */
+ { 0x30b4, 0x03 }, /* pll1 pre divider */
+ { 0x30b5, 0x05 }, /* pll1 mipi divider */
+ { 0x3106, 0xda },
+ { 0x3503, 0x07 },
+ { 0x3509, 0x10 },
+ { 0x3600, 0x1c },
+ { 0x3602, 0x62 },
+ { 0x3620, 0xb7 },
+ { 0x3622, 0x04 },
+ { 0x3626, 0x21 },
+ { 0x3627, 0x30 },
+ { 0x3630, 0x44 },
+ { 0x3631, 0x35 },
+ { 0x3634, 0x60 },
+ { 0x3636, 0x00 },
+ { 0x3662, 0x01 },
+ { 0x3663, 0x70 },
+ { 0x3664, 0x50 },
+ { 0x3666, 0x0a },
+ { 0x3669, 0x1a },
+ { 0x366a, 0x00 },
+ { 0x366b, 0x50 },
+ { 0x3673, 0x01 },
+ { 0x3674, 0xff },
+ { 0x3675, 0x03 },
+ { 0x3705, 0xc1 },
+ { 0x3709, 0x40 },
+ { 0x373c, 0x08 },
+ { 0x3742, 0x00 },
+ { 0x3757, 0xb3 },
+ { 0x3788, 0x00 },
+ { 0x37a8, 0x01 },
+ { 0x37a9, 0xc0 },
+ { 0x3800, 0x00 },
+ { 0x3801, 0x04 },
+ { 0x3802, 0x00 },
+ { 0x3803, 0x04 },
+ { 0x3804, 0x02 },
+ { 0x3805, 0x8b },
+ { 0x3806, 0x01 },
+ { 0x3807, 0xeb },
+ { 0x3808, 0x02 }, /* width high */
+ { 0x3809, 0x80 }, /* width low */
+ { 0x380a, 0x01 }, /* height high */
+ { 0x380b, 0xe0 }, /* height low */
+ { 0x380c, 0x03 }, /* total horiz timing high */
+ { 0x380d, 0xa0 }, /* total horiz timing low */
+ { 0x380e, 0x02 }, /* total vertical timing high */
+ { 0x380f, 0x3c }, /* total vertical timing low */
+ { 0x3810, 0x00 },
+ { 0x3811, 0x04 },
+ { 0x3812, 0x00 },
+ { 0x3813, 0x05 },
+ { 0x3814, 0x11 },
+ { 0x3815, 0x11 },
+ { 0x3820, 0x40 },
+ { 0x3821, 0x00 },
+ { 0x382f, 0x0e },
+ { 0x3832, 0x00 },
+ { 0x3833, 0x05 },
+ { 0x3834, 0x00 },
+ { 0x3835, 0x0c },
+ { 0x3837, 0x00 },
+ { 0x3b80, 0x00 },
+ { 0x3b81, 0xa5 },
+ { 0x3b82, 0x10 },
+ { 0x3b83, 0x00 },
+ { 0x3b84, 0x08 },
+ { 0x3b85, 0x00 },
+ { 0x3b86, 0x01 },
+ { 0x3b87, 0x00 },
+ { 0x3b88, 0x00 },
+ { 0x3b89, 0x00 },
+ { 0x3b8a, 0x00 },
+ { 0x3b8b, 0x05 },
+ { 0x3b8c, 0x00 },
+ { 0x3b8d, 0x00 },
+ { 0x3b8e, 0x00 },
+ { 0x3b8f, 0x1a },
+ { 0x3b94, 0x05 },
+ { 0x3b95, 0xf2 },
+ { 0x3b96, 0x40 },
+ { 0x3c00, 0x89 },
+ { 0x3c01, 0x63 },
+ { 0x3c02, 0x01 },
+ { 0x3c03, 0x00 },
+ { 0x3c04, 0x00 },
+ { 0x3c05, 0x03 },
+ { 0x3c06, 0x00 },
+ { 0x3c07, 0x06 },
+ { 0x3c0c, 0x01 },
+ { 0x3c0d, 0xd0 },
+ { 0x3c0e, 0x02 },
+ { 0x3c0f, 0x0a },
+ { 0x4001, 0x42 },
+ { 0x4004, 0x04 },
+ { 0x4005, 0x00 },
+ { 0x404e, 0x01 },
+ { 0x4300, 0xff },
+ { 0x4301, 0x00 },
+ { 0x4315, 0x00 },
+ { 0x4501, 0x48 },
+ { 0x4600, 0x00 },
+ { 0x4601, 0x4e },
+ { 0x4801, 0x0f },
+ { 0x4806, 0x0f },
+ { 0x4819, 0xaa },
+ { 0x4823, 0x3e },
+ { 0x4837, 0x19 },
+ { 0x4a0d, 0x00 },
+ { 0x4a47, 0x7f },
+ { 0x4a49, 0xf0 },
+ { 0x4a4b, 0x30 },
+ { 0x5000, 0x85 },
+ { 0x5001, 0x80 },
+ {REG_NULL, 0x00 },
};
static const struct ov7251_mode supported_modes[] = {
@@ -455,44 +729,34 @@
.exp_def = 0x00f8,
.hts_def = 0x03a1,
.vts_def = 0x021a,
+ .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
.reg_list = ov7251_640x480_120fps_regs,
- .hdr_mode = 0,
- },
- {
- .width = 640,
- .height = 480,
- .max_fps = {
- .numerator = 10000,
- .denominator = 300000,
- },
- .exp_def = 0x061c,
- .hts_def = 0x03a0,
- .vts_def = 0x06b8,
- .reg_list = ov7251_640x480_30fps_regs,
- .hdr_mode = 0,
+ .hdr_mode = NO_HDR,
+ .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
}
};
-#define OV7251_LINK_FREQ_320MHZ 320000000
static const s64 link_freq_menu_items[] = {
- OV7251_LINK_FREQ_320MHZ
+ OV7251_LINK_FREQ_240
};
static const char * const ov7251_test_pattern_menu[] = {
"Disabled",
- "Vertical Color Bar",
+ "Vertical Color Bar Type 1",
+ "Vertical Color Bar Type 2",
+ "Vertical Color Bar Type 3",
+ "Vertical Color Bar Type 4"
};
/* Write registers up to 4 at a time */
static int ov7251_write_reg(struct i2c_client *client, u16 reg,
- int len, u32 val)
+ u32 len, u32 val)
{
u32 buf_i, val_i;
u8 buf[6];
u8 *val_p;
__be32 val_be;
- usleep_range(1500, 1600);
if (len > 4)
return -EINVAL;
@@ -509,26 +773,25 @@
if (i2c_master_send(client, buf, len + 2) != len + 2)
return -EIO;
-
return 0;
}
static int ov7251_write_array(struct i2c_client *client,
- const struct regval *regs)
+ const struct regval *regs)
{
u32 i;
int ret = 0;
- for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++)
+ for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) {
ret = ov7251_write_reg(client, regs[i].addr,
- OV7251_REG_VALUE_08BIT, regs[i].val);
-
+ OV7251_REG_VALUE_08BIT, regs[i].val);
+ }
return ret;
}
/* Read registers up to 4 at a time */
static int ov7251_read_reg(struct i2c_client *client, u16 reg, unsigned int len,
- u32 *val)
+ u32 *val)
{
struct i2c_msg msgs[2];
u8 *data_be_p;
@@ -561,8 +824,10 @@
return 0;
}
+
+
static int ov7251_get_reso_dist(const struct ov7251_mode *mode,
- struct v4l2_mbus_framefmt *framefmt)
+ struct v4l2_mbus_framefmt *framefmt)
{
return abs(mode->width - framefmt->width) +
abs(mode->height - framefmt->height);
@@ -575,7 +840,7 @@
int dist;
int cur_best_fit = 0;
int cur_best_fit_dist = -1;
- size_t i;
+ unsigned int i;
for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
dist = ov7251_get_reso_dist(&supported_modes[i], framefmt);
@@ -589,8 +854,8 @@
}
static int ov7251_set_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *fmt)
{
struct ov7251 *ov7251 = to_ov7251(sd);
const struct ov7251_mode *mode;
@@ -599,7 +864,7 @@
mutex_lock(&ov7251->mutex);
mode = ov7251_find_best_fit(fmt);
- fmt->format.code = PIX_FORMAT;
+ fmt->format.code = mode->bus_fmt;
fmt->format.width = mode->width;
fmt->format.height = mode->height;
fmt->format.field = V4L2_FIELD_NONE;
@@ -619,6 +884,7 @@
__v4l2_ctrl_modify_range(ov7251->vblank, vblank_def,
OV7251_VTS_MAX - mode->height,
1, vblank_def);
+ ov7251->cur_fps = mode->max_fps;
}
mutex_unlock(&ov7251->mutex);
@@ -627,8 +893,8 @@
}
static int ov7251_get_fmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *fmt)
{
struct ov7251 *ov7251 = to_ov7251(sd);
const struct ov7251_mode *mode = ov7251->cur_mode;
@@ -644,8 +910,13 @@
} else {
fmt->format.width = mode->width;
fmt->format.height = mode->height;
- fmt->format.code = PIX_FORMAT;
+ fmt->format.code = mode->bus_fmt;
fmt->format.field = V4L2_FIELD_NONE;
+ /* format info: width/height/data type/virctual channel */
+ if (fmt->pad < PAD_MAX && mode->hdr_mode != NO_HDR)
+ fmt->reserved[0] = mode->vc[fmt->pad];
+ else
+ fmt->reserved[0] = mode->vc[PAD0];
}
mutex_unlock(&ov7251->mutex);
@@ -653,24 +924,26 @@
}
static int ov7251_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
+ struct ov7251 *ov7251 = to_ov7251(sd);
+
if (code->index != 0)
return -EINVAL;
- code->code = PIX_FORMAT;
+ code->code = ov7251->cur_mode->bus_fmt;
return 0;
}
static int ov7251_enum_frame_sizes(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_frame_size_enum *fse)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_frame_size_enum *fse)
{
if (fse->index >= ARRAY_SIZE(supported_modes))
return -EINVAL;
- if (fse->code != PIX_FORMAT)
+ if (fse->code != supported_modes[0].bus_fmt)
return -EINVAL;
fse->min_width = supported_modes[fse->index].width;
@@ -695,20 +968,42 @@
}
static int ov7251_g_frame_interval(struct v4l2_subdev *sd,
- struct v4l2_subdev_frame_interval *fi)
+ struct v4l2_subdev_frame_interval *fi)
{
struct ov7251 *ov7251 = to_ov7251(sd);
const struct ov7251_mode *mode = ov7251->cur_mode;
- mutex_lock(&ov7251->mutex);
- fi->interval = mode->max_fps;
- mutex_unlock(&ov7251->mutex);
+ if (ov7251->streaming)
+ fi->interval = ov7251->cur_fps;
+ else
+ fi->interval = mode->max_fps;
+
+ return 0;
+}
+
+static int ov7251_g_mbus_config(struct v4l2_subdev *sd,
+ unsigned int pad_id,
+ struct v4l2_mbus_config *config)
+{
+ struct ov7251 *ov7251 = to_ov7251(sd);
+ const struct ov7251_mode *mode = ov7251->cur_mode;
+ u32 val = 1 << (OV7251_LANES - 1) |
+ V4L2_MBUS_CSI2_CHANNEL_0 |
+ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+
+ if (mode->hdr_mode != NO_HDR)
+ val |= V4L2_MBUS_CSI2_CHANNEL_1;
+ if (mode->hdr_mode == HDR_X3)
+ val |= V4L2_MBUS_CSI2_CHANNEL_2;
+
+ config->type = V4L2_MBUS_CSI2_DPHY;
+ config->flags = val;
return 0;
}
static void ov7251_get_module_inf(struct ov7251 *ov7251,
- struct rkmodule_inf *inf)
+ struct rkmodule_inf *inf)
{
memset(inf, 0, sizeof(*inf));
strscpy(inf->base.sensor, OV7251_NAME, sizeof(inf->base.sensor));
@@ -721,6 +1016,7 @@
{
struct ov7251 *ov7251 = to_ov7251(sd);
struct rkmodule_hdr_cfg *hdr;
+ u32 i, h, w;
long ret = 0;
u32 stream = 0;
@@ -735,20 +1031,44 @@
break;
case RKMODULE_SET_HDR_CFG:
hdr = (struct rkmodule_hdr_cfg *)arg;
- if (hdr->hdr_mode != 0)
- ret = -1;
+ w = ov7251->cur_mode->width;
+ h = ov7251->cur_mode->height;
+ for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
+ if (w == supported_modes[i].width &&
+ h == supported_modes[i].height &&
+ supported_modes[i].hdr_mode == hdr->hdr_mode) {
+ ov7251->cur_mode = &supported_modes[i];
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(supported_modes)) {
+ dev_err(&ov7251->client->dev,
+ "not find hdr mode:%d %dx%d config\n",
+ hdr->hdr_mode, w, h);
+ ret = -EINVAL;
+ } else {
+ w = ov7251->cur_mode->hts_def - ov7251->cur_mode->width;
+ h = ov7251->cur_mode->vts_def - ov7251->cur_mode->height;
+ __v4l2_ctrl_modify_range(ov7251->hblank, w, w, 1, w);
+ __v4l2_ctrl_modify_range(ov7251->vblank, h,
+ OV7251_VTS_MAX - ov7251->cur_mode->height, 1, h);
+ }
+ break;
+ case PREISP_CMD_SET_HDRAE_EXP:
break;
case RKMODULE_SET_QUICK_STREAM:
+
stream = *((u32 *)arg);
+
if (stream)
ret = ov7251_write_reg(ov7251->client, OV7251_REG_CTRL_MODE,
- OV7251_REG_VALUE_08BIT, OV7251_MODE_STREAMING);
+ OV7251_REG_VALUE_08BIT, OV7251_MODE_STREAMING);
else
ret = ov7251_write_reg(ov7251->client, OV7251_REG_CTRL_MODE,
- OV7251_REG_VALUE_08BIT, OV7251_MODE_SW_STANDBY);
+ OV7251_REG_VALUE_08BIT, OV7251_MODE_SW_STANDBY);
break;
default:
- ret = -ENOTTY;
+ ret = -ENOIOCTLCMD;
break;
}
@@ -757,11 +1077,12 @@
#ifdef CONFIG_COMPAT
static long ov7251_compat_ioctl32(struct v4l2_subdev *sd,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
void __user *up = compat_ptr(arg);
struct rkmodule_inf *inf;
struct rkmodule_hdr_cfg *hdr;
+ struct preisp_hdrae_exp_s *hdrae;
long ret;
u32 stream = 0;
@@ -775,8 +1096,7 @@
ret = ov7251_ioctl(sd, cmd, inf);
if (!ret) {
- ret = copy_to_user(up, inf, sizeof(*inf));
- if (ret)
+ if (copy_to_user(up, inf, sizeof(*inf)))
ret = -EFAULT;
}
kfree(inf);
@@ -790,8 +1110,7 @@
ret = ov7251_ioctl(sd, cmd, hdr);
if (!ret) {
- ret = copy_to_user(up, hdr, sizeof(*hdr));
- if (ret)
+ if (copy_to_user(up, hdr, sizeof(*hdr)))
ret = -EFAULT;
}
kfree(hdr);
@@ -803,19 +1122,33 @@
return ret;
}
- if (copy_from_user(hdr, up, sizeof(*hdr))) {
- kfree(hdr);
- return -EFAULT;
- }
-
- ret = ov7251_ioctl(sd, cmd, hdr);
+ ret = copy_from_user(hdr, up, sizeof(*hdr));
+ if (!ret)
+ ret = ov7251_ioctl(sd, cmd, hdr);
+ else
+ ret = -EFAULT;
kfree(hdr);
break;
- case RKMODULE_SET_QUICK_STREAM:
- if (copy_from_user(&stream, up, sizeof(u32)))
- return -EFAULT;
+ case PREISP_CMD_SET_HDRAE_EXP:
+ hdrae = kzalloc(sizeof(*hdrae), GFP_KERNEL);
+ if (!hdrae) {
+ ret = -ENOMEM;
+ return ret;
+ }
- ret = ov7251_ioctl(sd, cmd, &stream);
+ ret = copy_from_user(hdrae, up, sizeof(*hdrae));
+ if (!ret)
+ ret = ov7251_ioctl(sd, cmd, hdrae);
+ else
+ ret = -EFAULT;
+ kfree(hdrae);
+ break;
+ case RKMODULE_SET_QUICK_STREAM:
+ ret = copy_from_user(&stream, up, sizeof(u32));
+ if (!ret)
+ ret = ov7251_ioctl(sd, cmd, &stream);
+ else
+ ret = -EFAULT;
break;
default:
ret = -ENOIOCTLCMD;
@@ -835,20 +1168,18 @@
return ret;
/* In case these controls are set before streaming */
- mutex_unlock(&ov7251->mutex);
- ret = v4l2_ctrl_handler_setup(&ov7251->ctrl_handler);
- mutex_lock(&ov7251->mutex);
+ ret = __v4l2_ctrl_handler_setup(&ov7251->ctrl_handler);
if (ret)
return ret;
return ov7251_write_reg(ov7251->client, OV7251_REG_CTRL_MODE,
- OV7251_REG_VALUE_08BIT, OV7251_MODE_STREAMING);
+ OV7251_REG_VALUE_08BIT, OV7251_MODE_STREAMING);
}
static int __ov7251_stop_stream(struct ov7251 *ov7251)
{
return ov7251_write_reg(ov7251->client, OV7251_REG_CTRL_MODE,
- OV7251_REG_VALUE_08BIT, OV7251_MODE_SW_STANDBY);
+ OV7251_REG_VALUE_08BIT, OV7251_MODE_SW_STANDBY);
}
static int ov7251_s_stream(struct v4l2_subdev *sd, int on)
@@ -868,6 +1199,7 @@
pm_runtime_put_noidle(&client->dev);
goto unlock_and_return;
}
+
ret = __ov7251_start_stream(ov7251);
if (ret) {
v4l2_err(sd, "start stream failed while write regs\n");
@@ -907,6 +1239,13 @@
goto unlock_and_return;
}
+ ret = ov7251_write_array(ov7251->client, ov7251_global_regs);
+ if (ret) {
+ v4l2_err(sd, "could not set init registers\n");
+ pm_runtime_put_noidle(&client->dev);
+ goto unlock_and_return;
+ }
+
ov7251->power_on = true;
} else {
pm_runtime_put(&client->dev);
@@ -937,12 +1276,11 @@
if (ret < 0)
dev_err(dev, "could not set pins\n");
}
-
ret = clk_set_rate(ov7251->xvclk, OV7251_XVCLK_FREQ);
if (ret < 0)
- dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
+ dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
if (clk_get_rate(ov7251->xvclk) != OV7251_XVCLK_FREQ)
- dev_err(dev, "xvclk mismatched, modes are based on 24MHz\n");
+ dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
ret = clk_prepare_enable(ov7251->xvclk);
if (ret < 0) {
dev_err(dev, "Failed to enable xvclk\n");
@@ -950,7 +1288,7 @@
}
if (!IS_ERR(ov7251->reset_gpio))
- gpiod_set_value_cansleep(ov7251->reset_gpio, 1);
+ gpiod_set_value_cansleep(ov7251->reset_gpio, 0);
ret = regulator_bulk_enable(OV7251_NUM_SUPPLIES, ov7251->supplies);
if (ret < 0) {
@@ -958,13 +1296,18 @@
goto disable_clk;
}
- usleep_range(1000, 1100);
-
+ usleep_range(5 * 1000, 10 * 1000);
if (!IS_ERR(ov7251->reset_gpio))
- gpiod_set_value_cansleep(ov7251->reset_gpio, 0);
+ gpiod_set_value_cansleep(ov7251->reset_gpio, 1);
+ usleep_range(500, 1000);
if (!IS_ERR(ov7251->pwdn_gpio))
gpiod_set_value_cansleep(ov7251->pwdn_gpio, 1);
+
+ if (!IS_ERR(ov7251->reset_gpio))
+ usleep_range(6000, 8000);
+ else
+ usleep_range(12000, 16000);
/* 8192 cycles prior to first SCCB transaction */
delay_us = ov7251_cal_delay(8192);
@@ -975,9 +1318,6 @@
disable_clk:
clk_disable_unprepare(ov7251->xvclk);
- if (!IS_ERR_OR_NULL(ov7251->pins_sleep))
- pinctrl_select_state(ov7251->pinctrl, ov7251->pins_sleep);
-
return ret;
}
@@ -986,17 +1326,17 @@
int ret;
struct device *dev = &ov7251->client->dev;
+ if (!IS_ERR(ov7251->pwdn_gpio))
+ gpiod_set_value_cansleep(ov7251->pwdn_gpio, 0);
+ clk_disable_unprepare(ov7251->xvclk);
+ if (!IS_ERR(ov7251->reset_gpio))
+ gpiod_set_value_cansleep(ov7251->reset_gpio, 0);
if (!IS_ERR_OR_NULL(ov7251->pins_sleep)) {
ret = pinctrl_select_state(ov7251->pinctrl,
ov7251->pins_sleep);
if (ret < 0)
dev_dbg(dev, "could not set pins\n");
}
- if (!IS_ERR(ov7251->pwdn_gpio))
- gpiod_set_value_cansleep(ov7251->pwdn_gpio, 0);
- clk_disable_unprepare(ov7251->xvclk);
- if (!IS_ERR(ov7251->reset_gpio))
- gpiod_set_value_cansleep(ov7251->reset_gpio, 1);
regulator_bulk_disable(OV7251_NUM_SUPPLIES, ov7251->supplies);
}
@@ -1032,7 +1372,7 @@
/* Initialize try_fmt */
try_fmt->width = def_mode->width;
try_fmt->height = def_mode->height;
- try_fmt->code = PIX_FORMAT;
+ try_fmt->code = def_mode->bus_fmt;
try_fmt->field = V4L2_FIELD_NONE;
mutex_unlock(&ov7251->mutex);
@@ -1049,56 +1389,12 @@
if (fie->index >= ARRAY_SIZE(supported_modes))
return -EINVAL;
- if (fie->code != PIX_FORMAT)
- return -EINVAL;
-
+ fie->code = supported_modes[fie->index].bus_fmt;
fie->width = supported_modes[fie->index].width;
fie->height = supported_modes[fie->index].height;
fie->interval = supported_modes[fie->index].max_fps;
+ fie->reserved[0] = supported_modes[fie->index].hdr_mode;
return 0;
-}
-
-static int ov7251_g_mbus_config(struct v4l2_subdev *sd,
- struct v4l2_mbus_config *config)
-{
- u32 val = 0;
-
- val = 1 << (OV7251_LANES - 1) |
- V4L2_MBUS_CSI2_CHANNEL_0 |
- V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
- config->type = V4L2_MBUS_CSI2;
- config->flags = val;
-
- return 0;
-}
-
-#define CROP_START(SRC, DST) (((SRC) - (DST)) / 2 / 4 * 4)
-#define DST_WIDTH 640
-#define DST_HEIGHT 480
-
-/*
- * The resolution of the driver configuration needs to be exactly
- * the same as the current output resolution of the sensor,
- * the input width of the isp needs to be 16 aligned,
- * the input height of the isp needs to be 8 aligned.
- * Can be cropped to standard resolution by this function,
- * otherwise it will crop out strange resolution according
- * to the alignment rules.
- */
-static int ov7251_get_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_selection *sel)
-{
- struct ov7251 *ov7251 = to_ov7251(sd);
-
- if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) {
- sel->r.left = CROP_START(ov7251->cur_mode->width, DST_WIDTH);
- sel->r.width = DST_WIDTH;
- sel->r.top = CROP_START(ov7251->cur_mode->height, DST_HEIGHT);
- sel->r.height = DST_HEIGHT;
- return 0;
- }
- return -EINVAL;
}
static const struct dev_pm_ops ov7251_pm_ops = {
@@ -1123,7 +1419,6 @@
static const struct v4l2_subdev_video_ops ov7251_video_ops = {
.s_stream = ov7251_s_stream,
.g_frame_interval = ov7251_g_frame_interval,
- .g_mbus_config = ov7251_g_mbus_config,
};
static const struct v4l2_subdev_pad_ops ov7251_pad_ops = {
@@ -1132,7 +1427,7 @@
.enum_frame_interval = ov7251_enum_frame_interval,
.get_fmt = ov7251_get_fmt,
.set_fmt = ov7251_set_fmt,
- .get_selection = ov7251_get_selection,
+ .get_mbus_config = ov7251_g_mbus_config,
};
static const struct v4l2_subdev_ops ov7251_subdev_ops = {
@@ -1144,10 +1439,11 @@
static int ov7251_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct ov7251 *ov7251 = container_of(ctrl->handler,
- struct ov7251, ctrl_handler);
+ struct ov7251, ctrl_handler);
struct i2c_client *client = ov7251->client;
s64 max;
int ret = 0;
+ u32 val = 0;
/* Propagate change of current control to all related controls */
switch (ctrl->id) {
@@ -1183,6 +1479,21 @@
case V4L2_CID_TEST_PATTERN:
ret = ov7251_enable_test_pattern(ov7251, ctrl->val);
break;
+ case V4L2_CID_HFLIP:
+ ret = ov7251_read_reg(ov7251->client, OV7251_MIRROR_REG,
+ OV7251_REG_VALUE_08BIT, &val);
+ ret |= ov7251_write_reg(ov7251->client, OV7251_MIRROR_REG,
+ OV7251_REG_VALUE_08BIT,
+ OV7251_FETCH_MIRROR(val, ctrl->val));
+ break;
+ case V4L2_CID_VFLIP:
+ ret = ov7251_read_reg(ov7251->client, OV7251_FLIP_REG,
+ OV7251_REG_VALUE_08BIT, &val);
+ ret |= ov7251_write_reg(ov7251->client, OV7251_FLIP_REG,
+ OV7251_REG_VALUE_08BIT,
+ OV7251_FETCH_FLIP(val, ctrl->val));
+ break;
+
default:
dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
__func__, ctrl->id, ctrl->val);
@@ -1209,7 +1520,7 @@
handler = &ov7251->ctrl_handler;
mode = ov7251->cur_mode;
- ret = v4l2_ctrl_handler_init(handler, 8);
+ ret = v4l2_ctrl_handler_init(handler, 9);
if (ret)
return ret;
handler->lock = &ov7251->mutex;
@@ -1220,36 +1531,38 @@
ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
- 0, OV7251_PIXEL_RATE, 1, OV7251_PIXEL_RATE);
+ 0, PIXEL_RATE_WITH_240M_10BIT, 1, PIXEL_RATE_WITH_240M_10BIT);
h_blank = mode->hts_def - mode->width;
ov7251->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
- h_blank, h_blank, 1, h_blank);
+ h_blank, h_blank, 1, h_blank);
if (ov7251->hblank)
ov7251->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
vblank_def = mode->vts_def - mode->height;
ov7251->vblank = v4l2_ctrl_new_std(handler, &ov7251_ctrl_ops,
- V4L2_CID_VBLANK, vblank_def,
- OV7251_VTS_MAX - mode->height,
- 1, vblank_def);
-
+ V4L2_CID_VBLANK, vblank_def,
+ OV7251_VTS_MAX - mode->height,
+ 1, vblank_def);
+ ov7251->cur_fps = mode->max_fps;
exposure_max = mode->vts_def - 20;
ov7251->exposure = v4l2_ctrl_new_std(handler, &ov7251_ctrl_ops,
- V4L2_CID_EXPOSURE, OV7251_EXPOSURE_MIN,
- exposure_max, OV7251_EXPOSURE_STEP,
- mode->exp_def);
-
+ V4L2_CID_EXPOSURE, OV7251_EXPOSURE_MIN,
+ exposure_max, OV7251_EXPOSURE_STEP,
+ mode->exp_def);
ov7251->anal_gain = v4l2_ctrl_new_std(handler, &ov7251_ctrl_ops,
V4L2_CID_ANALOGUE_GAIN, ANALOG_GAIN_MIN,
ANALOG_GAIN_MAX, ANALOG_GAIN_STEP,
ANALOG_GAIN_DEFAULT);
ov7251->test_pattern = v4l2_ctrl_new_std_menu_items(handler,
- &ov7251_ctrl_ops, V4L2_CID_TEST_PATTERN,
- ARRAY_SIZE(ov7251_test_pattern_menu) - 1,
- 0, 0, ov7251_test_pattern_menu);
-
+ &ov7251_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(ov7251_test_pattern_menu) - 1,
+ 0, 0, ov7251_test_pattern_menu);
+ v4l2_ctrl_new_std(handler, &ov7251_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(handler, &ov7251_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
if (handler->error) {
ret = handler->error;
dev_err(&ov7251->client->dev,
@@ -1268,14 +1581,14 @@
}
static int ov7251_check_sensor_id(struct ov7251 *ov7251,
- struct i2c_client *client)
+ struct i2c_client *client)
{
struct device *dev = &ov7251->client->dev;
u32 id = 0;
int ret;
ret = ov7251_read_reg(client, OV7251_REG_CHIP_ID,
- OV7251_REG_VALUE_16BIT, &id);
+ OV7251_REG_VALUE_08BIT, &id);
if (id != CHIP_ID) {
dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret);
return -ENODEV;
@@ -1288,7 +1601,7 @@
static int ov7251_configure_regulators(struct ov7251 *ov7251)
{
- size_t i;
+ unsigned int i;
for (i = 0; i < OV7251_NUM_SUPPLIES; i++)
ov7251->supplies[i].supply = ov7251_supply_names[i];
@@ -1299,7 +1612,7 @@
}
static int ov7251_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct device_node *node = dev->of_node;
@@ -1309,9 +1622,9 @@
int ret;
dev_info(dev, "driver version: %02x.%02x.%02x",
- DRIVER_VERSION >> 16,
- (DRIVER_VERSION & 0xff00) >> 8,
- DRIVER_VERSION & 0x00ff);
+ DRIVER_VERSION >> 16,
+ (DRIVER_VERSION & 0xff00) >> 8,
+ DRIVER_VERSION & 0x00ff);
ov7251 = devm_kzalloc(dev, sizeof(*ov7251), GFP_KERNEL);
if (!ov7251)
@@ -1347,27 +1660,29 @@
if (IS_ERR(ov7251->pwdn_gpio))
dev_warn(dev, "Failed to get pwdn-gpios\n");
- ret = ov7251_configure_regulators(ov7251);
- if (ret) {
- dev_err(dev, "Failed to get power regulators\n");
- return ret;
- }
ov7251->pinctrl = devm_pinctrl_get(dev);
if (!IS_ERR(ov7251->pinctrl)) {
ov7251->pins_default =
pinctrl_lookup_state(ov7251->pinctrl,
OF_CAMERA_PINCTRL_STATE_DEFAULT);
if (IS_ERR(ov7251->pins_default))
- dev_info(dev, "could not get default pinstate\n");
+ dev_err(dev, "could not get default pinstate\n");
ov7251->pins_sleep =
pinctrl_lookup_state(ov7251->pinctrl,
OF_CAMERA_PINCTRL_STATE_SLEEP);
if (IS_ERR(ov7251->pins_sleep))
- dev_info(dev, "could not get sleep pinstate\n");
+ dev_err(dev, "could not get sleep pinstate\n");
} else {
- dev_info(dev, "no pinctrl\n");
+ dev_err(dev, "no pinctrl\n");
}
+
+ ret = ov7251_configure_regulators(ov7251);
+ if (ret) {
+ dev_err(dev, "Failed to get power regulators\n");
+ return ret;
+ }
+
mutex_init(&ov7251->mutex);
sd = &ov7251->subdev;
--
Gitblit v1.6.2