mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
media: i2c: gc8034: add 2lane full 30fps & rk otp support
Signed-off-by: Wang Panzhenzhuan <randy.wang@rock-chips.com> Change-Id: I215e3fc9442c93450e45f3b06579403fcc9f2d02
This commit is contained in:
committed by
Tao Huang
parent
e21704dc6a
commit
016f705b4c
@@ -13,9 +13,12 @@
|
||||
* 1. add 2lane support.
|
||||
* 2. add some debug info.
|
||||
* 3. adjust gc8034_g_mbus_config function.
|
||||
* V0.0X01.0X06 support get channel info
|
||||
* V0.0X01.0X07 support get channel info
|
||||
* V0.0X01.0X08
|
||||
* 1. default support 2lane full 30fps.
|
||||
* 2. default support rk otp spec.
|
||||
*/
|
||||
|
||||
//#define DEBUG
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
@@ -40,8 +43,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, 0x07)
|
||||
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x08)
|
||||
|
||||
#ifndef V4L2_CID_DIGITAL_GAIN
|
||||
#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
|
||||
@@ -50,6 +55,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
|
||||
@@ -93,15 +99,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 */
|
||||
};
|
||||
|
||||
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;
|
||||
@@ -146,6 +157,7 @@ static const struct gc8034_id_name gc8034_lens_info[] = {
|
||||
{0xd0, "CK8401"},
|
||||
{0x00, "Unknown"}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct regval {
|
||||
u8 addr;
|
||||
@@ -159,6 +171,8 @@ struct gc8034_mode {
|
||||
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];
|
||||
};
|
||||
@@ -194,7 +208,11 @@ struct gc8034 {
|
||||
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;
|
||||
};
|
||||
@@ -246,6 +264,217 @@ struct gc8034 {
|
||||
* 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},
|
||||
@@ -435,10 +664,11 @@ static const struct regval gc8034_global_regs_2lane[] = {
|
||||
{0xfe, 0x00},
|
||||
//{0x3f, 0x91},
|
||||
{0x3f, 0x00},
|
||||
|
||||
#endif
|
||||
{REG_NULL, 0x00},
|
||||
};
|
||||
|
||||
#ifndef GC8034_2LANE_30FPS
|
||||
/*
|
||||
* Xclk 24Mhz
|
||||
* max_framerate 30fps
|
||||
@@ -509,6 +739,7 @@ static const struct regval gc8034_1632x1224_regs_2lane[] = {
|
||||
|
||||
{REG_NULL, 0x00},
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Xclk 24Mhz
|
||||
@@ -516,6 +747,72 @@ static const struct regval gc8034_1632x1224_regs_2lane[] = {
|
||||
* 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},
|
||||
@@ -572,6 +869,7 @@ static const struct regval gc8034_3264x2448_regs_2lane[] = {
|
||||
{0xfe, 0x00},
|
||||
//{0x3f, 0x91},
|
||||
{0x3f, 0x00},
|
||||
#endif
|
||||
{REG_NULL, 0x00},
|
||||
};
|
||||
|
||||
@@ -845,6 +1143,23 @@ static const struct regval gc8034_3264x2448_regs_4lane[] = {
|
||||
};
|
||||
|
||||
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,
|
||||
@@ -855,6 +1170,8 @@ static const struct gc8034_mode supported_modes_2lane[] = {
|
||||
.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,
|
||||
},
|
||||
@@ -868,9 +1185,12 @@ static const struct gc8034_mode supported_modes_2lane[] = {
|
||||
.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[] = {
|
||||
@@ -884,6 +1204,8 @@ static const struct gc8034_mode supported_modes_4lane[] = {
|
||||
.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,
|
||||
},
|
||||
@@ -893,6 +1215,7 @@ static const struct gc8034_mode *supported_modes;
|
||||
|
||||
static const s64 link_freq_menu_items[] = {
|
||||
GC8034_MIPI_FREQ_336MHZ,
|
||||
GC8034_MIPI_FREQ_634MHZ
|
||||
};
|
||||
|
||||
/* Write registers up to 4 at a time */
|
||||
@@ -1022,8 +1345,8 @@ static int gc8034_set_fmt(struct v4l2_subdev *sd,
|
||||
__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);
|
||||
@@ -1101,6 +1424,86 @@ static int gc8034_g_frame_interval(struct v4l2_subdev *sd,
|
||||
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.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
|
||||
|
||||
@@ -1610,11 +2013,16 @@ static void gc8034_get_otp(struct gc8034_otp_info *otp,
|
||||
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,
|
||||
@@ -1772,6 +2180,7 @@ static long gc8034_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef RK_OTP
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int gc8034_apply_otp(struct gc8034 *gc8034)
|
||||
{
|
||||
@@ -1952,11 +2361,12 @@ static int gc8034_apply_otp(struct gc8034 *gc8034)
|
||||
}
|
||||
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);
|
||||
@@ -1966,6 +2376,7 @@ static int __gc8034_start_stream(struct gc8034 *gc8034)
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
ret = gc8034_write_array(gc8034->client, gc8034->cur_mode->reg_list);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -2050,6 +2461,7 @@ static int gc8034_s_power(struct v4l2_subdev *sd, int on)
|
||||
{
|
||||
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);
|
||||
@@ -2066,7 +2478,7 @@ static int gc8034_s_power(struct v4l2_subdev *sd, int on)
|
||||
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);
|
||||
@@ -2432,15 +2844,15 @@ static int gc8034_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
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,
|
||||
@@ -2484,8 +2896,10 @@ static int gc8034_initialize_controls(struct gc8034 *gc8034)
|
||||
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);
|
||||
@@ -2586,7 +3000,6 @@ static int gc8034_parse_of(struct gc8034 *gc8034)
|
||||
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);
|
||||
@@ -2599,7 +3012,6 @@ static int gc8034_parse_of(struct gc8034 *gc8034)
|
||||
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);
|
||||
@@ -2624,6 +3036,10 @@ static int gc8034_probe(struct i2c_client *client,
|
||||
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,
|
||||
@@ -2705,10 +3121,40 @@ static int gc8034_probe(struct i2c_client *client,
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user