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/gc8034.c | 596 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 558 insertions(+), 38 deletions(-)
diff --git a/kernel/drivers/media/i2c/gc8034.c b/kernel/drivers/media/i2c/gc8034.c
index 51d5320..bd7e4bd 100644
--- a/kernel/drivers/media/i2c/gc8034.c
+++ b/kernel/drivers/media/i2c/gc8034.c
@@ -13,8 +13,13 @@
* 1. add 2lane support.
* 2. add some debug info.
* 3. adjust gc8034_g_mbus_config function.
+ * V0.0X01.0X07 support get channel info
+ * V0.0X01.0X08
+ * 1. default support 2lane full 30fps.
+ * 2. default support rk otp spec.
+ * V0.0X01.0X09 adjust supply sequence to suit spec
*/
-
+//#define DEBUG
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/delay.h>
@@ -39,8 +44,10 @@
#include <media/v4l2-subdev.h>
#include <linux/pinctrl/consumer.h>
#include <linux/slab.h>
+#include <linux/of_graph.h>
+#include "otp_eeprom.h"
-#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x06)
+#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x09)
#ifndef V4L2_CID_DIGITAL_GAIN
#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
@@ -49,6 +56,7 @@
#define GC8034_LANES 4
#define GC8034_BITS_PER_SAMPLE 10
#define GC8034_MIPI_FREQ_336MHZ 336000000U
+#define GC8034_MIPI_FREQ_634MHZ 634000000U
/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
#define GC8034_PIXEL_RATE 288000000
@@ -92,15 +100,20 @@
#define GC8034_NAME "gc8034"
#define GC8034_MEDIA_BUS_FMT MEDIA_BUS_FMT_SRGGB10_1X10
+/* use RK_OTP or old mode */
+#define RK_OTP
+/* choose 2lane support full 30fps or 15fps */
+#define GC8034_2LANE_30FPS
+
static const char * const gc8034_supply_names[] = {
- "avdd", /* Analog power */
"dovdd", /* Digital I/O power */
"dvdd", /* Digital core power */
+ "avdd", /* Analog power */
};
-static const struct regval *gc8034_global_regs;
#define GC8034_NUM_SUPPLIES ARRAY_SIZE(gc8034_supply_names)
+#ifndef RK_OTP
struct gc8034_dd {
u16 x;
u16 y;
@@ -145,6 +158,7 @@
{0xd0, "CK8401"},
{0x00, "Unknown"}
};
+#endif
struct regval {
u8 addr;
@@ -158,7 +172,10 @@
u32 hts_def;
u32 vts_def;
u32 exp_def;
+ u32 mipi_freq_idx;
+ const struct regval *global_reg_list;
const struct regval *reg_list;
+ u32 vc[PAD_MAX];
};
struct gc8034 {
@@ -192,7 +209,11 @@
const char *module_name;
const char *len_name;
u32 Dgain_ratio;
+#ifdef RK_OTP
+ struct otp_info *otp;
+#else
struct gc8034_otp_info *otp;
+#endif
struct rkmodule_inf module_inf;
struct rkmodule_awb_cfg awb_cfg;
};
@@ -244,6 +265,217 @@
* Xclk 24Mhz
*/
static const struct regval gc8034_global_regs_2lane[] = {
+#ifdef GC8034_2LANE_30FPS
+ /* SYS */
+ {0xf2, 0x00},
+ {0xf4, 0x90},
+ {0xf5, 0x3d},
+ {0xf6, 0x44},
+ {0xf8, 0x63},
+ {0xfa, 0x42},
+ {0xf9, 0x00},
+ {0xf7, 0x95},
+ {0xfc, 0x00},
+ {0xfc, 0x00},
+ {0xfc, 0xea},
+ {0xfe, 0x03},
+ {0x03, 0x9a},
+ {0xfc, 0xee},
+ {0xfe, 0x00},
+ {0x88, 0x03},
+
+ /*Cisctl&Analog*/
+ {0xfe, 0x00},
+ {0x03, 0x08},
+ {0x04, 0xc6},
+ {0x05, 0x02},
+ {0x06, 0x16},
+ {0x07, 0x00},
+ {0x08, 0x10},
+ {0x0a, 0x3a}, //row start
+ {0x0b, 0x00},
+ {0x0c, 0x04}, //col start
+ {0x0d, 0x09},
+ {0x0e, 0xa0}, //win_height 2464
+ {0x0f, 0x0c},
+ {0x10, 0xd4}, //win_width 3284
+ {0x17, GC8034_MIRROR},
+ {0x18, 0x02},
+ {0x19, 0x17},
+ {0x1e, 0x50},
+ {0x1f, 0x80},
+ {0x21, 0x4c},
+ {0x25, 0x00},
+ {0x28, 0x4a},
+ {0x2d, 0x89},
+ {0xca, 0x02},
+ {0xcb, 0x00},
+ {0xcc, 0x39},
+ {0xce, 0xd0},
+ {0xcf, 0x93},
+ {0xd0, 0x1b},
+ {0xd1, 0xaa},
+ {0xd2, 0xcb},
+ {0xd8, 0x40},
+ {0xd9, 0xff},
+ {0xda, 0x0e},
+ {0xdb, 0xb0},
+ {0xdc, 0x0e},
+ {0xde, 0x08},
+ {0xe4, 0xc6},
+ {0xe5, 0x08},
+ {0xe6, 0x10},
+ {0xed, 0x2a},
+ {0xfe, 0x02},
+ {0x59, 0x02},
+ {0x5a, 0x04},
+ {0x5b, 0x08},
+ {0x5c, 0x20},
+ {0xfe, 0x00},
+ {0x1a, 0x09},
+ {0x1d, 0x13},
+ {0xfe, 0x10},
+ {0xfe, 0x00},
+ {0xfe, 0x10},
+ {0xfe, 0x00},
+
+ /* Gamma */
+ {0xfe, 0x00},
+ {0x20, 0x54},
+ {0x33, 0x82},
+ {0xfe, 0x01},
+ {0xdf, 0x06},
+ {0xe7, 0x18},
+ {0xe8, 0x20},
+ {0xe9, 0x16},
+ {0xea, 0x17},
+ {0xeb, 0x50},
+ {0xec, 0x6c},
+ {0xed, 0x9b},
+ {0xee, 0xd8},
+
+ /*ISP*/
+ {0xfe, 0x00},
+ {0x80, 0x13},
+ {0x84, 0x01},
+ {0x89, 0x03},
+ {0x8d, 0x03},
+ {0x8f, 0x14},
+ {0xad, 0x00},
+ {0x66, 0x0c},
+ {0xbc, 0x09},
+ {0xc2, 0x7f},
+ {0xc3, 0xff},
+
+ /*Crop window*/
+ {0x90, 0x01},
+ {0x92, FULL_STARTY},
+ {0x94, FULL_STARTX},
+ {0x95, 0x09},
+ {0x96, 0x90},
+ {0x97, 0x0c},
+ {0x98, 0xc0},
+
+ /*Gain*/
+ {0xb0, 0x90},
+ {0xb1, 0x01},
+ {0xb2, 0x00},
+ {0xb6, 0x00},
+
+ /*BLK*/
+ {0xfe, 0x00},
+ {0x40, 0x22},
+ {0x41, 0x20},
+ {0x42, 0x02},
+ {0x43, 0x08},
+ {0x4e, 0x0f},
+ {0x4f, 0xf0},
+ {0x58, 0x80},
+ {0x59, 0x80},
+ {0x5a, 0x80},
+ {0x5b, 0x80},
+ {0x5c, 0x00},
+ {0x5d, 0x00},
+ {0x5e, 0x00},
+ {0x5f, 0x00},
+ {0x6b, 0x01},
+ {0x6c, 0x00},
+ {0x6d, 0x0c},
+
+ /*WB offset*/
+ {0xfe, 0x01},
+ {0xbf, 0x40},
+
+ /*Dark Sun*/
+ {0xfe, 0x01},
+ {0x68, 0x77},
+
+ /*DPC*/
+ {0xfe, 0x01},
+ {0x60, 0x00},
+ {0x61, 0x10},
+ {0x62, 0x60},
+ {0x63, 0x30},
+ {0x64, 0x00},
+
+ /* LSC */
+ {0xfe, 0x01},
+ {0xa8, 0x60},
+ {0xa2, 0xd1},
+ {0xc8, 0x57},
+ {0xa1, 0xb8},
+ {0xa3, 0x91},
+ {0xc0, 0x50},
+ {0xd0, 0x05},
+ {0xd1, 0xb2},
+ {0xd2, 0x1f},
+ {0xd3, 0x00},
+ {0xd4, 0x00},
+ {0xd5, 0x00},
+ {0xd6, 0x00},
+ {0xd7, 0x00},
+ {0xd8, 0x00},
+ {0xd9, 0x00},
+ {0xa4, 0x10},
+ {0xa5, 0x20},
+ {0xa6, 0x60},
+ {0xa7, 0x80},
+ {0xab, 0x18},
+ {0xc7, 0xc0},
+
+ /*ABB*/
+ {0xfe, 0x01},
+ {0x20, 0x02},
+ {0x21, 0x02},
+ {0x23, 0x42},
+
+ /*MIPI*/
+ {0xfe, 0x03},
+ {0x01, 0x07},
+ {0x02, 0x04},
+ {0x04, 0x80},
+ {0x11, 0x2b},
+ {0x12, 0xf0}, //lwc 3264*5/4
+ {0x13, 0x0f},
+ {0x15, 0x10}, //LP
+ {0x16, 0x29},
+ {0x17, 0xff},
+ {0x18, 0x01},
+ {0x19, 0xaa},
+ {0x1a, 0x02},
+ {0x21, 0x0c},
+ {0x22, 0x0e},
+ {0x23, 0x45},
+ {0x24, 0x01},
+ {0x25, 0x1c},
+ {0x26, 0x0b},
+ {0x29, 0x0e},
+ {0x2a, 0x1d},
+ {0x2b, 0x0b},
+ {0xfe, 0x00},
+ //{0x3f, 0x91},
+ {0x3f, 0x00},
+#else
/*SYS*/
{0xf2, 0x00},
{0xf4, 0x80},
@@ -433,10 +665,11 @@
{0xfe, 0x00},
//{0x3f, 0x91},
{0x3f, 0x00},
-
+#endif
{REG_NULL, 0x00},
};
+#ifndef GC8034_2LANE_30FPS
/*
* Xclk 24Mhz
* max_framerate 30fps
@@ -507,6 +740,7 @@
{REG_NULL, 0x00},
};
+#endif
/*
* Xclk 24Mhz
@@ -514,6 +748,72 @@
* mipi_datarate per lane 672Mbps
*/
static const struct regval gc8034_3264x2448_regs_2lane[] = {
+#ifdef GC8034_2LANE_30FPS
+ /* SYS */
+ {0xf2, 0x00},
+ {0xf4, 0x90},
+ {0xf5, 0x3d},
+ {0xf6, 0x44},
+ {0xf8, 0x63},
+ {0xfa, 0x42},
+ {0xf9, 0x00},
+ {0xf7, 0x95},
+ {0xfc, 0x00},
+ {0xfc, 0x00},
+ {0xfc, 0xea},
+ {0xfe, 0x03},
+ {0x03, 0x9a},
+ {0xfc, 0xee},
+ {0xfe, 0x00},
+ {0x3f, 0x00},
+ {0xfe, 0x10},
+ {0xfe, 0x00},
+ {0xfe, 0x10},
+ {0xfe, 0x00},
+
+ /* ISP */
+ {0xfe, 0x00},
+ {0x80, 0x13},
+ {0xad, 0x00},
+ {0x66, 0x0c},
+ {0xbc, 0x06},
+
+ /* Crop window */
+ {0x90, 0x01},
+ {0x92, FULL_STARTY},
+ {0x94, FULL_STARTX},
+ {0x95, 0x09},
+ {0x96, 0x90},
+ {0x97, 0x0c},
+ {0x98, 0xc0},
+
+ /* MIPI */
+ {0xfe, 0x03},
+ {0x01, 0x07},
+ {0x02, 0x04},
+ {0x04, 0x80},
+ {0x11, 0x2b},
+ {0x12, 0xf0}, //lwc 3264*5/4
+ {0x13, 0x0f},
+ {0x15, 0x10}, //LP
+ {0x16, 0x29},
+ {0x17, 0xff},
+ {0x18, 0x01},
+ {0x19, 0xaa},
+ {0x1a, 0x02},
+ {0x21, 0x0c},
+ {0x22, 0x0c},
+ {0x23, 0x56},
+ {0x24, 0x00},
+ {0x25, 0x1c},
+ {0x26, 0x0b},
+ {0x29, 0x0e},
+ {0x2a, 0x1d},
+ {0x2b, 0x0b},
+ {0xfe, 0x00},
+ //{0x3f, 0x91},
+ {0x3f, 0x00},
+#else
/*SYS*/
{0xf2, 0x00},
{0xf4, 0x80},
@@ -570,6 +870,7 @@
{0xfe, 0x00},
//{0x3f, 0x91},
{0x3f, 0x00},
+#endif
{REG_NULL, 0x00},
};
@@ -843,6 +1144,23 @@
};
static const struct gc8034_mode supported_modes_2lane[] = {
+#ifdef GC8034_2LANE_30FPS
+ {
+ .width = 3264,
+ .height = 2448,
+ .max_fps = {
+ .numerator = 10000,
+ .denominator = 300000,
+ },
+ .exp_def = 0x0900,
+ .hts_def = 0x0858 * 2,
+ .vts_def = 0x09c0,
+ .mipi_freq_idx = 1,
+ .global_reg_list = gc8034_global_regs_2lane,
+ .reg_list = gc8034_3264x2448_regs_2lane,
+ .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
+ },
+#else
{
.width = 3264,
.height = 2448,
@@ -853,7 +1171,10 @@
.exp_def = 0x09a0,
.hts_def = 0x0858 * 2,
.vts_def = 0x09c4,
+ .mipi_freq_idx = 0,
+ .global_reg_list = gc8034_global_regs_2lane,
.reg_list = gc8034_3264x2448_regs_2lane,
+ .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
},
{
.width = 1632,
@@ -865,8 +1186,12 @@
.exp_def = 0x09a0,
.hts_def = 0x0858 * 2,
.vts_def = 0x09c4,
+ .mipi_freq_idx = 0,
+ .global_reg_list = gc8034_global_regs_2lane,
.reg_list = gc8034_1632x1224_regs_2lane,
+ .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
},
+#endif
};
static const struct gc8034_mode supported_modes_4lane[] = {
@@ -880,7 +1205,10 @@
.exp_def = 0x08c6,
.hts_def = 0x10b0,
.vts_def = 0x09c0,
+ .mipi_freq_idx = 0,
+ .global_reg_list = gc8034_global_regs_4lane,
.reg_list = gc8034_3264x2448_regs_4lane,
+ .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
},
};
@@ -888,6 +1216,7 @@
static const s64 link_freq_menu_items[] = {
GC8034_MIPI_FREQ_336MHZ,
+ GC8034_MIPI_FREQ_634MHZ
};
/* Write registers up to 4 at a time */
@@ -1017,8 +1346,8 @@
__v4l2_ctrl_modify_range(gc8034->vblank, vblank_def,
GC8034_VTS_MAX - mode->height,
1, vblank_def);
- __v4l2_ctrl_s_ctrl(gc8034->link_freq,
- link_freq_menu_items[0]);
+ __v4l2_ctrl_s_ctrl(gc8034->vblank, vblank_def);
+ __v4l2_ctrl_s_ctrl(gc8034->link_freq, mode->mipi_freq_idx);
}
mutex_unlock(&gc8034->mutex);
@@ -1089,13 +1418,92 @@
struct gc8034 *gc8034 = to_gc8034(sd);
const struct gc8034_mode *mode = gc8034->cur_mode;
- mutex_lock(&gc8034->mutex);
fi->interval = mode->max_fps;
- mutex_unlock(&gc8034->mutex);
return 0;
}
+#ifdef RK_OTP
+static void gc8034_get_otp(struct otp_info *otp,
+ struct rkmodule_inf *inf)
+{
+ u32 i, j;
+ u32 w, h;
+
+ /* awb */
+ if (otp->awb_data.flag) {
+ inf->awb.flag = 1;
+ inf->awb.r_value = otp->awb_data.r_ratio;
+ inf->awb.b_value = otp->awb_data.b_ratio;
+ inf->awb.gr_value = otp->awb_data.g_ratio;
+ inf->awb.gb_value = 0x0;
+
+ inf->awb.golden_r_value = otp->awb_data.r_golden;
+ inf->awb.golden_b_value = otp->awb_data.b_golden;
+ inf->awb.golden_gr_value = otp->awb_data.g_golden;
+ inf->awb.golden_gb_value = 0x0;
+ }
+
+ /* lsc */
+ if (otp->lsc_data.flag) {
+ inf->lsc.flag = 1;
+ inf->lsc.width = otp->basic_data.size.width;
+ inf->lsc.height = otp->basic_data.size.height;
+ inf->lsc.table_size = otp->lsc_data.table_size;
+
+ for (i = 0; i < 289; i++) {
+ inf->lsc.lsc_r[i] = (otp->lsc_data.data[i * 2] << 8) |
+ otp->lsc_data.data[i * 2 + 1];
+ inf->lsc.lsc_gr[i] = (otp->lsc_data.data[i * 2 + 578] << 8) |
+ otp->lsc_data.data[i * 2 + 579];
+ inf->lsc.lsc_gb[i] = (otp->lsc_data.data[i * 2 + 1156] << 8) |
+ otp->lsc_data.data[i * 2 + 1157];
+ inf->lsc.lsc_b[i] = (otp->lsc_data.data[i * 2 + 1734] << 8) |
+ otp->lsc_data.data[i * 2 + 1735];
+ }
+ }
+
+ /* pdaf */
+ if (otp->pdaf_data.flag) {
+ inf->pdaf.flag = 1;
+ inf->pdaf.gainmap_width = otp->pdaf_data.gainmap_width;
+ inf->pdaf.gainmap_height = otp->pdaf_data.gainmap_height;
+ inf->pdaf.pd_offset = otp->pdaf_data.pd_offset;
+ inf->pdaf.dcc_mode = otp->pdaf_data.dcc_mode;
+ inf->pdaf.dcc_dir = otp->pdaf_data.dcc_dir;
+ inf->pdaf.dccmap_width = otp->pdaf_data.dccmap_width;
+ inf->pdaf.dccmap_height = otp->pdaf_data.dccmap_height;
+ w = otp->pdaf_data.gainmap_width;
+ h = otp->pdaf_data.gainmap_height;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ inf->pdaf.gainmap[i * w + j] =
+ (otp->pdaf_data.gainmap[(i * w + j) * 2] << 8) |
+ otp->pdaf_data.gainmap[(i * w + j) * 2 + 1];
+ }
+ }
+ w = otp->pdaf_data.dccmap_width;
+ h = otp->pdaf_data.dccmap_height;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ inf->pdaf.dccmap[i * w + j] =
+ (otp->pdaf_data.dccmap[(i * w + j) * 2] << 8) |
+ otp->pdaf_data.dccmap[(i * w + j) * 2 + 1];
+ }
+ }
+ }
+
+ /* af */
+ if (otp->af_data.flag) {
+ inf->af.flag = 1;
+ inf->af.dir_cnt = 1;
+ inf->af.af_otp[0].vcm_start = otp->af_data.af_inf;
+ inf->af.af_otp[0].vcm_end = otp->af_data.af_macro;
+ inf->af.af_otp[0].vcm_dir = 0;
+ }
+
+}
+#else
#define DD_WIDTH 3284
#define DD_HEIGHT 2464
@@ -1605,11 +2013,16 @@
inf->af.af_otp[0].vcm_dir = otp->vcm_dir;
}
}
+#endif
static void gc8034_get_module_inf(struct gc8034 *gc8034,
struct rkmodule_inf *inf)
{
+#ifdef RK_OTP
+ struct otp_info *otp = gc8034->otp;
+#else
struct gc8034_otp_info *otp = gc8034->otp;
+#endif
strlcpy(inf->base.sensor,
GC8034_NAME,
@@ -1632,11 +2045,23 @@
mutex_unlock(&gc8034->mutex);
}
+static int gc8034_get_channel_info(struct gc8034 *gc8034, struct rkmodule_channel_info *ch_info)
+{
+ if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX)
+ return -EINVAL;
+ ch_info->vc = gc8034->cur_mode->vc[ch_info->index];
+ ch_info->width = gc8034->cur_mode->width;
+ ch_info->height = gc8034->cur_mode->height;
+ ch_info->bus_fmt = GC8034_MEDIA_BUS_FMT;
+ return 0;
+}
+
static long gc8034_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
struct gc8034 *gc8034 = to_gc8034(sd);
long ret = 0;
u32 stream = 0;
+ struct rkmodule_channel_info *ch_info;
switch (cmd) {
case RKMODULE_GET_MODULE_INFO:
@@ -1671,6 +2096,10 @@
GC8034_MODE_SW_STANDBY);
}
break;
+ case RKMODULE_GET_CHANNEL_INFO:
+ ch_info = (struct rkmodule_channel_info *)arg;
+ ret = gc8034_get_channel_info(gc8034, ch_info);
+ break;
default:
ret = -ENOTTY;
break;
@@ -1688,6 +2117,7 @@
struct rkmodule_awb_cfg *cfg;
long ret = 0;
u32 stream = 0;
+ struct rkmodule_channel_info *ch_info;
switch (cmd) {
case RKMODULE_GET_MODULE_INFO:
@@ -1698,8 +2128,11 @@
}
ret = gc8034_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:
@@ -1712,12 +2145,31 @@
ret = copy_from_user(cfg, up, sizeof(*cfg));
if (!ret)
ret = gc8034_ioctl(sd, cmd, cfg);
+ else
+ ret = -EFAULT;
kfree(cfg);
break;
case RKMODULE_SET_QUICK_STREAM:
ret = copy_from_user(&stream, up, sizeof(u32));
if (!ret)
ret = gc8034_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 = gc8034_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;
default:
ret = -ENOTTY;
@@ -1728,6 +2180,7 @@
}
#endif
+#ifndef RK_OTP
/*--------------------------------------------------------------------------*/
static int gc8034_apply_otp(struct gc8034 *gc8034)
{
@@ -1908,11 +2361,12 @@
}
return 0;
}
+#endif
static int __gc8034_start_stream(struct gc8034 *gc8034)
{
int ret;
-
+#ifndef RK_OTP
if (gc8034->otp) {
ret = gc8034_otp_enable(gc8034);
gc8034_check_prsel(gc8034);
@@ -1922,6 +2376,7 @@
if (ret)
return ret;
}
+#endif
ret = gc8034_write_array(gc8034->client, gc8034->cur_mode->reg_list);
if (ret)
return ret;
@@ -2006,6 +2461,7 @@
{
struct gc8034 *gc8034 = to_gc8034(sd);
struct i2c_client *client = gc8034->client;
+ const struct gc8034_mode *mode = gc8034->cur_mode;
int ret = 0;
dev_info(&client->dev, "%s(%d) on(%d)\n", __func__, __LINE__, on);
@@ -2022,7 +2478,7 @@
goto unlock_and_return;
}
- ret = gc8034_write_array(gc8034->client, gc8034_global_regs);
+ ret = gc8034_write_array(gc8034->client, mode->global_reg_list);
if (ret) {
v4l2_err(sd, "could not set init registers\n");
pm_runtime_put_noidle(&client->dev);
@@ -2047,6 +2503,31 @@
return DIV_ROUND_UP(cycles, GC8034_XVCLK_FREQ / 1000 / 1000);
}
+static int gc8034_enable_regulators(struct gc8034 *gc8034,
+ struct regulator_bulk_data *consumers)
+{
+ int i, j;
+ int ret = 0;
+ struct device *dev = &gc8034->client->dev;
+ int num_consumers = GC8034_NUM_SUPPLIES;
+
+ for (i = 0; i < num_consumers; i++) {
+
+ ret = regulator_enable(consumers[i].consumer);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable regulator: %s\n",
+ consumers[i].supply);
+ goto err;
+ }
+ }
+ return 0;
+err:
+ for (j = 0; j < i; j++)
+ regulator_disable(consumers[j].consumer);
+
+ return ret;
+}
+
static int __gc8034_power_on(struct gc8034 *gc8034)
{
int ret;
@@ -2069,27 +2550,32 @@
dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
if (clk_get_rate(gc8034->xvclk) != GC8034_XVCLK_FREQ)
dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
- ret = clk_prepare_enable(gc8034->xvclk);
- if (ret < 0) {
- dev_err(dev, "Failed to enable xvclk\n");
- return ret;
- }
+
if (!IS_ERR(gc8034->reset_gpio))
gpiod_set_value_cansleep(gc8034->reset_gpio, 1);
- ret = regulator_bulk_enable(GC8034_NUM_SUPPLIES, gc8034->supplies);
+ ret = gc8034_enable_regulators(gc8034, gc8034->supplies);
if (ret < 0) {
dev_err(dev, "Failed to enable regulators\n");
goto disable_clk;
}
+ usleep_range(100, 200);
+ ret = clk_prepare_enable(gc8034->xvclk);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable xvclk\n");
+ return ret;
+ }
+
usleep_range(1000, 1100);
+ if (!IS_ERR(gc8034->pwdn_gpio))
+ gpiod_set_value_cansleep(gc8034->pwdn_gpio, 0);
+
+ usleep_range(500, 1000);
if (!IS_ERR(gc8034->reset_gpio))
gpiod_set_value_cansleep(gc8034->reset_gpio, 0);
- usleep_range(500, 1000);
- if (!IS_ERR(gc8034->pwdn_gpio))
- gpiod_set_value_cansleep(gc8034->pwdn_gpio, 0);
+ usleep_range(6000, 7000);
/* 8192 cycles prior to first SCCB transaction */
delay_us = gc8034_cal_delay(8192);
@@ -2109,9 +2595,11 @@
if (!IS_ERR(gc8034->pwdn_gpio))
gpiod_set_value_cansleep(gc8034->pwdn_gpio, 1);
- clk_disable_unprepare(gc8034->xvclk);
+
if (!IS_ERR(gc8034->reset_gpio))
gpiod_set_value_cansleep(gc8034->reset_gpio, 1);
+
+ clk_disable_unprepare(gc8034->xvclk);
if (!IS_ERR_OR_NULL(gc8034->pins_sleep)) {
ret = pinctrl_select_state(gc8034->pinctrl,
gc8034->pins_sleep);
@@ -2124,7 +2612,7 @@
regulator_bulk_disable(GC8034_NUM_SUPPLIES, gc8034->supplies);
}
-static int gc8034_runtime_resume(struct device *dev)
+static int __maybe_unused gc8034_runtime_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
@@ -2133,7 +2621,7 @@
return __gc8034_power_on(gc8034);
}
-static int gc8034_runtime_suspend(struct device *dev)
+static int __maybe_unused gc8034_runtime_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
@@ -2175,16 +2663,14 @@
if (fie->index >= gc8034->cfg_num)
return -EINVAL;
- if (fie->code != GC8034_MEDIA_BUS_FMT)
- return -EINVAL;
-
+ fie->code = GC8034_MEDIA_BUS_FMT;
fie->width = supported_modes[fie->index].width;
fie->height = supported_modes[fie->index].height;
fie->interval = supported_modes[fie->index].max_fps;
return 0;
}
-static int gc8034_g_mbus_config(struct v4l2_subdev *sd,
+static int gc8034_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
struct v4l2_mbus_config *config)
{
struct gc8034 *sensor = to_gc8034(sd);
@@ -2193,12 +2679,12 @@
dev_info(dev, "%s(%d) enter!\n", __func__, __LINE__);
if (2 == sensor->lane_num) {
- config->type = V4L2_MBUS_CSI2;
+ config->type = V4L2_MBUS_CSI2_DPHY;
config->flags = V4L2_MBUS_CSI2_2_LANE |
V4L2_MBUS_CSI2_CHANNEL_0 |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
} else if (4 == sensor->lane_num) {
- config->type = V4L2_MBUS_CSI2;
+ config->type = V4L2_MBUS_CSI2_DPHY;
config->flags = V4L2_MBUS_CSI2_4_LANE |
V4L2_MBUS_CSI2_CHANNEL_0 |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
@@ -2231,7 +2717,6 @@
static const struct v4l2_subdev_video_ops gc8034_video_ops = {
.s_stream = gc8034_s_stream,
.g_frame_interval = gc8034_g_frame_interval,
- .g_mbus_config = gc8034_g_mbus_config,
};
static const struct v4l2_subdev_pad_ops gc8034_pad_ops = {
@@ -2240,6 +2725,7 @@
.enum_frame_interval = gc8034_enum_frame_interval,
.get_fmt = gc8034_get_fmt,
.set_fmt = gc8034_set_fmt,
+ .get_mbus_config = gc8034_g_mbus_config,
};
static const struct v4l2_subdev_ops gc8034_subdev_ops = {
@@ -2388,15 +2874,15 @@
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
/* 4 least significant bits of expsoure are fractional part */
- dev_info(&client->dev, "set exposure value 0x%x\n", ctrl->val);
+ dev_dbg(&client->dev, "set exposure value 0x%x\n", ctrl->val);
ret = gc8034_set_exposure_reg(gc8034, ctrl->val);
break;
case V4L2_CID_ANALOGUE_GAIN:
- dev_info(&client->dev, "set analog gain value 0x%x\n", ctrl->val);
+ dev_dbg(&client->dev, "set analog gain value 0x%x\n", ctrl->val);
ret = gc8034_set_gain_reg(gc8034, ctrl->val);
break;
case V4L2_CID_VBLANK:
- dev_info(&client->dev, "set vb value 0x%x\n", ctrl->val);
+ dev_dbg(&client->dev, "set vb value 0x%x\n", ctrl->val);
/* VB = VTS - 2448 -36, according android8.1 driver */
temp = ctrl->val + gc8034->cur_mode->height - 2448 - 36;
ret = gc8034_write_reg(gc8034->client,
@@ -2440,8 +2926,10 @@
handler->lock = &gc8034->mutex;
gc8034->link_freq = v4l2_ctrl_new_int_menu(handler, NULL,
- V4L2_CID_LINK_FREQ, 0, 0,
+ V4L2_CID_LINK_FREQ,
+ ARRAY_SIZE(link_freq_menu_items) - 1, 0,
link_freq_menu_items);
+ v4l2_ctrl_s_ctrl(gc8034->link_freq, mode->mipi_freq_idx);
v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,
0, gc8034->pixel_rate, 1, gc8034->pixel_rate);
@@ -2542,7 +3030,6 @@
gc8034->cur_mode = &supported_modes_4lane[0];
supported_modes = supported_modes_4lane;
gc8034->cfg_num = ARRAY_SIZE(supported_modes_4lane);
- gc8034_global_regs = gc8034_global_regs_4lane;
/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
fps = DIV_ROUND_CLOSEST(gc8034->cur_mode->max_fps.denominator,
gc8034->cur_mode->max_fps.numerator);
@@ -2555,7 +3042,6 @@
gc8034->cur_mode = &supported_modes_2lane[0];
supported_modes = supported_modes_2lane;
gc8034->cfg_num = ARRAY_SIZE(supported_modes_2lane);
- gc8034_global_regs = gc8034_global_regs_2lane;
/*pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
fps = DIV_ROUND_CLOSEST(gc8034->cur_mode->max_fps.denominator,
gc8034->cur_mode->max_fps.numerator);
@@ -2580,6 +3066,10 @@
struct v4l2_subdev *sd;
char facing[2];
int ret;
+ struct device_node *eeprom_ctrl_node;
+ struct i2c_client *eeprom_ctrl_client;
+ struct v4l2_subdev *eeprom_ctrl;
+ struct otp_info *otp_ptr;
dev_info(dev, "driver version: %02x.%02x.%02x",
DRIVER_VERSION >> 16,
@@ -2661,10 +3151,40 @@
ret = gc8034_check_sensor_id(gc8034, client);
if (ret)
goto err_power_off;
-
+#ifdef RK_OTP
+ eeprom_ctrl_node = of_parse_phandle(node, "eeprom-ctrl", 0);
+ if (eeprom_ctrl_node) {
+ eeprom_ctrl_client =
+ of_find_i2c_device_by_node(eeprom_ctrl_node);
+ of_node_put(eeprom_ctrl_node);
+ if (IS_ERR_OR_NULL(eeprom_ctrl_client)) {
+ dev_err(dev, "can not get node\n");
+ goto continue_probe;
+ }
+ eeprom_ctrl = i2c_get_clientdata(eeprom_ctrl_client);
+ if (IS_ERR_OR_NULL(eeprom_ctrl)) {
+ dev_err(dev, "can not get eeprom i2c client\n");
+ } else {
+ otp_ptr = devm_kzalloc(dev, sizeof(*otp_ptr), GFP_KERNEL);
+ if (!otp_ptr)
+ return -ENOMEM;
+ ret = v4l2_subdev_call(eeprom_ctrl,
+ core, ioctl, 0, otp_ptr);
+ if (!ret) {
+ gc8034->otp = otp_ptr;
+ } else {
+ gc8034->otp = NULL;
+ devm_kfree(dev, otp_ptr);
+ dev_warn(dev, "can not get otp info, skip!\n");
+ }
+ }
+ }
+continue_probe:
+#else
gc8034_otp_enable(gc8034);
gc8034_otp_read(gc8034);
gc8034_otp_disable(gc8034);
+#endif
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
sd->internal_ops = &gc8034_internal_ops;
--
Gitblit v1.6.2