From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB
---
kernel/drivers/media/i2c/imx464.c | 1043 ++++++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 872 insertions(+), 171 deletions(-)
diff --git a/kernel/drivers/media/i2c/imx464.c b/kernel/drivers/media/i2c/imx464.c
index 3458ff9..142550a 100644
--- a/kernel/drivers/media/i2c/imx464.c
+++ b/kernel/drivers/media/i2c/imx464.c
@@ -26,8 +26,11 @@
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mediabus.h>
#include <linux/pinctrl/consumer.h>
#include <linux/rk-preisp.h>
+#include <linux/of_graph.h>
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03)
@@ -42,15 +45,12 @@
#define OF_CAMERA_HDR_MODE "rockchip,camera-hdr-mode"
/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
-#define IMX464_10BIT_LINEAR_PIXEL_RATE (MIPI_FREQ_445M * 2 / 10 * 4)
#define IMX464_10BIT_HDR2_PIXEL_RATE (MIPI_FREQ_594M * 2 / 10 * 4)
-#define IMX464_10BIT_HDR3_PIXEL_RATE (MIPI_FREQ_594M * 2 / 10 * 4)
-#define IMX464_12BIT_PIXEL_RATE (MIPI_FREQ_360M * 2 / 12 * 4)
#define IMX464_XVCLK_FREQ_37M 37125000
#define IMX464_XVCLK_FREQ_24M 24000000
-#define CHIP_ID 0x00
-#define IMX464_REG_CHIP_ID 0x0000
+#define CHIP_ID 0x06
+#define IMX464_REG_CHIP_ID 0x3057
#define IMX464_REG_CTRL_MODE 0x3000
#define IMX464_MODE_SW_STANDBY BIT(0)
@@ -133,8 +133,6 @@
#define IMX464_REG_VALUE_16BIT 2
#define IMX464_REG_VALUE_24BIT 3
-#define IMX464_2LANES 2
-#define IMX464_4LANES 4
#define IMX464_BITS_PER_SAMPLE 10
#define IMX464_VREVERSE_REG 0x304f
@@ -150,12 +148,10 @@
#define USED_SYS_DEBUG
-static bool g_isHCG;
-
#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
#define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep"
-#define IMX464_NAME "IMX464"
+#define IMX464_NAME "imx464"
static const char * const IMX464_supply_names[] = {
"avdd", /* Analog power */
@@ -164,14 +160,6 @@
};
#define IMX464_NUM_SUPPLIES ARRAY_SIZE(IMX464_supply_names)
-
-enum IMX464_max_pad {
- PAD0, /* link to isp */
- PAD1, /* link to csi wr0 | hdr x2:L x3:M */
- PAD2, /* link to csi wr1 | hdr x3:L */
- PAD3, /* link to csi wr2 | hdr x2:M x3:S */
- PAD_MAX,
-};
struct regval {
u16 addr;
@@ -186,6 +174,9 @@
u32 hts_def;
u32 vts_def;
u32 exp_def;
+ u32 mipi_freq_idx;
+ u32 mclk;
+ u32 bpp;
const struct regval *reg_list;
u32 hdr_mode;
u32 vc[PAD_MAX];
@@ -213,19 +204,22 @@
struct v4l2_ctrl *pixel_rate;
struct v4l2_ctrl *link_freq;
struct mutex mutex;
+ struct v4l2_fwnode_endpoint bus_cfg;
bool streaming;
bool power_on;
+ bool has_init_exp;
+ const struct IMX464_mode *support_modes;
const struct IMX464_mode *cur_mode;
u32 module_index;
u32 cfg_num;
- u32 cur_pixel_rate;
- u32 cur_link_freq;
+ u32 cur_vts;
+ u32 cur_mclk;
const char *module_facing;
const char *module_name;
const char *len_name;
- u32 cur_vts;
- bool has_init_exp;
+ enum rkmodule_sync_mode sync_mode;
struct preisp_hdrae_exp_s init_hdrae_exp;
+ bool isHCG;
};
#define to_IMX464(sd) container_of(sd, struct IMX464, subdev)
@@ -237,16 +231,16 @@
{REG_NULL, 0x00},
};
-static const struct regval IMX464_linear_10bit_2688x1520_regs[] = {
+static __maybe_unused const struct regval IMX464_linear_10bit_2688x1520_2lane_37m_regs[] = {
{0x3000, 0x01},
{0x3002, 0x01},
{0x300C, 0x5B},
{0x300D, 0x40},
- {0x3030, 0xE4},
- {0x3031, 0x0C},
+ {0x3034, 0xDC},
+ {0x3035, 0x05},
{0x3050, 0x00},
- {0x3058, 0x06},
- {0x3059, 0x09},
+ {0x3058, 0x83},
+ {0x3059, 0x04},
{0x30BE, 0x5E},
{0x30E8, 0x14},
{0x3110, 0x02},
@@ -256,6 +250,488 @@
{0x319D, 0x00},
{0x319E, 0x02},
{0x31A1, 0x00},
+ {0x3288, 0x22},
+ {0x328A, 0x02},
+ {0x328C, 0xA2},
+ {0x328E, 0x22},
+ {0x3415, 0x27},
+ {0x3418, 0x27},
+ {0x3428, 0xFE},
+ {0x349E, 0x6A},
+ {0x34A2, 0x9A},
+ {0x34A4, 0x8A},
+ {0x34A6, 0x8E},
+ {0x34AA, 0xD8},
+ {0x35BC, 0x00},
+ {0x35BE, 0xFF},
+ {0x35CC, 0x1B},
+ {0x35CD, 0x00},
+ {0x35CE, 0x2A},
+ {0x35CF, 0x00},
+ {0x35DC, 0x07},
+ {0x35DE, 0x1A},
+ {0x35DF, 0x00},
+ {0x35E4, 0x2B},
+ {0x35E5, 0x00},
+ {0x35E6, 0x07},
+ {0x35E7, 0x01},
+ {0x3648, 0x01},
+ {0x3678, 0x01},
+ {0x367C, 0x69},
+ {0x367E, 0x69},
+ {0x3680, 0x69},
+ {0x3682, 0x69},
+ {0x3718, 0x1C},
+ {0x371D, 0x05},
+ {0x375D, 0x11},
+ {0x375E, 0x43},
+ {0x375F, 0x76},
+ {0x3760, 0x07},
+ {0x3768, 0x1B},
+ {0x3769, 0x1B},
+ {0x376A, 0x1A},
+ {0x376B, 0x19},
+ {0x376C, 0x17},
+ {0x376D, 0x0F},
+ {0x376E, 0x0B},
+ {0x376F, 0x0B},
+ {0x3770, 0x0B},
+ {0x3776, 0x89},
+ {0x3777, 0x00},
+ {0x3778, 0xCA},
+ {0x3779, 0x00},
+ {0x377A, 0x45},
+ {0x377B, 0x01},
+ {0x377C, 0x56},
+ {0x377D, 0x02},
+ {0x377E, 0xFE},
+ {0x377F, 0x03},
+ {0x3780, 0xFE},
+ {0x3781, 0x05},
+ {0x3782, 0xFE},
+ {0x3783, 0x06},
+ {0x3784, 0x7F},
+ {0x3788, 0x1F},
+ {0x378A, 0xCA},
+ {0x378B, 0x00},
+ {0x378C, 0x45},
+ {0x378D, 0x01},
+ {0x378E, 0x56},
+ {0x378F, 0x02},
+ {0x3790, 0xFE},
+ {0x3791, 0x03},
+ {0x3792, 0xFE},
+ {0x3793, 0x05},
+ {0x3794, 0xFE},
+ {0x3795, 0x06},
+ {0x3796, 0x7F},
+ {0x3798, 0xBF},
+ {0x3A01, 0x01},
+ {0x3A18, 0x7F},
+ {0x3A1A, 0x37},
+ {0x3A1C, 0x37},
+ {0x3A1E, 0xF7},
+ {0x3A1F, 0x00},
+ {0x3A20, 0x3F},
+ {0x3A22, 0x6F},
+ {0x3A24, 0x3F},
+ {0x3A26, 0x5F},
+ {0x3A28, 0x2F},
+ {REG_NULL, 0x00},
+};
+
+static __maybe_unused const struct regval IMX464_hdr_2x_10bit_2688x1520_2lane_37m_regs[] = {
+ {0x3000, 0x01},
+ {0x3002, 0x01},
+ {0x300C, 0x5B},
+ {0x300D, 0x40},
+ {0x3034, 0xDC},
+ {0x3035, 0x05},
+ {0x3048, 0x01},
+ {0x3049, 0x01},
+ {0x304A, 0x01},
+ {0x304B, 0x01},
+ {0x304C, 0x13},
+ {0x304D, 0x00},
+ {0x3050, 0x00},
+ {0x3058, 0xF4},
+ {0x3059, 0x0A},
+ {0x3068, 0x3D},
+ {0x30BE, 0x5E},
+ {0x30E8, 0x0A},
+ {0x3110, 0x02},
+ {0x314C, 0x80},//
+ {0x315A, 0x02},
+ {0x316A, 0x7E},
+ {0x319D, 0x00},
+ {0x319E, 0x01},//1188M
+ {0x31A1, 0x00},
+ {0x31D7, 0x01},
+ {0x3200, 0x10},
+ {0x3288, 0x22},
+ {0x328A, 0x02},
+ {0x328C, 0xA2},
+ {0x328E, 0x22},
+ {0x3415, 0x27},
+ {0x3418, 0x27},
+ {0x3428, 0xFE},
+ {0x349E, 0x6A},
+ {0x34A2, 0x9A},
+ {0x34A4, 0x8A},
+ {0x34A6, 0x8E},
+ {0x34AA, 0xD8},
+ {0x35BC, 0x00},
+ {0x35BE, 0xFF},
+ {0x35CC, 0x1B},
+ {0x35CD, 0x00},
+ {0x35CE, 0x2A},
+ {0x35CF, 0x00},
+ {0x35DC, 0x07},
+ {0x35DE, 0x1A},
+ {0x35DF, 0x00},
+ {0x35E4, 0x2B},
+ {0x35E5, 0x00},
+ {0x35E6, 0x07},
+ {0x35E7, 0x01},
+ {0x3648, 0x01},
+ {0x3678, 0x01},
+ {0x367C, 0x69},
+ {0x367E, 0x69},
+ {0x3680, 0x69},
+ {0x3682, 0x69},
+ {0x3718, 0x1C},
+ {0x371D, 0x05},
+ {0x375D, 0x11},
+ {0x375E, 0x43},
+ {0x375F, 0x76},
+ {0x3760, 0x07},
+ {0x3768, 0x1B},
+ {0x3769, 0x1B},
+ {0x376A, 0x1A},
+ {0x376B, 0x19},
+ {0x376C, 0x17},
+ {0x376D, 0x0F},
+ {0x376E, 0x0B},
+ {0x376F, 0x0B},
+ {0x3770, 0x0B},
+ {0x3776, 0x89},
+ {0x3777, 0x00},
+ {0x3778, 0xCA},
+ {0x3779, 0x00},
+ {0x377A, 0x45},
+ {0x377B, 0x01},
+ {0x377C, 0x56},
+ {0x377D, 0x02},
+ {0x377E, 0xFE},
+ {0x377F, 0x03},
+ {0x3780, 0xFE},
+ {0x3781, 0x05},
+ {0x3782, 0xFE},
+ {0x3783, 0x06},
+ {0x3784, 0x7F},
+ {0x3788, 0x1F},
+ {0x378A, 0xCA},
+ {0x378B, 0x00},
+ {0x378C, 0x45},
+ {0x378D, 0x01},
+ {0x378E, 0x56},
+ {0x378F, 0x02},
+ {0x3790, 0xFE},
+ {0x3791, 0x03},
+ {0x3792, 0xFE},
+ {0x3793, 0x05},
+ {0x3794, 0xFE},
+ {0x3795, 0x06},
+ {0x3796, 0x7F},
+ {0x3798, 0xBF},
+ {0x3A01, 0x01},
+ {0x3A18, 0x8F},
+ {0x3A1A, 0x4F},
+ {0x3A1C, 0x47},
+ {0x3A1E, 0x37},
+ {0x3A1F, 0x01},
+ {0x3A20, 0x4F},
+ {0x3A22, 0x87},
+ {0x3A24, 0x4F},
+ {0x3A26, 0x7F},
+ {0x3A28, 0x3F},
+ {REG_NULL, 0x00},
+};
+
+static const struct regval IMX464_linear_10bit_2688x1520_2lane_regs[] = {
+ {0x3000, 0x01},
+ {0x3002, 0x01},
+ {0x300C, 0x3b},
+ {0x300D, 0x2a},
+ {0x3034, 0xDC},
+ {0x3035, 0x05},
+ {0x3048, 0x00},
+ {0x3049, 0x00},
+ {0x304A, 0x03},
+ {0x304B, 0x02},
+ {0x304C, 0x14},
+ {0x304D, 0x03},
+ {0x3050, 0x00},
+ {0x3058, 0x83},
+ {0x3059, 0x04},
+ {0x3068, 0xc9},
+ {0x30BE, 0x5E},
+ {0x30E8, 0x14},
+ {0x3110, 0x02},
+ {0x314C, 0x29},
+ {0x314D, 0x01},
+ {0x315A, 0x06},
+ {0x3168, 0xA0},
+ {0x316A, 0x7E},
+ {0x319D, 0x00},
+ {0x319E, 0x02},
+ {0x31A1, 0x00},
+ {0x31D7, 0x00},
+ {0x3200, 0x11},
+ {0x3288, 0x22},
+ {0x328A, 0x02},
+ {0x328C, 0xA2},
+ {0x328E, 0x22},
+ {0x3415, 0x27},
+ {0x3418, 0x27},
+ {0x3428, 0xFE},
+ {0x349E, 0x6A},
+ {0x34A2, 0x9A},
+ {0x34A4, 0x8A},
+ {0x34A6, 0x8E},
+ {0x34AA, 0xD8},
+ {0x35BC, 0x00},
+ {0x35BE, 0xFF},
+ {0x35CC, 0x1B},
+ {0x35CD, 0x00},
+ {0x35CE, 0x2A},
+ {0x35CF, 0x00},
+ {0x35DC, 0x07},
+ {0x35DE, 0x1A},
+ {0x35DF, 0x00},
+ {0x35E4, 0x2B},
+ {0x35E5, 0x00},
+ {0x35E6, 0x07},
+ {0x35E7, 0x01},
+ {0x3648, 0x01},
+ {0x3678, 0x01},
+ {0x367C, 0x69},
+ {0x367E, 0x69},
+ {0x3680, 0x69},
+ {0x3682, 0x69},
+ {0x3718, 0x1C},
+ {0x371D, 0x05},
+ {0x375D, 0x11},
+ {0x375E, 0x43},
+ {0x375F, 0x76},
+ {0x3760, 0x07},
+ {0x3768, 0x1B},
+ {0x3769, 0x1B},
+ {0x376A, 0x1A},
+ {0x376B, 0x19},
+ {0x376C, 0x17},
+ {0x376D, 0x0F},
+ {0x376E, 0x0B},
+ {0x376F, 0x0B},
+ {0x3770, 0x0B},
+ {0x3776, 0x89},
+ {0x3777, 0x00},
+ {0x3778, 0xCA},
+ {0x3779, 0x00},
+ {0x377A, 0x45},
+ {0x377B, 0x01},
+ {0x377C, 0x56},
+ {0x377D, 0x02},
+ {0x377E, 0xFE},
+ {0x377F, 0x03},
+ {0x3780, 0xFE},
+ {0x3781, 0x05},
+ {0x3782, 0xFE},
+ {0x3783, 0x06},
+ {0x3784, 0x7F},
+ {0x3788, 0x1F},
+ {0x378A, 0xCA},
+ {0x378B, 0x00},
+ {0x378C, 0x45},
+ {0x378D, 0x01},
+ {0x378E, 0x56},
+ {0x378F, 0x02},
+ {0x3790, 0xFE},
+ {0x3791, 0x03},
+ {0x3792, 0xFE},
+ {0x3793, 0x05},
+ {0x3794, 0xFE},
+ {0x3795, 0x06},
+ {0x3796, 0x7F},
+ {0x3798, 0xBF},
+ {0x3A01, 0x01},
+ {0x3A18, 0x7F},
+ {0x3A1A, 0x37},
+ {0x3A1C, 0x37},
+ {0x3A1E, 0xF7},
+ {0x3A1F, 0x00},
+ {0x3A20, 0x3F},
+ {0x3A22, 0x6F},
+ {0x3A24, 0x3F},
+ {0x3A26, 0x5F},
+ {0x3A28, 0x2F},
+ {REG_NULL, 0x00},
+};
+
+static const struct regval IMX464_hdr_2x_10bit_2688x1520_2lane_regs[] = {
+ {0x3000, 0x01},
+ {0x3002, 0x01},
+ {0x300C, 0x3B},
+ {0x300D, 0x2A},
+ {0x3034, 0xDC},
+ {0x3035, 0x05},
+ {0x3048, 0x01},
+ {0x3049, 0x01},
+ {0x304A, 0x04},
+ {0x304B, 0x04},
+ {0x304C, 0x13},
+ {0x304D, 0x00},
+ {0x3050, 0x00},
+ {0x3058, 0xF4},
+ {0x3059, 0x0A},
+ {0x3068, 0x3D},
+ {0x30BE, 0x5E},
+ {0x30E8, 0x14},
+ {0x3110, 0x02},
+ {0x314C, 0x29},//
+ {0x314D, 0x01},//
+ {0x315A, 0x06},
+ {0x3168, 0xA0},
+ {0x316A, 0x7E},
+ {0x319D, 0x00},
+ {0x319E, 0x02},//1188M
+ {0x31A1, 0x00},
+ {0x31D7, 0x01},
+ {0x3200, 0x10},
+ {0x3288, 0x22},
+ {0x328A, 0x02},
+ {0x328C, 0xA2},
+ {0x328E, 0x22},
+ {0x3415, 0x27},
+ {0x3418, 0x27},
+ {0x3428, 0xFE},
+ {0x349E, 0x6A},
+ {0x34A2, 0x9A},
+ {0x34A4, 0x8A},
+ {0x34A6, 0x8E},
+ {0x34AA, 0xD8},
+ {0x35BC, 0x00},
+ {0x35BE, 0xFF},
+ {0x35CC, 0x1B},
+ {0x35CD, 0x00},
+ {0x35CE, 0x2A},
+ {0x35CF, 0x00},
+ {0x35DC, 0x07},
+ {0x35DE, 0x1A},
+ {0x35DF, 0x00},
+ {0x35E4, 0x2B},
+ {0x35E5, 0x00},
+ {0x35E6, 0x07},
+ {0x35E7, 0x01},
+ {0x3648, 0x01},
+ {0x3678, 0x01},
+ {0x367C, 0x69},
+ {0x367E, 0x69},
+ {0x3680, 0x69},
+ {0x3682, 0x69},
+ {0x3718, 0x1C},
+ {0x371D, 0x05},
+ {0x375D, 0x11},
+ {0x375E, 0x43},
+ {0x375F, 0x76},
+ {0x3760, 0x07},
+ {0x3768, 0x1B},
+ {0x3769, 0x1B},
+ {0x376A, 0x1A},
+ {0x376B, 0x19},
+ {0x376C, 0x17},
+ {0x376D, 0x0F},
+ {0x376E, 0x0B},
+ {0x376F, 0x0B},
+ {0x3770, 0x0B},
+ {0x3776, 0x89},
+ {0x3777, 0x00},
+ {0x3778, 0xCA},
+ {0x3779, 0x00},
+ {0x377A, 0x45},
+ {0x377B, 0x01},
+ {0x377C, 0x56},
+ {0x377D, 0x02},
+ {0x377E, 0xFE},
+ {0x377F, 0x03},
+ {0x3780, 0xFE},
+ {0x3781, 0x05},
+ {0x3782, 0xFE},
+ {0x3783, 0x06},
+ {0x3784, 0x7F},
+ {0x3788, 0x1F},
+ {0x378A, 0xCA},
+ {0x378B, 0x00},
+ {0x378C, 0x45},
+ {0x378D, 0x01},
+ {0x378E, 0x56},
+ {0x378F, 0x02},
+ {0x3790, 0xFE},
+ {0x3791, 0x03},
+ {0x3792, 0xFE},
+ {0x3793, 0x05},
+ {0x3794, 0xFE},
+ {0x3795, 0x06},
+ {0x3796, 0x7F},
+ {0x3798, 0xBF},
+ {0x3A01, 0x01},
+ {0x3A18, 0x7F},
+ {0x3A1A, 0x37},
+ {0x3A1C, 0x37},
+ {0x3A1E, 0xF7},
+ {0x3A1F, 0x00},
+ {0x3A20, 0x3F},
+ {0x3A22, 0x6F},
+ {0x3A24, 0x3F},
+ {0x3A26, 0x5F},
+ {0x3A28, 0x2F},
+ {REG_NULL, 0x00},
+};
+
+static const struct regval IMX464_linear_10bit_2688x1520_regs[] = {
+ {0x3000, 0x01},
+ {0x3002, 0x01},
+ {0x300C, 0x5B},
+ {0x300D, 0x40},
+ {0x3030, 0xE4},
+ {0x3031, 0x0C},
+ {0x3034, 0xee},
+ {0x3035, 0x02},
+ {0x3048, 0x00},
+ {0x3049, 0x00},
+ {0x304A, 0x03},
+ {0x304B, 0x02},
+ {0x304C, 0x14},
+ {0x3050, 0x00},
+ {0x3058, 0x06},
+ {0x3059, 0x09},
+ {0x305C, 0x09},
+ {0x3060, 0x21},
+ {0x3061, 0x01},
+ {0x3068, 0xc9},
+ {0x306C, 0x56},
+ {0x306D, 0x09},
+ {0x30BE, 0x5E},
+ {0x30E8, 0x14},
+ {0x3110, 0x02},
+ {0x314C, 0xC0},
+ {0x315A, 0x06},
+ {0x316A, 0x7E},
+ {0x319D, 0x00},
+ {0x319E, 0x02},
+ {0x31A1, 0x00},
+ {0x31D7, 0x00},
+ {0x3200, 0x11},
{0x3288, 0x22},
{0x328A, 0x02},
{0x328C, 0xA2},
@@ -350,6 +826,10 @@
{0x3002, 0x01},
{0x300C, 0x5B},
{0x300D, 0x40},
+ {0x3030, 0x72},
+ {0x3031, 0x06},
+ {0x3034, 0xee},
+ {0x3035, 0x02},
{0x3048, 0x01},
{0x3049, 0x01},
{0x304A, 0x04},
@@ -358,7 +838,12 @@
{0x3050, 0x00},
{0x3058, 0x06},
{0x3059, 0x09},
+ {0x305C, 0x09},
+ {0x3060, 0x21},
+ {0x3061, 0x01},
{0x3068, 0x6D},
+ {0x306C, 0x56},
+ {0x306D, 0x09},
{0x30BE, 0x5E},
{0x30E8, 0x14},
{0x3110, 0x02},
@@ -498,6 +983,7 @@
{0x319E, 0x01},
{0x31A1, 0x00},
{0x31D7, 0x03},
+ {0x3200, 0x10},
{0x3288, 0x22},
{0x328A, 0x02},
{0x328C, 0xA2},
@@ -584,7 +1070,6 @@
{0x3A24, 0x4F},
{0x3A26, 0x5F},
{0x3A28, 0x3F},
- {0x3200, 0x10},
{REG_NULL, 0x00},
};
@@ -824,6 +1309,33 @@
{REG_NULL, 0x00},
};
+static __maybe_unused const struct regval IMX464_interal_sync_master_start_regs[] = {
+ {0x3010, 0x07},
+ {0x31a1, 0x00},
+ {REG_NULL, 0x00},
+};
+static __maybe_unused const struct regval IMX464_interal_sync_master_stop_regs[] = {
+ {0x31a1, 0x0f},
+ {REG_NULL, 0x00},
+};
+
+static __maybe_unused const struct regval IMX464_external_sync_master_start_regs[] = {
+ {0x3010, 0x05},
+ {0x31a1, 0x03},
+ {0x31d9, 0x01},
+ {REG_NULL, 0x00},
+};
+static __maybe_unused const struct regval IMX464_external_sync_master_stop_regs[] = {
+ {0x31a1, 0x0f},
+ {REG_NULL, 0x00},
+};
+
+static __maybe_unused const struct regval IMX464_slave_start_regs[] = {
+ {0x3010, 0x05},
+ {0x31a1, 0x0f},
+ {REG_NULL, 0x00},
+};
+
/*
* The width and height must be configured to be
* the same as the current output resolution of the sensor.
@@ -848,6 +1360,9 @@
.exp_def = 0x0906,
.hts_def = 0x05dc * 2,
.vts_def = 0x0ce4,
+ .mipi_freq_idx = 0,
+ .bpp = 10,
+ .mclk = 37125000,
.reg_list = IMX464_linear_10bit_2688x1520_regs,
.hdr_mode = NO_HDR,
.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
@@ -863,6 +1378,9 @@
.exp_def = 0x03de,
.hts_def = 0x02ee * 4,
.vts_def = 0x0672 * 2,
+ .mipi_freq_idx = 1,
+ .bpp = 10,
+ .mclk = 37125000,
.reg_list = IMX464_hdr_2x_10bit_2688x1520_regs,
.hdr_mode = HDR_X2,
.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
@@ -889,12 +1407,57 @@
#else
.vts_def = 0x04D1 * 4,
#endif
+ .mipi_freq_idx = 1,
+ .bpp = 10,
+ .mclk = 37125000,
.reg_list = IMX464_hdr_3x_10bit_2688x1520_regs,
.hdr_mode = HDR_X3,
.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_2,
.vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr0
.vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr1
.vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_2,//S->csi wr2
+ },
+};
+
+static const struct IMX464_mode supported_modes_2lane[] = {
+ {
+ .bus_fmt = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .width = 2712,
+ .height = 1538,
+ .max_fps = {
+ .numerator = 10000,
+ .denominator = 300000,
+ },
+ .exp_def = 0x0600,
+ .hts_def = 0x05dc * 2,
+ .vts_def = 0x672,
+ .mipi_freq_idx = 0,
+ .bpp = 10,
+ .mclk = 24000000,
+ .reg_list = IMX464_linear_10bit_2688x1520_2lane_regs,
+ .hdr_mode = NO_HDR,
+ .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
+ },
+ {
+ .bus_fmt = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .width = 2712,
+ .height = 1538,
+ .max_fps = {
+ .numerator = 10000,
+ .denominator = 150000,
+ },
+ .exp_def = 0x0600,
+ .hts_def = 0x05dc * 4,
+ .vts_def = 0x0672 * 2,
+ .mipi_freq_idx = 0,
+ .bpp = 10,
+ .mclk = 24000000,
+ .reg_list = IMX464_hdr_2x_10bit_2688x1520_2lane_regs,
+ .hdr_mode = HDR_X2,
+ .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
+ .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
+ .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
+ .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
},
};
@@ -997,15 +1560,15 @@
unsigned int i;
for (i = 0; i < IMX464->cfg_num; i++) {
- dist = IMX464_get_reso_dist(&supported_modes[i], framefmt);
+ dist = IMX464_get_reso_dist(&IMX464->support_modes[i], framefmt);
if ((cur_best_fit_dist == -1 || dist <= cur_best_fit_dist) &&
- supported_modes[i].bus_fmt == framefmt->code) {
+ IMX464->support_modes[i].bus_fmt == framefmt->code) {
cur_best_fit_dist = dist;
cur_best_fit = i;
}
}
- return &supported_modes[cur_best_fit];
+ return &IMX464->support_modes[cur_best_fit];
}
static int IMX464_set_fmt(struct v4l2_subdev *sd,
@@ -1015,8 +1578,7 @@
struct IMX464 *IMX464 = to_IMX464(sd);
const struct IMX464_mode *mode;
s64 h_blank, vblank_def;
- struct device *dev = &IMX464->client->dev;
- int ret = 0;
+ u64 pixel_rate = 0;
mutex_lock(&IMX464->mutex);
@@ -1042,42 +1604,12 @@
IMX464_VTS_MAX - mode->height,
1, vblank_def);
IMX464->cur_vts = IMX464->cur_mode->vts_def;
- if (mode->bus_fmt == MEDIA_BUS_FMT_SRGGB10_1X10) {
- IMX464->cur_link_freq = 1;
- if (mode->hdr_mode == NO_HDR) {
- IMX464->cur_pixel_rate = IMX464_10BIT_LINEAR_PIXEL_RATE;
- IMX464->cur_link_freq = 0;
- } else if (mode->hdr_mode == HDR_X2)
- IMX464->cur_pixel_rate = IMX464_10BIT_HDR2_PIXEL_RATE;
- else if (mode->hdr_mode == HDR_X3)
- IMX464->cur_pixel_rate = IMX464_10BIT_HDR3_PIXEL_RATE;
-
- clk_disable_unprepare(IMX464->xvclk);
- ret = clk_set_rate(IMX464->xvclk, IMX464_XVCLK_FREQ_37M);
- if (ret < 0)
- dev_err(dev, "Failed to set xvclk rate\n");
- if (clk_get_rate(IMX464->xvclk) != IMX464_XVCLK_FREQ_37M)
- dev_err(dev, "xvclk mismatched\n");
- ret = clk_prepare_enable(IMX464->xvclk);
- if (ret < 0)
- dev_err(dev, "Failed to enable xvclk\n");
- } else {
- IMX464->cur_pixel_rate = IMX464_12BIT_PIXEL_RATE;
- IMX464->cur_link_freq = 0;
- clk_disable_unprepare(IMX464->xvclk);
- ret = clk_set_rate(IMX464->xvclk, IMX464_XVCLK_FREQ_24M);
- if (ret < 0)
- dev_err(dev, "Failed to set xvclk rate\n");
- if (clk_get_rate(IMX464->xvclk) != IMX464_XVCLK_FREQ_24M)
- dev_err(dev, "xvclk mismatched\n");
- ret = clk_prepare_enable(IMX464->xvclk);
- if (ret < 0)
- dev_err(dev, "Failed to enable xvclk\n");
- }
+ pixel_rate = (u32)link_freq_menu_items[mode->mipi_freq_idx] / mode->bpp * 2 *
+ IMX464->bus_cfg.bus.mipi_csi2.num_data_lanes;
__v4l2_ctrl_s_ctrl_int64(IMX464->pixel_rate,
- IMX464->cur_pixel_rate);
+ pixel_rate);
__v4l2_ctrl_s_ctrl(IMX464->link_freq,
- IMX464->cur_link_freq);
+ mode->mipi_freq_idx);
}
mutex_unlock(&IMX464->mutex);
@@ -1137,13 +1669,13 @@
if (fse->index >= IMX464->cfg_num)
return -EINVAL;
- if (fse->code != supported_modes[fse->index].bus_fmt)
+ if (fse->code != IMX464->support_modes[fse->index].bus_fmt)
return -EINVAL;
- fse->min_width = supported_modes[fse->index].width;
- fse->max_width = supported_modes[fse->index].width;
- fse->max_height = supported_modes[fse->index].height;
- fse->min_height = supported_modes[fse->index].height;
+ fse->min_width = IMX464->support_modes[fse->index].width;
+ fse->max_width = IMX464->support_modes[fse->index].width;
+ fse->max_height = IMX464->support_modes[fse->index].height;
+ fse->min_height = IMX464->support_modes[fse->index].height;
return 0;
}
@@ -1154,38 +1686,37 @@
struct IMX464 *IMX464 = to_IMX464(sd);
const struct IMX464_mode *mode = IMX464->cur_mode;
- mutex_lock(&IMX464->mutex);
fi->interval = mode->max_fps;
- mutex_unlock(&IMX464->mutex);
return 0;
}
-static int IMX464_g_mbus_config(struct v4l2_subdev *sd,
+static int IMX464_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
struct v4l2_mbus_config *config)
{
struct IMX464 *IMX464 = to_IMX464(sd);
const struct IMX464_mode *mode = IMX464->cur_mode;
u32 val = 0;
+ u32 lane_num = IMX464->bus_cfg.bus.mipi_csi2.num_data_lanes;
if (mode->hdr_mode == NO_HDR) {
- val = 1 << (IMX464_4LANES - 1) |
+ val = 1 << (lane_num - 1) |
V4L2_MBUS_CSI2_CHANNEL_0 |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
}
if (mode->hdr_mode == HDR_X2)
- val = 1 << (IMX464_4LANES - 1) |
+ val = 1 << (lane_num - 1) |
V4L2_MBUS_CSI2_CHANNEL_0 |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK |
V4L2_MBUS_CSI2_CHANNEL_1;
if (mode->hdr_mode == HDR_X3)
- val = 1 << (IMX464_4LANES - 1) |
+ val = 1 << (lane_num - 1) |
V4L2_MBUS_CSI2_CHANNEL_0 |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK |
V4L2_MBUS_CSI2_CHANNEL_1 |
V4L2_MBUS_CSI2_CHANNEL_2;
- config->type = V4L2_MBUS_CSI2;
+ config->type = V4L2_MBUS_CSI2_DPHY;
config->flags = val;
return 0;
@@ -1241,12 +1772,12 @@
l_exp_time = m_exp_time;
cg_mode = ae->middle_cg_mode;
}
- if (!g_isHCG && cg_mode == GAIN_MODE_HCG) {
+ if (!IMX464->isHCG && cg_mode == GAIN_MODE_HCG) {
gain_switch = 0x01 | 0x100;
- g_isHCG = true;
- } else if (g_isHCG && cg_mode == GAIN_MODE_LCG) {
+ IMX464->isHCG = true;
+ } else if (IMX464->isHCG && cg_mode == GAIN_MODE_LCG) {
gain_switch = 0x00 | 0x100;
- g_isHCG = false;
+ IMX464->isHCG = false;
}
ret = imx464_write_reg(client,
IMX464_GROUP_HOLD_REG,
@@ -1323,7 +1854,7 @@
__LINE__, rhs1, s_exp_time, rhs1_old,
(rhs1_old + 2 * BRL - fsc + 2));
- rhs1 = (rhs1 >> 2) * 4 + 1;
+ rhs1 = ((rhs1 + 3) >> 2) * 4 + 1;
rhs1_old = rhs1;
if (rhs1 - s_exp_time <= SHR1_MIN) {
@@ -1428,12 +1959,12 @@
//3 stagger
cg_mode = ae->long_cg_mode;
}
- if (!g_isHCG && cg_mode == GAIN_MODE_HCG) {
+ if (!IMX464->isHCG && cg_mode == GAIN_MODE_HCG) {
gain_switch = 0x01 | 0x100;
- g_isHCG = true;
- } else if (g_isHCG && cg_mode == GAIN_MODE_LCG) {
+ IMX464->isHCG = true;
+ } else if (IMX464->isHCG && cg_mode == GAIN_MODE_LCG) {
gain_switch = 0x00 | 0x100;
- g_isHCG = false;
+ IMX464->isHCG = false;
}
dev_dbg(&client->dev,
@@ -1670,12 +2201,12 @@
int cur_cg = *cg;
u32 gain_switch = 0;
- if (g_isHCG && cur_cg == GAIN_MODE_LCG) {
+ if (IMX464->isHCG && cur_cg == GAIN_MODE_LCG) {
gain_switch = 0x00 | 0x100;
- g_isHCG = false;
- } else if (!g_isHCG && cur_cg == GAIN_MODE_HCG) {
+ IMX464->isHCG = false;
+ } else if (!IMX464->isHCG && cur_cg == GAIN_MODE_HCG) {
gain_switch = 0x01 | 0x100;
- g_isHCG = true;
+ IMX464->isHCG = true;
}
ret = imx464_write_reg(client,
IMX464_GROUP_HOLD_REG,
@@ -1743,12 +2274,26 @@
}
#endif
+static int IMX464_get_channel_info(struct IMX464 *IMX464, struct rkmodule_channel_info *ch_info)
+{
+ if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX)
+ return -EINVAL;
+ ch_info->vc = IMX464->cur_mode->vc[ch_info->index];
+ ch_info->width = IMX464->cur_mode->width;
+ ch_info->height = IMX464->cur_mode->height;
+ ch_info->bus_fmt = IMX464->cur_mode->bus_fmt;
+ return 0;
+}
+
static long IMX464_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
struct IMX464 *IMX464 = to_IMX464(sd);
struct rkmodule_hdr_cfg *hdr;
+ struct rkmodule_channel_info *ch_info;
u32 i, h, w, stream;
long ret = 0;
+ u64 pixel_rate = 0;
+ u32 *sync_mode = NULL;
switch (cmd) {
case PREISP_CMD_SET_HDRAE_EXP:
@@ -1770,10 +2315,10 @@
w = IMX464->cur_mode->width;
h = IMX464->cur_mode->height;
for (i = 0; i < IMX464->cfg_num; i++) {
- if (w == supported_modes[i].width &&
- h == supported_modes[i].height &&
- supported_modes[i].hdr_mode == hdr->hdr_mode) {
- IMX464->cur_mode = &supported_modes[i];
+ if (w == IMX464->support_modes[i].width &&
+ h == IMX464->support_modes[i].height &&
+ IMX464->support_modes[i].hdr_mode == hdr->hdr_mode) {
+ IMX464->cur_mode = &IMX464->support_modes[i];
break;
}
}
@@ -1790,16 +2335,12 @@
IMX464_VTS_MAX - IMX464->cur_mode->height,
1, h);
IMX464->cur_vts = IMX464->cur_mode->vts_def;
- if (IMX464->cur_mode->bus_fmt == MEDIA_BUS_FMT_SRGGB10_1X10) {
- if (IMX464->cur_mode->hdr_mode == NO_HDR)
- IMX464->cur_pixel_rate = IMX464_10BIT_LINEAR_PIXEL_RATE;
- else if (IMX464->cur_mode->hdr_mode == HDR_X2)
- IMX464->cur_pixel_rate = IMX464_10BIT_HDR2_PIXEL_RATE;
- else if (IMX464->cur_mode->hdr_mode == HDR_X3)
- IMX464->cur_pixel_rate = IMX464_10BIT_HDR3_PIXEL_RATE;
- __v4l2_ctrl_s_ctrl_int64(IMX464->pixel_rate,
- IMX464->cur_pixel_rate);
- }
+ pixel_rate = (u32)link_freq_menu_items[IMX464->cur_mode->mipi_freq_idx] / IMX464->cur_mode->bpp * 2 *
+ IMX464->bus_cfg.bus.mipi_csi2.num_data_lanes;
+ __v4l2_ctrl_s_ctrl_int64(IMX464->pixel_rate,
+ pixel_rate);
+ __v4l2_ctrl_s_ctrl(IMX464->link_freq,
+ IMX464->cur_mode->mipi_freq_idx);
}
break;
case RKMODULE_SET_CONVERSION_GAIN:
@@ -1809,16 +2350,25 @@
stream = *((u32 *)arg);
- if (stream) {
+ if (stream)
ret = imx464_write_reg(IMX464->client, IMX464_REG_CTRL_MODE,
IMX464_REG_VALUE_08BIT, IMX464_MODE_STREAMING);
- usleep_range(30000, 40000);
- imx464_write_reg(IMX464->client, IMX464_REG_MARSTER_MODE,
- IMX464_REG_VALUE_08BIT, 0);
- } else {
+ else
ret = imx464_write_reg(IMX464->client, IMX464_REG_CTRL_MODE,
IMX464_REG_VALUE_08BIT, IMX464_MODE_SW_STANDBY);
- }
+
+ break;
+ case RKMODULE_GET_CHANNEL_INFO:
+ ch_info = (struct rkmodule_channel_info *)arg;
+ ret = IMX464_get_channel_info(IMX464, ch_info);
+ break;
+ case RKMODULE_GET_SYNC_MODE:
+ sync_mode = (u32 *)arg;
+ *sync_mode = IMX464->sync_mode;
+ break;
+ case RKMODULE_SET_SYNC_MODE:
+ sync_mode = (u32 *)arg;
+ IMX464->sync_mode = *sync_mode;
break;
default:
ret = -ENOIOCTLCMD;
@@ -1837,9 +2387,11 @@
struct rkmodule_awb_cfg *cfg;
struct rkmodule_hdr_cfg *hdr;
struct preisp_hdrae_exp_s *hdrae;
+ struct rkmodule_channel_info *ch_info;
long ret;
u32 cg = 0;
u32 stream;
+ u32 sync_mode;
switch (cmd) {
case RKMODULE_GET_MODULE_INFO:
@@ -1850,8 +2402,11 @@
}
ret = IMX464_ioctl(sd, cmd, inf);
- if (!ret)
+ if (!ret) {
ret = copy_to_user(up, inf, sizeof(*inf));
+ if (ret)
+ ret = -EFAULT;
+ }
kfree(inf);
break;
case RKMODULE_AWB_CFG:
@@ -1864,6 +2419,8 @@
ret = copy_from_user(cfg, up, sizeof(*cfg));
if (!ret)
ret = IMX464_ioctl(sd, cmd, cfg);
+ else
+ ret = -EFAULT;
kfree(cfg);
break;
case RKMODULE_GET_HDR_CFG:
@@ -1874,8 +2431,11 @@
}
ret = IMX464_ioctl(sd, cmd, hdr);
- if (!ret)
+ if (!ret) {
ret = copy_to_user(up, hdr, sizeof(*hdr));
+ if (ret)
+ ret = -EFAULT;
+ }
kfree(hdr);
break;
case RKMODULE_SET_HDR_CFG:
@@ -1888,6 +2448,8 @@
ret = copy_from_user(hdr, up, sizeof(*hdr));
if (!ret)
ret = IMX464_ioctl(sd, cmd, hdr);
+ else
+ ret = -EFAULT;
kfree(hdr);
break;
case PREISP_CMD_SET_HDRAE_EXP:
@@ -1900,18 +2462,54 @@
ret = copy_from_user(hdrae, up, sizeof(*hdrae));
if (!ret)
ret = IMX464_ioctl(sd, cmd, hdrae);
+ else
+ ret = -EFAULT;
kfree(hdrae);
break;
case RKMODULE_SET_CONVERSION_GAIN:
ret = copy_from_user(&cg, up, sizeof(cg));
if (!ret)
ret = IMX464_ioctl(sd, cmd, &cg);
+ else
+ ret = -EFAULT;
break;
case RKMODULE_SET_QUICK_STREAM:
ret = copy_from_user(&stream, up, sizeof(u32));
if (!ret)
ret = IMX464_ioctl(sd, cmd, &stream);
+ else
+ ret = -EFAULT;
+ break;
+ case RKMODULE_GET_CHANNEL_INFO:
+ ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
+ if (!ch_info) {
+ ret = -ENOMEM;
+ return ret;
+ }
+
+ ret = IMX464_ioctl(sd, cmd, ch_info);
+ if (!ret) {
+ ret = copy_to_user(up, ch_info, sizeof(*ch_info));
+ if (ret)
+ ret = -EFAULT;
+ }
+ kfree(ch_info);
+ break;
+ case RKMODULE_GET_SYNC_MODE:
+ ret = IMX464_ioctl(sd, cmd, &sync_mode);
+ if (!ret) {
+ ret = copy_to_user(up, &sync_mode, sizeof(u32));
+ if (ret)
+ ret = -EFAULT;
+ }
+ break;
+ case RKMODULE_SET_SYNC_MODE:
+ ret = copy_from_user(&sync_mode, up, sizeof(u32));
+ if (!ret)
+ ret = IMX464_ioctl(sd, cmd, &sync_mode);
+ else
+ ret = -EFAULT;
break;
default:
ret = -ENOIOCTLCMD;
@@ -1922,17 +2520,20 @@
}
#endif
-static int IMX464_init_conversion_gain(struct IMX464 *IMX464)
+static int IMX464_init_conversion_gain(struct IMX464 *IMX464, bool isHCG)
{
- int ret = 0;
struct i2c_client *client = IMX464->client;
+ int ret = 0;
+ u32 val = 0;
+ if (isHCG)
+ val = 0x01;
+ else
+ val = 0;
ret = imx464_write_reg(client,
IMX464_GAIN_SWITCH_REG,
IMX464_REG_VALUE_08BIT,
- 0X00);
- if (!ret)
- g_isHCG = false;
+ val);
return ret;
}
@@ -1943,7 +2544,7 @@
ret = IMX464_write_array(IMX464->client, IMX464->cur_mode->reg_list);
if (ret)
return ret;
- ret = IMX464_init_conversion_gain(IMX464);
+ ret = IMX464_init_conversion_gain(IMX464, IMX464->isHCG);
if (ret)
return ret;
/* In case these controls are set before streaming */
@@ -1959,18 +2560,43 @@
return ret;
}
}
- imx464_write_reg(IMX464->client, IMX464_REG_CTRL_MODE,
- IMX464_REG_VALUE_08BIT, IMX464_MODE_STREAMING);
- usleep_range(30000, 40000);
- return imx464_write_reg(IMX464->client, IMX464_REG_MARSTER_MODE,
- IMX464_REG_VALUE_08BIT, 0);
+
+ if (IMX464->sync_mode == EXTERNAL_MASTER_MODE) {
+ ret |= IMX464_write_array(IMX464->client, IMX464_external_sync_master_start_regs);
+ v4l2_err(&IMX464->subdev, "cur externam master mode\n");
+ } else if (IMX464->sync_mode == INTERNAL_MASTER_MODE) {
+ ret |= IMX464_write_array(IMX464->client, IMX464_interal_sync_master_start_regs);
+ v4l2_err(&IMX464->subdev, "cur intertal master\n");
+ } else if (IMX464->sync_mode == SLAVE_MODE) {
+ ret |= IMX464_write_array(IMX464->client, IMX464_slave_start_regs);
+ v4l2_err(&IMX464->subdev, "cur slave mode\n");
+ }
+ if (IMX464->sync_mode == NO_SYNC_MODE) {
+ ret = imx464_write_reg(IMX464->client, IMX464_REG_CTRL_MODE,
+ IMX464_REG_VALUE_08BIT, IMX464_MODE_STREAMING);
+ usleep_range(30000, 40000);
+ ret |= imx464_write_reg(IMX464->client, IMX464_REG_MARSTER_MODE,
+ IMX464_REG_VALUE_08BIT, 0);
+ } else {
+ ret |= imx464_write_reg(IMX464->client, IMX464_REG_MARSTER_MODE,
+ IMX464_REG_VALUE_08BIT, 0);
+ }
+ return ret;
}
static int __IMX464_stop_stream(struct IMX464 *IMX464)
{
+ int ret = 0;
+
IMX464->has_init_exp = false;
- return imx464_write_reg(IMX464->client, IMX464_REG_CTRL_MODE,
- IMX464_REG_VALUE_08BIT, IMX464_MODE_SW_STANDBY);
+ ret = imx464_write_reg(IMX464->client, IMX464_REG_CTRL_MODE,
+ IMX464_REG_VALUE_08BIT, IMX464_MODE_SW_STANDBY);
+
+ if (IMX464->sync_mode == EXTERNAL_MASTER_MODE)
+ ret |= IMX464_write_array(IMX464->client, IMX464_external_sync_master_stop_regs);
+ else if (IMX464->sync_mode == INTERNAL_MASTER_MODE)
+ ret |= IMX464_write_array(IMX464->client, IMX464_interal_sync_master_stop_regs);
+ return ret;
}
static int IMX464_s_stream(struct v4l2_subdev *sd, int on)
@@ -2059,7 +2685,6 @@
int ret;
u32 delay_us;
struct device *dev = &IMX464->client->dev;
- unsigned long mclk = 0;
if (!IS_ERR_OR_NULL(IMX464->pins_default)) {
ret = pinctrl_select_state(IMX464->pinctrl,
@@ -2067,15 +2692,14 @@
if (ret < 0)
dev_err(dev, "could not set pins\n");
}
- if (IMX464->cur_mode->bus_fmt == MEDIA_BUS_FMT_SRGGB10_1X10)
- mclk = IMX464_XVCLK_FREQ_37M;
- else
- mclk = IMX464_XVCLK_FREQ_24M;
- ret = clk_set_rate(IMX464->xvclk, mclk);
+
+ ret = clk_set_rate(IMX464->xvclk, IMX464->cur_mode->mclk);
if (ret < 0)
dev_warn(dev, "Failed to set xvclk rate\n");
- if (clk_get_rate(IMX464->xvclk) != mclk)
- dev_warn(dev, "xvclk mismatched\n");
+ if (clk_get_rate(IMX464->xvclk) != IMX464->cur_mode->mclk)
+ dev_warn(dev, "xvclk mismatched, %lu\n", clk_get_rate(IMX464->xvclk));
+ else
+ IMX464->cur_mclk = IMX464->cur_mode->mclk;
ret = clk_prepare_enable(IMX464->xvclk);
if (ret < 0) {
dev_err(dev, "Failed to enable xvclk\n");
@@ -2089,7 +2713,7 @@
dev_err(dev, "Failed to enable regulators\n");
goto disable_clk;
}
-
+ usleep_range(15000, 16000);
if (!IS_ERR(IMX464->reset_gpio))
gpiod_set_value_cansleep(IMX464->reset_gpio, 1);
@@ -2126,6 +2750,7 @@
dev_err(dev, "could not set pins\n");
}
regulator_bulk_disable(IMX464_NUM_SUPPLIES, IMX464->supplies);
+ usleep_range(15000, 16000);
}
static int IMX464_runtime_resume(struct device *dev)
@@ -2154,7 +2779,7 @@
struct IMX464 *IMX464 = to_IMX464(sd);
struct v4l2_mbus_framefmt *try_fmt =
v4l2_subdev_get_try_format(sd, fh->pad, 0);
- const struct IMX464_mode *def_mode = &supported_modes[0];
+ const struct IMX464_mode *def_mode = &IMX464->support_modes[0];
mutex_lock(&IMX464->mutex);
/* Initialize try_fmt */
@@ -2179,16 +2804,16 @@
if (fie->index >= IMX464->cfg_num)
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;
+ fie->code = IMX464->support_modes[fie->index].bus_fmt;
+ fie->width = IMX464->support_modes[fie->index].width;
+ fie->height = IMX464->support_modes[fie->index].height;
+ fie->interval = IMX464->support_modes[fie->index].max_fps;
+ fie->reserved[0] = IMX464->support_modes[fie->index].hdr_mode;
return 0;
}
#define CROP_START(SRC, DST) (((SRC) - (DST)) / 2 / 4 * 4)
-#define DST_WIDTH 2688
+#define DST_WIDTH 2560
#define DST_HEIGHT 1520
/*
@@ -2238,7 +2863,6 @@
static const struct v4l2_subdev_video_ops IMX464_video_ops = {
.s_stream = IMX464_s_stream,
.g_frame_interval = IMX464_g_frame_interval,
- .g_mbus_config = IMX464_g_mbus_config,
};
static const struct v4l2_subdev_pad_ops IMX464_pad_ops = {
@@ -2248,6 +2872,7 @@
.get_fmt = IMX464_get_fmt,
.set_fmt = IMX464_set_fmt,
.get_selection = IMX464_get_selection,
+ .get_mbus_config = IMX464_g_mbus_config,
};
static const struct v4l2_subdev_ops IMX464_subdev_ops = {
@@ -2266,7 +2891,7 @@
u32 vts = 0;
int ret = 0;
u32 shr0 = 0;
- //u32 flip = 0;
+ u32 flip = 0;
/* Propagate change of current control to all related controls */
switch (ctrl->id) {
@@ -2342,8 +2967,64 @@
vts);
break;
case V4L2_CID_HFLIP:
+ ret = imx464_write_reg(client,
+ IMX464_GROUP_HOLD_REG,
+ IMX464_REG_VALUE_08BIT,
+ IMX464_GROUP_HOLD_START);
+ ret |= imx464_write_reg(IMX464->client, IMX464_HREVERSE_REG,
+ IMX464_REG_VALUE_08BIT, !!ctrl->val);
+ ret |= imx464_write_reg(client,
+ IMX464_GROUP_HOLD_REG,
+ IMX464_REG_VALUE_08BIT,
+ IMX464_GROUP_HOLD_END);
break;
case V4L2_CID_VFLIP:
+ flip = ctrl->val;
+ ret = imx464_write_reg(client,
+ IMX464_GROUP_HOLD_REG,
+ IMX464_REG_VALUE_08BIT,
+ IMX464_GROUP_HOLD_START);
+ ret |= imx464_write_reg(IMX464->client, IMX464_VREVERSE_REG,
+ IMX464_REG_VALUE_08BIT, !!flip);
+ if (flip) {
+ ret |= imx464_write_reg(IMX464->client, 0x3074,
+ IMX464_REG_VALUE_08BIT, 0x40);
+ ret |= imx464_write_reg(IMX464->client, 0x3075,
+ IMX464_REG_VALUE_08BIT, 0x06);
+ ret |= imx464_write_reg(IMX464->client, 0x3080,
+ IMX464_REG_VALUE_08BIT, 0xff);
+ ret |= imx464_write_reg(IMX464->client, 0x30ad,
+ IMX464_REG_VALUE_08BIT, 0x7e);
+ ret |= imx464_write_reg(IMX464->client, 0x30b6,
+ IMX464_REG_VALUE_08BIT, 0xff);
+ ret |= imx464_write_reg(IMX464->client, 0x30b7,
+ IMX464_REG_VALUE_08BIT, 0x01);
+ ret |= imx464_write_reg(IMX464->client, 0x30d8,
+ IMX464_REG_VALUE_08BIT, 0x45);
+ ret |= imx464_write_reg(IMX464->client, 0x3114,
+ IMX464_REG_VALUE_08BIT, 0x01);
+ } else {
+ ret |= imx464_write_reg(IMX464->client, 0x3074,
+ IMX464_REG_VALUE_08BIT, 0x3c);
+ ret |= imx464_write_reg(IMX464->client, 0x3075,
+ IMX464_REG_VALUE_08BIT, 0x00);
+ ret |= imx464_write_reg(IMX464->client, 0x3080,
+ IMX464_REG_VALUE_08BIT, 0x01);
+ ret |= imx464_write_reg(IMX464->client, 0x30ad,
+ IMX464_REG_VALUE_08BIT, 0x02);
+ ret |= imx464_write_reg(IMX464->client, 0x30b6,
+ IMX464_REG_VALUE_08BIT, 0x00);
+ ret |= imx464_write_reg(IMX464->client, 0x30b7,
+ IMX464_REG_VALUE_08BIT, 0x00);
+ ret |= imx464_write_reg(IMX464->client, 0x30d8,
+ IMX464_REG_VALUE_08BIT, 0x44);
+ ret |= imx464_write_reg(IMX464->client, 0x3114,
+ IMX464_REG_VALUE_08BIT, 0x02);
+ }
+ ret |= imx464_write_reg(client,
+ IMX464_GROUP_HOLD_REG,
+ IMX464_REG_VALUE_08BIT,
+ IMX464_GROUP_HOLD_END);
break;
default:
dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
@@ -2366,6 +3047,7 @@
struct v4l2_ctrl_handler *handler;
s64 exposure_max, vblank_def;
u32 h_blank;
+ u64 pixel_rate = 0;
int ret;
handler = &IMX464->ctrl_handler;
@@ -2378,28 +3060,13 @@
IMX464->link_freq = v4l2_ctrl_new_int_menu(handler,
NULL, V4L2_CID_LINK_FREQ,
1, 0, link_freq_menu_items);
- if (IMX464->cur_mode->bus_fmt == MEDIA_BUS_FMT_SRGGB10_1X10) {
- IMX464->cur_link_freq = 1;
- if (IMX464->cur_mode->hdr_mode == NO_HDR) {
- IMX464->cur_pixel_rate =
- IMX464_10BIT_LINEAR_PIXEL_RATE;
- IMX464->cur_link_freq = 0;
- } else if (IMX464->cur_mode->hdr_mode == HDR_X2)
- IMX464->cur_pixel_rate =
- IMX464_10BIT_HDR2_PIXEL_RATE;
- else if (IMX464->cur_mode->hdr_mode == HDR_X3)
- IMX464->cur_pixel_rate =
- IMX464_10BIT_HDR3_PIXEL_RATE;
- } else {
- IMX464->cur_link_freq = 0;
- IMX464->cur_pixel_rate =
- IMX464_12BIT_PIXEL_RATE;
- }
__v4l2_ctrl_s_ctrl(IMX464->link_freq,
- IMX464->cur_link_freq);
+ IMX464->cur_mode->mipi_freq_idx);
+ pixel_rate = (u32)link_freq_menu_items[mode->mipi_freq_idx] / mode->bpp * 2 *
+ IMX464->bus_cfg.bus.mipi_csi2.num_data_lanes;
IMX464->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
V4L2_CID_PIXEL_RATE, 0, IMX464_10BIT_HDR2_PIXEL_RATE,
- 1, IMX464->cur_pixel_rate);
+ 1, pixel_rate);
h_blank = mode->hts_def - mode->width;
IMX464->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,
@@ -2436,6 +3103,7 @@
IMX464->subdev.ctrl_handler = handler;
IMX464->has_init_exp = false;
+ IMX464->isHCG = false;
return 0;
@@ -2483,9 +3151,12 @@
struct device_node *node = dev->of_node;
struct IMX464 *IMX464;
struct v4l2_subdev *sd;
+ struct device_node *endpoint;
char facing[2];
int ret;
u32 i, hdr_mode = 0;
+ const char *sync_mode_name = NULL;
+
dev_info(dev, "driver version: %02x.%02x.%02x",
DRIVER_VERSION >> 16,
@@ -2509,6 +3180,20 @@
return -EINVAL;
}
+ ret = of_property_read_string(node, RKMODULE_CAMERA_SYNC_MODE,
+ &sync_mode_name);
+ if (ret) {
+ IMX464->sync_mode = NO_SYNC_MODE;
+ dev_err(dev, "could not get sync mode!\n");
+ } else {
+ if (strcmp(sync_mode_name, RKMODULE_EXTERNAL_MASTER_MODE) == 0)
+ IMX464->sync_mode = EXTERNAL_MASTER_MODE;
+ else if (strcmp(sync_mode_name, RKMODULE_INTERNAL_MASTER_MODE) == 0)
+ IMX464->sync_mode = INTERNAL_MASTER_MODE;
+ else if (strcmp(sync_mode_name, RKMODULE_SLAVE_MODE) == 0)
+ IMX464->sync_mode = SLAVE_MODE;
+ }
+
ret = of_property_read_u32(node, OF_CAMERA_HDR_MODE,
&hdr_mode);
if (ret) {
@@ -2516,15 +3201,32 @@
dev_warn(dev, " Get hdr mode failed! no hdr default\n");
}
IMX464->client = client;
+ endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
+ if (!endpoint) {
+ dev_err(dev, "Failed to get endpoint\n");
+ return -EINVAL;
+ }
+ ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
+ &IMX464->bus_cfg);
+ if (ret) {
+ dev_err(dev, "Failed to get bus cfg\n");
+ return ret;
+ }
+ if (IMX464->bus_cfg.bus.mipi_csi2.num_data_lanes == 4) {
+ IMX464->support_modes = supported_modes;
+ IMX464->cfg_num = ARRAY_SIZE(supported_modes);
+ } else {
+ IMX464->support_modes = supported_modes_2lane;
+ IMX464->cfg_num = ARRAY_SIZE(supported_modes_2lane);
+ }
- IMX464->cfg_num = ARRAY_SIZE(supported_modes);
for (i = 0; i < IMX464->cfg_num; i++) {
- if (hdr_mode == supported_modes[i].hdr_mode) {
- IMX464->cur_mode = &supported_modes[i];
+ if (hdr_mode == IMX464->support_modes[i].hdr_mode) {
+ IMX464->cur_mode = &IMX464->support_modes[i];
break;
}
}
- IMX464->cur_mode = &supported_modes[0];
+ IMX464->cur_mode = &IMX464->support_modes[0];
IMX464->xvclk = devm_clk_get(dev, "xvclk");
if (IS_ERR(IMX464->xvclk)) {
dev_err(dev, "Failed to get xvclk\n");
@@ -2610,7 +3312,6 @@
pm_runtime_enable(dev);
pm_runtime_idle(dev);
- g_isHCG = false;
#ifdef USED_SYS_DEBUG
add_sysfs_interfaces(dev);
#endif
@@ -2654,14 +3355,14 @@
#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id IMX464_of_match[] = {
- { .compatible = "sony,IMX464" },
+ { .compatible = "sony,imx464" },
{},
};
MODULE_DEVICE_TABLE(of, IMX464_of_match);
#endif
static const struct i2c_device_id IMX464_match_id[] = {
- { "sony,IMX464", 0 },
+ { "sony,imx464", 0 },
{ },
};
--
Gitblit v1.6.2